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 | 
