Beispiel #1
0
/**
 * Send a raw API call to an elgg api endpoint.
 *
 * @param array  $keys         The api keys.
 * @param string $url          URL of the endpoint.
 * @param array  $call         Associated array of "variable" => "value"
 * @param string $method       GET or POST
 * @param string $post_data    The post data
 * @param string $content_type The content type
 *
 * @return string
 */
function send_api_call(array $keys, $url, array $call, $method = 'GET', $post_data = '', $content_type = 'application/octet-stream')
{
    global $CONFIG;
    $headers = array();
    $encoded_params = array();
    $method = strtoupper($method);
    switch (strtoupper($method)) {
        case 'GET':
        case 'POST':
            break;
        default:
            $msg = elgg_echo('NotImplementedException:CallMethodNotImplemented', array($method));
            throw new NotImplementedException($msg);
    }
    // Time
    $time = time();
    // Nonce
    $nonce = uniqid('');
    // URL encode all the parameters
    foreach ($call as $k => $v) {
        $encoded_params[] = urlencode($k) . '=' . urlencode($v);
    }
    $params = implode('&', $encoded_params);
    // Put together the query string
    $url = $url . "?" . $params;
    // Construct headers
    $posthash = "";
    if ($method == 'POST') {
        $posthash = calculate_posthash($post_data, 'md5');
    }
    if (isset($keys['public']) && isset($keys['private'])) {
        $headers['X-Elgg-apikey'] = $keys['public'];
        $headers['X-Elgg-time'] = $time;
        $headers['X-Elgg-nonce'] = $nonce;
        $headers['X-Elgg-hmac-algo'] = 'sha1';
        $headers['X-Elgg-hmac'] = calculate_hmac('sha1', $time, $nonce, $keys['public'], $keys['private'], $params, $posthash);
    }
    if ($method == 'POST') {
        $headers['X-Elgg-posthash'] = $posthash;
        $headers['X-Elgg-posthash-algo'] = 'md5';
        $headers['Content-type'] = $content_type;
        $headers['Content-Length'] = strlen($post_data);
    }
    // Opt array
    $http_opts = array('method' => $method, 'header' => serialise_api_headers($headers));
    if ($method == 'POST') {
        $http_opts['content'] = $post_data;
    }
    $opts = array('http' => $http_opts);
    // Send context
    $context = stream_context_create($opts);
    // Send the query and get the result and decode.
    elgg_log("APICALL: {$url}");
    $results = file_get_contents($url, false, $context);
    return $results;
}
Beispiel #2
0
/**
 * PAM: Confirm the HMAC signature
 *
 * @return true if success - otherwise throws exception
 *
 * @throws SecurityException
 * @since 1.7.0
 * @access private
 */
function api_auth_hmac()
{
    // Get api header
    $api_header = get_and_validate_api_headers();
    // Pull API user details
    $api_user = get_api_user(elgg_get_site_entity()->guid, $api_header->api_key);
    if (!$api_user) {
        throw new SecurityException(elgg_echo('SecurityException:InvalidAPIKey'), ErrorResult::$RESULT_FAIL_APIKEY_INVALID);
    }
    // Get the secret key
    $secret_key = $api_user->secret;
    // get the query string
    $query = _elgg_services()->request->server->get('REQUEST_URI');
    $query = substr($query, strpos($query, '?') + 1);
    // calculate expected HMAC
    $hmac = calculate_hmac($api_header->hmac_algo, $api_header->time, $api_header->nonce, $api_header->api_key, $secret_key, $query, $api_header->method == 'POST' ? $api_header->posthash : "");
    if ($api_header->hmac !== $hmac) {
        throw new SecurityException("HMAC is invalid.  {$api_header->hmac} != [calc]{$hmac}");
    }
    // Now make sure this is not a replay
    if (cache_hmac_check_replay($hmac)) {
        throw new SecurityException(elgg_echo('SecurityException:DupePacket'));
    }
    // Validate post data
    if ($api_header->method == "POST") {
        $postdata = get_post_data();
        $calculated_posthash = calculate_posthash($postdata, $api_header->posthash_algo);
        if (strcmp($api_header->posthash, $calculated_posthash) != 0) {
            $msg = elgg_echo('SecurityException:InvalidPostHash', array($calculated_posthash, $api_header->posthash));
            throw new SecurityException($msg);
        }
    }
    return true;
}
Beispiel #3
0
/**
 * Send a raw API call to an elgg api endpoint.
 *
 * @param array $keys The api keys.
 * @param string $url URL of the endpoint.
 * @param array $call Associated array of "variable" => "value"
 * @param string $method GET or POST
 * @param string $post_data The post data
 * @param string $content_type The content type
 * @return stdClass The unserialised response object
 */
function send_api_call(array $keys, $url, array $call, $method = 'GET', $post_data = '', $content_type = 'application/octet-stream')
{
    global $APICLIENT_LAST_CALL, $APICLIENT_LAST_CALL_RAW, $APICLIENT_LAST_ERROR, $CONFIG;
    $headers = array();
    $encoded_params = array();
    $method = strtoupper($method);
    switch (strtoupper($method)) {
        case 'GET':
        case 'POST':
            break;
        default:
            throw new NotImplementedException(sprintf(elgg_echo('NotImplementedException:CallMethodNotImplemented'), $method));
    }
    // Time
    $time = microtime(true);
    // URL encode all the parameters, ensuring auth_token (if present) is at the end!
    foreach ($call as $k => $v) {
        if ($k != 'auth_token') {
            $encoded_params[] = urlencode($k) . '=' . urlencode($v);
        }
    }
    if ($call['auth_token']) {
        $encoded_params[] = urlencode('auth_token') . '=' . urlencode($call['auth_token']);
    }
    $params = implode('&', $encoded_params);
    // Put together the query string
    $url = $url . "?" . $params;
    // Construct headers
    $posthash = "";
    if ($method == 'POST') {
        $posthash = calculate_posthash($post_data, 'md5');
    }
    if (isset($keys['public']) && isset($keys['private'])) {
        $headers['X-Elgg-apikey'] = $keys['public'];
        $headers['X-Elgg-time'] = $time;
        $headers['X-Elgg-hmac-algo'] = 'sha1';
        $headers['X-Elgg-hmac'] = calculate_hmac('sha1', $time, $keys['public'], $keys['private'], $params, $posthash);
    }
    if ($method == 'POST') {
        $headers['X-Elgg-posthash'] = $posthash;
        $headers['X-Elgg-posthash-algo'] = 'md5';
        $headers['Content-type'] = $content_type;
        $headers['Content-Length'] = strlen($post_data);
    }
    // Opt array
    $http_opts = array('method' => $method, 'header' => serialise_api_headers($headers));
    if ($method == 'POST') {
        $http_opts['content'] = $post_data;
    }
    $opts = array('http' => $http_opts);
    // Send context
    $context = stream_context_create($opts);
    // Send the query and get the result and decode.
    if (isset($CONFIG->debug) && $CONFIG->debug) {
        error_log("APICALL: {$url}");
    }
    $APICLIENT_LAST_CALL_RAW = file_get_contents($url, false, $context);
    $APICLIENT_LAST_CALL = unserialize($APICLIENT_LAST_CALL_RAW);
    if ($APICLIENT_LAST_CALL && $APICLIENT_LAST_CALL->status != 0) {
        $APICLIENT_LAST_ERROR = $APICLIENT_LAST_CALL;
    }
    return $APICLIENT_LAST_CALL;
}