123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752 |
- <?php
- function authenticate_method($method) {
- global $API_METHODS;
-
- if (!isset($API_METHODS[$method])) {
- throw new APIException(elgg_echo('APIException:MethodCallNotImplemented', array($method)));
- }
-
- if ($API_METHODS[$method]["require_api_auth"] == true) {
- $api_pam = new ElggPAM('api');
- if ($api_pam->authenticate() !== true) {
- throw new APIException(elgg_echo('APIException:APIAuthenticationFailed'));
- }
- }
- $user_pam = new ElggPAM('user');
- $user_auth_result = $user_pam->authenticate(array());
-
- if ($API_METHODS[$method]["require_user_auth"] == true) {
- if ($user_auth_result == false) {
- throw new APIException($user_pam->getFailureMessage(), ErrorResult::$RESULT_FAIL_AUTHTOKEN);
- }
- }
- return true;
- }
- function execute_method($method) {
- global $API_METHODS;
-
- if (!isset($API_METHODS[$method])) {
- $msg = elgg_echo('APIException:MethodCallNotImplemented', array($method));
- throw new APIException($msg);
- }
-
- $function = null;
- if (isset($API_METHODS[$method]["function"])) {
- $function = $API_METHODS[$method]["function"];
-
- if (is_array($function)
- && isset($function[0], $function[1])
- && is_string($function[0])
- && is_string($function[1])) {
- $function = "{$function[0]}::{$function[1]}";
- }
- }
- if (!is_string($function) || !is_callable($function)) {
- $msg = elgg_echo('APIException:FunctionDoesNotExist', array($method));
- throw new APIException($msg);
- }
-
- if (strcmp(get_call_method(), $API_METHODS[$method]["call_method"]) != 0) {
- $msg = elgg_echo('CallException:InvalidCallMethod', array($method,
- $API_METHODS[$method]["call_method"]));
- throw new CallException($msg);
- }
- $parameters = get_parameters_for_method($method);
-
- verify_parameters($method, $parameters);
- $serialised_parameters = serialise_parameters($method, $parameters);
-
- $serialised_parameters = trim($serialised_parameters, ", ");
-
- $result = eval("return $function($serialised_parameters);");
-
-
- if ($result instanceof GenericResult) {
- return $result;
- }
- if ($result === false) {
- $msg = elgg_echo('APIException:FunctionParseError', array($function, $serialised_parameters));
- throw new APIException($msg);
- }
- if ($result === NULL) {
-
- $msg = elgg_echo('APIException:FunctionNoReturn', array($function, $serialised_parameters));
- throw new APIException($msg);
- }
-
- return SuccessResult::getInstance($result);
- }
- function get_call_method() {
- return _elgg_services()->request->server->get('REQUEST_METHOD');
- }
- function get_parameters_for_method($method) {
- global $API_METHODS;
- $sanitised = array();
-
- if (isset($API_METHODS[$method]['parameters'])) {
- foreach ($API_METHODS[$method]['parameters'] as $k => $v) {
- $param = get_input($k);
- if ($param !== '' && $param !== null) {
- $sanitised[$k] = $param;
- } else {
-
- if (isset($v['default'])) {
- $sanitised[$k] = $v['default'];
- }
- }
- }
- }
- return $sanitised;
- }
- function get_post_data() {
- $postdata = file_get_contents('php://input');
- return $postdata;
- }
- function verify_parameters($method, $parameters) {
- global $API_METHODS;
-
- if (!(isset($API_METHODS[$method]["parameters"]))) {
- return true;
- }
-
- foreach ($API_METHODS[$method]['parameters'] as $key => $value) {
-
- if (!is_array($value) || !isset($value['type'])) {
- $msg = elgg_echo('APIException:InvalidParameter', array($key, $method));
- throw new APIException($msg);
- }
-
- if ($value['required'] && !array_key_exists($key, $parameters)) {
- $msg = elgg_echo('APIException:MissingParameterInMethod', array($key, $method));
- throw new APIException($msg);
- }
- }
- return true;
- }
- function serialise_parameters($method, $parameters) {
- global $API_METHODS;
-
- if (!(isset($API_METHODS[$method]["parameters"]))) {
- return '';
- }
- $serialised_parameters = "";
- foreach ($API_METHODS[$method]['parameters'] as $key => $value) {
-
- if (!isset($parameters[$key])) {
- continue;
- }
-
- switch (strtolower($value['type']))
- {
- case 'int':
- case 'integer' :
- $serialised_parameters .= "," . (int)trim($parameters[$key]);
- break;
- case 'bool':
- case 'boolean':
-
- if (strcasecmp(trim($parameters[$key]), "false") == 0) {
- $serialised_parameters .= ',false';
- } else if ($parameters[$key] == 0) {
- $serialised_parameters .= ',false';
- } else {
- $serialised_parameters .= ',true';
- }
- break;
- case 'string':
- $serialised_parameters .= ",'" . addcslashes(trim($parameters[$key]), "'") . "'";
- break;
- case 'float':
- $serialised_parameters .= "," . (float)trim($parameters[$key]);
- break;
- case 'array':
-
- if (!is_array($parameters[$key])) {
- $msg = elgg_echo('APIException:ParameterNotArray', array($key));
- throw new APIException($msg);
- }
- $array = "array(";
- foreach ($parameters[$key] as $k => $v) {
- $k = sanitise_string($k);
- $v = sanitise_string($v);
- $array .= "'$k'=>'$v',";
- }
- $array = trim($array, ",");
- $array .= ")";
- $array = ",$array";
- $serialised_parameters .= $array;
- break;
- default:
- $msg = elgg_echo('APIException:UnrecognisedTypeCast', array($value['type'], $key, $method));
- throw new APIException($msg);
- }
- }
- return $serialised_parameters;
- }
- function api_auth_key() {
- global $CONFIG;
-
- $api_key = get_input('api_key');
- if ($api_key == "") {
- throw new APIException(elgg_echo('APIException:MissingAPIKey'));
- }
-
- $api_user = get_api_user($CONFIG->site_id, $api_key);
- if (!$api_user) {
-
- throw new APIException(elgg_echo('APIException:BadAPIKey'));
- }
-
-
- return elgg_trigger_plugin_hook('api_key', 'use', $api_key, true);
- }
- function api_auth_hmac() {
- global $CONFIG;
-
- $api_header = get_and_validate_api_headers();
-
- $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);
- }
-
- $secret_key = $api_user->secret;
-
- $query = _elgg_services()->request->server->get('REQUEST_URI');
- $query = substr($query, strpos($query, '?') + 1);
-
- $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");
- }
-
- if (cache_hmac_check_replay($hmac)) {
- throw new SecurityException(elgg_echo('SecurityException:DupePacket'));
- }
-
- 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;
- }
- function get_and_validate_api_headers() {
- $result = new stdClass;
- $result->method = get_call_method();
-
- if (($result->method != "GET") && ($result->method != "POST")) {
- throw new APIException(elgg_echo('APIException:NotGetOrPost'));
- }
- $server = _elgg_services()->request->server;
- $result->api_key = $server->get('HTTP_X_ELGG_APIKEY');
- if ($result->api_key == "") {
- throw new APIException(elgg_echo('APIException:MissingAPIKey'));
- }
- $result->hmac = $server->get('HTTP_X_ELGG_HMAC');
- if ($result->hmac == "") {
- throw new APIException(elgg_echo('APIException:MissingHmac'));
- }
- $result->hmac_algo = $server->get('HTTP_X_ELGG_HMAC_ALGO');
- if ($result->hmac_algo == "") {
- throw new APIException(elgg_echo('APIException:MissingHmacAlgo'));
- }
- $result->time = $server->get('HTTP_X_ELGG_TIME');
- if ($result->time == "") {
- throw new APIException(elgg_echo('APIException:MissingTime'));
- }
-
-
-
-
-
- if (($result->time < (time() - 90000)) || ($result->time > (time() + 90000))) {
- throw new APIException(elgg_echo('APIException:TemporalDrift'));
- }
- $result->nonce = $server->get('HTTP_X_ELGG_NONCE');
- if ($result->nonce == "") {
- throw new APIException(elgg_echo('APIException:MissingNonce'));
- }
- if ($result->method == "POST") {
- $result->posthash = $server->get('HTTP_X_ELGG_POSTHASH');
- if ($result->posthash == "") {
- throw new APIException(elgg_echo('APIException:MissingPOSTHash'));
- }
- $result->posthash_algo = $server->get('HTTP_X_ELGG_POSTHASH_ALGO');
- if ($result->posthash_algo == "") {
- throw new APIException(elgg_echo('APIException:MissingPOSTAlgo'));
- }
- $result->content_type = $server->get('CONTENT_TYPE');
- if ($result->content_type == "") {
- throw new APIException(elgg_echo('APIException:MissingContentType'));
- }
- }
- return $result;
- }
- function map_api_hash($algo) {
- $algo = strtolower(sanitise_string($algo));
- $supported_algos = array(
- "md5" => "md5",
- "sha" => "sha1",
- "sha1" => "sha1",
- "sha256" => "sha256"
- );
- if (array_key_exists($algo, $supported_algos)) {
- return $supported_algos[$algo];
- }
- throw new APIException(elgg_echo('APIException:AlgorithmNotSupported', array($algo)));
- }
- function calculate_hmac($algo, $time, $nonce, $api_key, $secret_key,
- $get_variables, $post_hash = "") {
- global $CONFIG;
- elgg_log("HMAC Parts: $algo, $time, $api_key, $secret_key, $get_variables, $post_hash");
- $ctx = hash_init(map_api_hash($algo), HASH_HMAC, $secret_key);
- hash_update($ctx, trim($time));
- hash_update($ctx, trim($nonce));
- hash_update($ctx, trim($api_key));
- hash_update($ctx, trim($get_variables));
- if (trim($post_hash) != "") {
- hash_update($ctx, trim($post_hash));
- }
- return urlencode(base64_encode(hash_final($ctx, true)));
- }
- function calculate_posthash($postdata, $algo) {
- $ctx = hash_init(map_api_hash($algo));
- hash_update($ctx, $postdata);
- return hash_final($ctx);
- }
- function cache_hmac_check_replay($hmac) {
-
-
- $cache = new ElggHMACCache(90000);
- if (!$cache->load($hmac)) {
- $cache->save($hmac, $hmac);
- return false;
- }
- return true;
- }
- function pam_auth_usertoken() {
- global $CONFIG;
- $token = get_input('auth_token');
- if (!$token) {
- return false;
- }
- $validated_userid = validate_user_token($token, $CONFIG->site_id);
- if ($validated_userid) {
- $u = get_entity($validated_userid);
-
- if (!$u) {
- return false;
- }
-
- if ((!$u instanceof ElggUser)) {
- return false;
- }
-
- if ($u->isBanned()) {
- return false;
- }
-
- if (!login($u)) {
- return false;
- }
- return true;
- }
- return false;
- }
- function pam_auth_session() {
- return elgg_is_logged_in();
- }
- function _php_api_error_handler($errno, $errmsg, $filename, $linenum, $vars) {
- global $ERRORS;
- $error = date("Y-m-d H:i:s (T)") . ": \"" . $errmsg . "\" in file "
- . $filename . " (line " . $linenum . ")";
- switch ($errno) {
- case E_USER_ERROR:
- error_log("ERROR: " . $error);
- $ERRORS[] = "ERROR: " . $error;
-
- throw new Exception("ERROR: " . $error);
- break;
- case E_WARNING :
- case E_USER_WARNING :
- error_log("WARNING: " . $error);
- $ERRORS[] = "WARNING: " . $error;
- break;
- default:
- error_log("DEBUG: " . $error);
- $ERRORS[] = "DEBUG: " . $error;
- }
- }
- function _php_api_exception_handler($exception) {
- error_log("*** FATAL EXCEPTION (API) *** : " . $exception);
- $code = $exception->getCode() == 0 ? ErrorResult::$RESULT_FAIL : $exception->getCode();
- $result = new ErrorResult($exception->getMessage(), $code, NULL);
- echo elgg_view_page($exception->getMessage(), elgg_view("api/output", array("result" => $result)));
- }
- function service_handler($handler, $request) {
- global $CONFIG;
- elgg_set_context('api');
- $request = explode('/', $request);
-
-
- $response_format = array_shift($request);
- if (!$response_format) {
- $response_format = 'json';
- }
- if (!ctype_alpha($response_format)) {
- header("HTTP/1.0 400 Bad Request");
- header("Content-type: text/plain");
- echo "Invalid format.";
- exit;
- }
- elgg_set_viewtype($response_format);
- if (!isset($CONFIG->servicehandler) || empty($handler)) {
-
- header("HTTP/1.0 404 Not Found");
- exit;
- } else if (isset($CONFIG->servicehandler[$handler]) && is_callable($CONFIG->servicehandler[$handler])) {
- $function = $CONFIG->servicehandler[$handler];
- call_user_func($function, $request, $handler);
- } else {
-
- header("HTTP/1.0 404 Not Found");
- exit;
- }
- }
|