| 1 |
<?php |
<?php |
| 2 |
// $Id: services.module,v 1.8.2.22 2008/08/29 10:58:12 brmassa Exp $ |
// $Id: services.module,v 1.8.2.23 2008/08/29 11:27:40 brmassa Exp $ |
| 3 |
/** |
/** |
| 4 |
* @author Services Dev Team |
* @author Services Dev Team |
| 5 |
* @file |
* @file |
| 7 |
*/ |
*/ |
| 8 |
|
|
| 9 |
/** |
/** |
| 10 |
|
* Implementation of hook_cron(). |
| 11 |
|
* |
| 12 |
|
* Clear down old values from the nonce table. |
| 13 |
|
*/ |
| 14 |
|
function services_cron() { |
| 15 |
|
$expiry_time = time() - variable_get('services_key_expiry', 30); |
| 16 |
|
db_query("DELETE FROM {services_timestamp_nonce} |
| 17 |
|
WHERE timestamp < %d", $expiry_time); |
| 18 |
|
} |
| 19 |
|
|
| 20 |
|
/** |
| 21 |
* Implementation of hook_help(). |
* Implementation of hook_help(). |
| 22 |
*/ |
*/ |
| 23 |
function services_help($path, $arg) { |
function services_help($path, $arg) { |
| 252 |
return services_error(t('Method %name does not exist.', array('%name' => $method_name))); |
return services_error(t('Method %name does not exist.', array('%name' => $method_name))); |
| 253 |
} |
} |
| 254 |
|
|
| 255 |
// Check for missing args. |
// Check for missing args and identify if arg is required in the hash. |
| 256 |
|
$hash_parameters = array(); |
| 257 |
foreach ($method['#args'] as $key => $arg) { |
foreach ($method['#args'] as $key => $arg) { |
| 258 |
if (!$arg['#optional']) { |
if (!$arg['#optional']) { |
| 259 |
if (!is_numeric($args[$key]) && empty($args[$key])) { |
if (!is_numeric($args[$key]) && empty($args[$key])) { |
| 260 |
return services_error(t('Missing required arguments.')); |
return services_error(t('Missing required arguments.')); |
| 261 |
} |
} |
| 262 |
} |
} |
| 263 |
|
|
| 264 |
|
// Key is part of the hash |
| 265 |
|
if ($arg['#signed'] == TRUE && variable_get('services_use_key', TRUE)) { |
| 266 |
|
if (is_numeric($args[$key]) || !empty($args[$key])) { |
| 267 |
|
$hash_parameters[] = $args[$key]; |
| 268 |
|
} |
| 269 |
|
else{ |
| 270 |
|
$hash_parameters[] = ''; |
| 271 |
|
} |
| 272 |
|
} |
| 273 |
} |
} |
| 274 |
|
|
| 275 |
// Add additonal processing for methods requiring api key |
if ($method['#key'] && variable_get('services_use_key', TRUE)) { |
| 276 |
if (variable_get('services_use_key', TRUE)) { |
$hash = array_shift($args); |
| 277 |
$api_key = array_shift($args); |
$domain = array_shift($args); |
| 278 |
$domain = NULL; |
$timestamp = array_shift($args); |
| 279 |
$timestamp = NULL; |
$nonce = array_shift($args); |
| 280 |
$hash = NULL; |
|
| 281 |
// Check strict domain matching. |
$expiry_time = $timestamp + variable_get('services_key_expiry', 30); |
| 282 |
if (variable_get('services_domain_strict', FALSE)) { |
|
| 283 |
$domain = array_shift($args); |
if ($expiry_time < time()) { |
| 284 |
$timestamp = array_shift($args); |
return services_error(t('Token has expired.')); |
| 285 |
$hash = $api_key; |
} |
| 286 |
$api_key = db_result(db_query("SELECT kid FROM {services_keys} WHERE domain = '%s'", $domain)); |
|
| 287 |
|
// Still in time but has it been used before |
| 288 |
|
if (db_result(db_query("SELECT count(*) FROM {services_timestamp_nonce} |
| 289 |
|
WHERE domain = '%s' AND timestamp = %d AND nonce = '%s'", |
| 290 |
|
$domain, $timestamp, $nonce))) { |
| 291 |
|
return services_error(t('Token has been used previously for a request.')); |
| 292 |
|
} |
| 293 |
|
else{ |
| 294 |
|
db_query("INSERT INTO {services_timestamp_nonce} (domain, timestamp, nonce) |
| 295 |
|
VALUES ('%s', %d, '%s')", $domain, $timestamp, $nonce); |
| 296 |
} |
} |
| 297 |
if (!services_validate_key($api_key, $timestamp, $domain, $hash)) { |
|
| 298 |
|
$api_key = db_result(db_query("SELECT kid FROM {services_keys} WHERE domain = '%s'", $domain)); |
| 299 |
|
|
| 300 |
|
if (!services_validate_key($api_key, $timestamp, $domain, $nonce, $method_name, $hash_parameters, $hash)) { |
| 301 |
return services_error(t('Invalid API key.')); |
return services_error(t('Invalid API key.')); |
| 302 |
} |
} |
| 303 |
} |
} |
| 349 |
|
|
| 350 |
// api_key arg |
// api_key arg |
| 351 |
$arg_api_key = array( |
$arg_api_key = array( |
| 352 |
'#name' => 'api_key', |
'#name' => 'hash', |
| 353 |
'#type' => 'string', |
'#type' => 'string', |
| 354 |
'#description' => t('A valid API key.'), |
'#description' => t('A valid API key.'), |
| 355 |
); |
); |
| 374 |
'#description' => t('Time stamp used to hash key.'), |
'#description' => t('Time stamp used to hash key.'), |
| 375 |
); |
); |
| 376 |
|
|
| 377 |
|
$arg_nonce = array( |
| 378 |
|
'#name' => 'nonce', |
| 379 |
|
'#type' => 'string', |
| 380 |
|
'#description' => t('One time use nonce also used hash key.'), |
| 381 |
|
); |
| 382 |
|
|
| 383 |
foreach ($methods as $key => $method) { |
foreach ($methods as $key => $method) { |
| 384 |
|
|
| 385 |
// set method defaults |
// set method defaults |
| 387 |
$methods[$key]['#auth'] = TRUE; |
$methods[$key]['#auth'] = TRUE; |
| 388 |
} |
} |
| 389 |
|
|
| 390 |
|
if (!isset($methods[$key]['#key'])) { |
| 391 |
|
$methods[$key]['#key'] = TRUE; |
| 392 |
|
} |
| 393 |
|
|
| 394 |
if (!isset($methods[$key]['#access callback'])) { |
if (!isset($methods[$key]['#access callback'])) { |
| 395 |
$methods[$key]['#access callback'] = 'user_access'; |
$methods[$key]['#access callback'] = 'user_access'; |
| 396 |
if (!isset($methods[$key]['#access arguments'])) { |
if (!isset($methods[$key]['#access arguments'])) { |
| 406 |
$methods[$key]['#args'] = array_merge(array($arg_sessid), $methods[$key]['#args']); |
$methods[$key]['#args'] = array_merge(array($arg_sessid), $methods[$key]['#args']); |
| 407 |
} |
} |
| 408 |
|
|
| 409 |
if (variable_get('services_use_key', TRUE)) { |
if ($methods[$key]['#key'] && variable_get('services_use_key', TRUE)) { |
| 410 |
|
$methods[$key]['#args'] = array_merge(array($arg_nonce), $methods[$key]['#args']); |
| 411 |
|
$methods[$key]['#args'] = array_merge(array($arg_domain_time_stamp), $methods[$key]['#args']); |
| 412 |
|
$methods[$key]['#args'] = array_merge(array($arg_domain_name), $methods[$key]['#args']); |
| 413 |
$methods[$key]['#args'] = array_merge(array($arg_api_key), $methods[$key]['#args']); |
$methods[$key]['#args'] = array_merge(array($arg_api_key), $methods[$key]['#args']); |
|
if (variable_get('services_domain_strict', FALSE)) { |
|
|
$methods[$key]['#args'] = array_merge(array($arg_domain_time_stamp), $methods[$key]['#args']); |
|
|
$methods[$key]['#args'] = array_merge(array($arg_domain_check), $methods[$key]['#args']); |
|
|
} |
|
| 414 |
} |
} |
| 415 |
|
|
| 416 |
// set defaults for args |
// set defaults for args |
| 457 |
return $method_cache[$method_name]; |
return $method_cache[$method_name]; |
| 458 |
} |
} |
| 459 |
|
|
| 460 |
function services_validate_key($kid, $timestamp, $domain, $hash) { |
function services_validate_key($kid, $timestamp, $domain, $nonce, $method_name, $hash_parameters, $hash) { |
| 461 |
if (!variable_get('services_domain_strict', FALSE)) { |
$hash_parameters_string = implode(';', $hash_parameters); |
| 462 |
$key = services_get_key($kid); |
$rehash = hash_hmac("sha256", $timestamp . $domain . $nonce . $method_name . $hash_parameters_string, $kid); |
| 463 |
if ($key) { |
return ($rehash == $hash) ? TRUE : FALSE; |
|
return TRUE; |
|
|
} |
|
|
//compare the domain against the key |
|
|
else { |
|
|
return FALSE; |
|
|
} |
|
|
} |
|
|
else { |
|
|
$rehash = md5($kid . $timestamp . $domain); |
|
|
if ($rehash == $hash) { |
|
|
return TRUE; |
|
|
} |
|
|
else { |
|
|
return FALSE; |
|
|
} |
|
|
} |
|
| 464 |
} |
} |
| 465 |
|
|
| 466 |
function services_get_key($kid) { |
function services_get_key($kid) { |