/** * PAM: Confirm the HMAC signature * * @return true if success - otherwise throws exception * * @throws SecurityException * @since 1.7.0 * @access private */ function api_auth_hmac() { global $CONFIG; // Get api header $api_header = get_and_validate_api_headers(); // Pull API user details $api_user = get_api_user($CONFIG->site_id, $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 = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], '?') + 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; }
/** * Secure authentication through headers and HMAC. */ function pam_auth_hmac($credentials = NULL) { global $CONFIG; $api_header = get_and_validate_api_headers(); // Get api header $api_user = get_api_user($CONFIG->site_id, $api_header->api_key); // Pull API user details if ($api_user) { // Get the secret key $secret_key = $api_user->secret; // Serialise parameters $encoded_params = array(); foreach ($api_header->get_variables as $k => $v) { $encoded_params[] = urlencode($k) . '=' . urlencode($v); } $params = implode('&', $encoded_params); // Validate HMAC $hmac = calculate_hmac($api_header->hmac_algo, $api_header->time, $api_header->api_key, $secret_key, $params, $api_header->method == 'POST' ? $api_header->posthash : ""); if (strcmp($api_header->hmac, $hmac) == 0 && $api_header->hmac && $hmac) { // Now make sure this is not a replay if (!cache_hmac_check_replay($hmac)) { // 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) { throw new SecurityException(sprintf(elgg_echo('SecurityException:InvalidPostHash'), $calculated_posthash, $api_header->posthash)); } } // If we've passed all the checks so far then we can be reasonably certain that the request is authentic, so return this fact to the PAM engine. return true; } else { throw new SecurityException(elgg_echo('SecurityException:DupePacket')); } } else { throw new SecurityException("HMAC is invalid. {$api_header->hmac} != [calc]{$hmac} = {$api_header->hmac_algo}(**SECRET KEY**, time:{$api_header->time}, apikey:{$api_header->api_key}, get_vars:{$params}" . ($api_header->method == "POST" ? "posthash:{$api_header->posthash}}" : ")")); } } else { throw new SecurityException(elgg_echo('SecurityException:InvalidAPIKey'), ErrorResult::$RESULT_FAIL_APIKEY_INVALID); } return false; }