diff options
-rw-r--r-- | engine/lib/api.php | 88 | ||||
-rw-r--r-- | engine/lib/pam.php | 44 | ||||
-rw-r--r-- | engine/tests/services/api.php | 2 | ||||
-rw-r--r-- | services/api/rest.php | 6 |
4 files changed, 46 insertions, 94 deletions
diff --git a/engine/lib/api.php b/engine/lib/api.php index 38b93cd3a..5372c0214 100644 --- a/engine/lib/api.php +++ b/engine/lib/api.php @@ -411,7 +411,7 @@ function authenticate_method($method) { // check API authentication if required if ($API_METHODS[$method]["require_api_auth"] == true) { - if (api_authenticate() == false) { + if (pam_authenticate(null, "api") == false) { throw new APIException(elgg_echo('APIException:APIAuthenticationFailed')); } } @@ -426,65 +426,6 @@ function authenticate_method($method) { return true; } -$API_AUTH_HANDLERS = array(); - -/** - * Register an API authorization handler - * - * @param $handler - * @param $importance - * @return bool - */ -function register_api_auth_handler($handler, $importance = "sufficient") { - global $API_AUTH_HANDLERS; - - if (is_callable($handler)) { - $API_AUTH_HANDLERS[$handler] = new stdClass; - - $API_AUTH_HANDLERS[$handler]->handler = $handler; - $API_AUTH_HANDLERS[$handler]->importance = strtolower($importance); - - return true; - } - - return false; -} - -/** - * Authenticate an API method call - * - * @return bool - */ -function api_authenticate() { - global $API_AUTH_HANDLERS; - - $authenticated = false; - - foreach ($API_AUTH_HANDLERS as $k => $v) { - $handler = $v->handler; - $importance = $v->importance; - - try { - // Execute the handler - if ($handler()) { - $authenticated = true; - } else { - // If this is required then abort. - if ($importance == 'required') { - return false; - } - } - } catch (Exception $e) { - // If this is required then abort. - if ($importance == 'required') { - return false; - } - } - } - - return $authenticated; -} - /** * Executes a method. * A method is a function which you have previously exposed using expose_function. @@ -758,7 +699,7 @@ function api_auth_hmac() { // 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); @@ -777,7 +718,7 @@ function api_auth_hmac() { $api_header->time, $api_header->api_key, $secret_key, - $params, + $query, $api_header->method == 'POST' ? $api_header->posthash : ""); @@ -842,7 +783,7 @@ function get_and_validate_api_headers() { } // Basic timecheck, think about making this smaller if we get loads of users and the cache gets really big. - if (($result->time<(microtime(true)-86400.00)) || ($result->time>(microtime(true)+86400.00))) { + if (($result->time<(time()-86400)) || ($result->time>(time()+86400))) { throw new APIException(elgg_echo('APIException:TemporalDrift')); } @@ -899,7 +840,7 @@ function map_api_hash($algo) { * @param $time string String representation of unix time as stored in X-Searunner-time. * @param $api_key string Your api key. * @param $secret string Your secret key. - * @param $get_variables string URLEncoded string representation of the get variable parameters, eg "format=php&method=searunner.test". + * @param $get_variables string URLEncoded string representation of the get variable parameters, eg "method=user&guid=2" * @param $post_hash string Optional sha1 hash of the post data. * @return string The HMAC string. */ @@ -1036,8 +977,11 @@ function pam_auth_usertoken($credentials = NULL) { global $CONFIG; $token = get_input('auth_token'); - - $validated_userid = validate_user_token($token); + if (!$token) { + return false; + } + + $validated_userid = validate_user_token($token, $CONFIG->site_id); if ($validated_userid) { $u = get_entity($validated_userid); @@ -1218,17 +1162,11 @@ function send_api_call(array $keys, $url, array $call, $method = 'GET', $post_da } // Time - $time = microtime(true); + $time = time(); - // URL encode all the parameters, ensuring auth_token (if present) is at the end! + // URL encode all the parameters 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']); + $encoded_params[] = urlencode($k).'='.urlencode($v); } $params = implode('&', $encoded_params); diff --git a/engine/lib/pam.php b/engine/lib/pam.php index 17b10b5cc..590ef9fde 100644 --- a/engine/lib/pam.php +++ b/engine/lib/pam.php @@ -3,12 +3,13 @@ * Elgg Simple PAM library * Contains functions for managing authentication. * This is not a full implementation of PAM. It supports a single facility - * (authentication) and only allows one policy at a time. There are two control - * flags possible for each module: sufficient or required. The entire chain for - * a policy is processed (or until a required module fails). A module fails by - * returning false or throwing an exception. The order that modules are - * processed is determined by the order they are registered. For an example of - * a PAM, see pam_auth_userpass() in sessions.php. + * (authentication) and allows multiple policies (user authentication is the + * default). There are two control flags possible for each module: sufficient + * or required. The entire chain for a policy is processed (or until a + * required module fails). A module fails by returning false or throwing an + * exception. The order that modules are processed is determined by the order + * they are registered. For an example of a PAM, see pam_auth_userpass() in + * sessions.php. * * For more information on PAMs see: * http://www.freebsd.org/doc/en/articles/pam/index.html @@ -27,16 +28,23 @@ $_PAM_HANDLERS_MSG = array(); * * @param string $handler The handler function in the format * pam_handler($credentials = NULL); - * @param string $importance The importance - "sufficient" or "required" + * @param string $importance The importance - "sufficient" (default) or "required" + * @param string $policy - the policy type, default is "user" + * @return boolean */ -function register_pam_handler($handler, $importance = "sufficient") { +function register_pam_handler($handler, $importance = "sufficient", $policy = "user") { global $_PAM_HANDLERS; + // setup array for this type of pam if not already set + if (!isset($_PAM_HANDLERS[$policy])) { + $_PAM_HANDLERS[$policy] = array(); + } + if (is_callable($handler)) { - $_PAM_HANDLERS[$handler] = new stdClass; + $_PAM_HANDLERS[$policy][$handler] = new stdClass; - $_PAM_HANDLERS[$handler]->handler = $handler; - $_PAM_HANDLERS[$handler]->importance = strtolower($importance); + $_PAM_HANDLERS[$policy][$handler]->handler = $handler; + $_PAM_HANDLERS[$policy][$handler]->importance = strtolower($importance); return true; } @@ -48,18 +56,19 @@ function register_pam_handler($handler, $importance = "sufficient") { * Unregisters a PAM handler. * * @param string $handler The PAM handler function name + * @param string $policy - the policy type, default is "user" */ -function unregister_pam_handler($handler) { +function unregister_pam_handler($handler, $policy = "user") { global $_PAM_HANDLERS; - unset($_PAM_HANDLERS[$handler]); + unset($_PAM_HANDLERS[$policy][$handler]); } /** * Attempt to authenticate. * This function will process all registered PAM handlers or stop when the first * handler fails. A handler fails by either returning false or throwing an - * exception. The advatange of throwing an exception is that it returns a message + * exception. The advantage of throwing an exception is that it returns a message * through the global $_PAM_HANDLERS_MSG which can be used in communication with * a user. The order that handlers are processed is determined by the order that * they were registered. @@ -69,14 +78,17 @@ function unregister_pam_handler($handler) { * otherwise retrieved (eg from the HTTP header or $_SESSION). * * @param mixed $credentials Mixed PAM handler specific credentials (e.g. username, password) + * @param string $policy - the policy type, default is "user" * @return bool true if authenticated, false if not. */ -function pam_authenticate($credentials = NULL) { +function pam_authenticate($credentials = NULL, $policy = "user") { global $_PAM_HANDLERS, $_PAM_HANDLERS_MSG; + $_PAM_HANDLERS_MSG = array(); + $authenticated = false; - foreach ($_PAM_HANDLERS as $k => $v) { + foreach ($_PAM_HANDLERS[$policy] as $k => $v) { $handler = $v->handler; $importance = $v->importance; diff --git a/engine/tests/services/api.php b/engine/tests/services/api.php index 66fff268d..28a7a64bc 100644 --- a/engine/tests/services/api.php +++ b/engine/tests/services/api.php @@ -257,7 +257,7 @@ class ElggCoreServicesApiTest extends ElggCoreUnitTest { // api key methods
public function testApiAuthenticate() {
- $this->assertFalse(api_authenticate());
+ $this->assertFalse(pam_authenticate(null, "api"));
}
public function testApiAuthKeyNoKey() {
diff --git a/services/api/rest.php b/services/api/rest.php index 8ac63022d..4d3e39aaa 100644 --- a/services/api/rest.php +++ b/services/api/rest.php @@ -34,8 +34,10 @@ if (trigger_plugin_hook('rest', 'init', null, false) == false) { // user token can also be used for user authentication register_pam_handler('pam_auth_usertoken'); - // for api authentication, we default to a simple API key check - register_api_auth_handler('api_auth_key'); + // simple API key check + register_pam_handler('api_auth_key', "sufficient", "api"); + // hmac + register_pam_handler('api_auth_hmac', "sufficient", "api"); } // Get parameter variables |