123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899 |
- <?php
- define('OPENID_DH_DEFAULT_MOD', '155172898181473697471232257763715539915724801' .
- '966915404479707795314057629378541917580651227423698188993727816152646631' .
- '438561595825688188889951272158842675419950341258706556549803580104870537' .
- '681476726513255747040765857479291291572334510643245094715007229621094194' .
- '349783925984760375594985848253359305585439638443');
- define('OPENID_DH_DEFAULT_GEN', '2');
- define('OPENID_SHA1_BLOCKSIZE', 64);
- define('OPENID_RAND_SOURCE', '/dev/urandom');
- define('OPENID_NS_2_0', 'http://specs.openid.net/auth/2.0');
- define('OPENID_NS_1_1', 'http://openid.net/signon/1.1');
- define('OPENID_NS_1_0', 'http://openid.net/signon/1.0');
- define('OPENID_NS_OPENID', 'http://openid.net/xmlns/1.0');
- define('OPENID_NS_SREG', 'http://openid.net/extensions/sreg/1.1');
- define('OPENID_NS_AX', 'http://openid.net/srv/ax/1.0');
- define('OPENID_NS_XRD', 'xri://$xrd*($v*2.0)');
- function openid_redirect_http($url, $message) {
- $query = array();
- foreach ($message as $key => $val) {
- $query[] = $key . '=' . urlencode($val);
- }
- $sep = (strpos($url, '?') === FALSE) ? '?' : '&';
- header('Location: ' . $url . $sep . implode('&', $query), TRUE, 302);
- drupal_exit();
- }
- function openid_redirect($url, $message) {
- global $language;
- $output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . "\n";
- $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . $language->language . '" lang="' . $language->language . '">' . "\n";
- $output .= "<head>\n";
- $output .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
- $output .= "<title>" . t('OpenID redirect') . "</title>\n";
- $output .= "</head>\n";
- $output .= "<body>\n";
- $elements = drupal_get_form('openid_redirect_form', $url, $message);
- $output .= drupal_render($elements);
- $output .= '<script type="text/javascript">document.getElementById("openid-redirect-form").submit();</script>' . "\n";
- $output .= "</body>\n";
- $output .= "</html>\n";
- print $output;
- drupal_exit();
- }
- function openid_redirect_form($form, &$form_state, $url, $message) {
- $form['#action'] = $url;
- $form['#method'] = "post";
- foreach ($message as $key => $value) {
- $form[$key] = array(
- '#type' => 'hidden',
- '#name' => $key,
- '#value' => $value,
- );
- }
- $form['actions'] = array('#type' => 'actions');
- $form['actions']['submit'] = array(
- '#type' => 'submit',
- '#prefix' => '<noscript><div>',
- '#suffix' => '</div></noscript>',
- '#value' => t('Send'),
- );
- return $form;
- }
- function _openid_xrds_parse($raw_xml) {
- $services = array();
-
-
-
- $disable_entity_loader = function_exists('libxml_disable_entity_loader');
- if ($disable_entity_loader) {
- $load_entities = libxml_disable_entity_loader(TRUE);
- }
-
- $dom = new DOMDocument();
- @$dom->loadXML($raw_xml);
-
-
-
- if (isset($dom->doctype)) {
- return array();
- }
-
- if ($dom->getElementsByTagName('*')->length > variable_get('openid_xrds_maximum_tag_count', 30000)) {
- return array();
- }
-
- if ($xml = simplexml_import_dom($dom)) {
- foreach ($xml->children(OPENID_NS_XRD)->XRD as $xrd) {
- foreach ($xrd->children(OPENID_NS_XRD)->Service as $service_element) {
- $service = array(
- 'priority' => $service_element->attributes()->priority ? (int)$service_element->attributes()->priority : PHP_INT_MAX,
- 'types' => array(),
- 'uri' => (string)$service_element->children(OPENID_NS_XRD)->URI,
- 'service' => $service_element,
- 'xrd' => $xrd,
- );
- foreach ($service_element->Type as $type) {
- $service['types'][] = (string)$type;
- }
- if ($service_element->children(OPENID_NS_XRD)->LocalID) {
- $service['identity'] = (string)$service_element->children(OPENID_NS_XRD)->LocalID;
- }
- elseif ($service_element->children(OPENID_NS_OPENID)->Delegate) {
- $service['identity'] = (string)$service_element->children(OPENID_NS_OPENID)->Delegate;
- }
- else {
- $service['identity'] = FALSE;
- }
- $services[] = $service;
- }
- }
- }
-
- if ($disable_entity_loader) {
- libxml_disable_entity_loader($load_entities);
- }
- return $services;
- }
- function _openid_select_service(array $services) {
-
-
-
- shuffle($services);
- $selected_service = NULL;
- $selected_type_priority = FALSE;
-
- foreach ($services as $service) {
- if (!empty($service['uri'])) {
- $type_priority = FALSE;
- if (in_array('http://specs.openid.net/auth/2.0/server', $service['types'])) {
- $service['version'] = 2;
- $type_priority = 1;
- }
- elseif (in_array('http://specs.openid.net/auth/2.0/signon', $service['types'])) {
- $service['version'] = 2;
- $type_priority = 2;
- }
- elseif (in_array(OPENID_NS_1_0, $service['types']) || in_array(OPENID_NS_1_1, $service['types'])) {
- $service['version'] = 1;
- $type_priority = 3;
- }
- if ($type_priority
- && (!$selected_service
- || $type_priority < $selected_type_priority
- || ($type_priority == $selected_type_priority && $service['priority'] < $selected_service['priority']))) {
- $selected_service = $service;
- $selected_type_priority = $type_priority;
- }
- }
- }
- if ($selected_service) {
-
- unset($selected_service['xrd']);
- unset($selected_service['service']);
- }
- return $selected_service;
- }
- function _openid_is_xri($identifier) {
-
- if (stripos($identifier, 'xri://') === 0) {
- $identifier = substr($identifier, 6);
- }
-
- $firstchar = substr($identifier, 0, 1);
- if (strpos("=@+$!(", $firstchar) !== FALSE) {
- return TRUE;
- }
- return FALSE;
- }
- function openid_normalize($identifier) {
- $methods = module_invoke_all('openid_normalization_method_info');
- drupal_alter('openid_normalization_method_info', $methods);
-
-
- foreach ($methods as $method) {
- $result = $method($identifier);
- if ($result !== NULL) {
- $identifier = $result;
- break;
- }
- }
- return $identifier;
- }
- function _openid_xri_normalize($identifier) {
- if (_openid_is_xri($identifier)) {
- if (stristr($identifier, 'xri://') !== FALSE) {
- $identifier = substr($identifier, 6);
- }
- return $identifier;
- }
- }
- function _openid_url_normalize($url) {
- $normalized_url = $url;
- if (stristr($url, '://') === FALSE) {
- $normalized_url = 'http://' . $url;
- }
-
- $normalized_url = strtok($normalized_url, '#');
- if (substr_count($normalized_url, '/') < 3) {
- $normalized_url .= '/';
- }
- return $normalized_url;
- }
- function _openid_create_message($data) {
- $serialized = '';
- foreach ($data as $key => $value) {
- if ((strpos($key, ':') !== FALSE) || (strpos($key, "\n") !== FALSE) || (strpos($value, "\n") !== FALSE)) {
- return NULL;
- }
- $serialized .= "$key:$value\n";
- }
- return $serialized;
- }
- function _openid_encode_message($message) {
- $encoded_message = '';
- $items = explode("\n", $message);
- foreach ($items as $item) {
- $parts = explode(':', $item, 2);
- if (count($parts) == 2) {
- if ($encoded_message != '') {
- $encoded_message .= '&';
- }
- $encoded_message .= rawurlencode(trim($parts[0])) . '=' . rawurlencode(trim($parts[1]));
- }
- }
- return $encoded_message;
- }
- function _openid_parse_message($message) {
- $parsed_message = array();
- $items = explode("\n", $message);
- foreach ($items as $item) {
- $parts = explode(':', $item, 2);
- if (count($parts) == 2) {
- $parsed_message[$parts[0]] = $parts[1];
- }
- }
- return $parsed_message;
- }
- function _openid_nonce() {
-
- return gmdate('Y-m-d\TH:i:s\Z') .
- chr(mt_rand(0, 25) + 65) .
- chr(mt_rand(0, 25) + 65) .
- chr(mt_rand(0, 25) + 65) .
- chr(mt_rand(0, 25) + 65);
- }
- function _openid_link_href($rel, $html) {
- $rel = preg_quote($rel);
- preg_match('|<link\s+rel=["\'](.*)' . $rel . '(.*)["\'](.*)/?>|iUs', $html, $matches);
- if (isset($matches[3])) {
- preg_match('|href=["\']([^"]+)["\']|iU', $matches[3], $href);
- return trim($href[1]);
- }
- return FALSE;
- }
- function _openid_meta_httpequiv($equiv, $html) {
- preg_match('|<meta\s+http-equiv=["\']' . $equiv . '["\'](.*)/?>|iUs', $html, $matches);
- if (isset($matches[1])) {
- preg_match('|content=["\']([^"]+)["\']|iUs', $matches[1], $content);
- if (isset($content[1])) {
- return $content[1];
- }
- }
- return FALSE;
- }
- function _openid_signature($association, $message_array, $keys_to_sign) {
- $signature = '';
- $sign_data = array();
- foreach ($keys_to_sign as $key) {
- if (isset($message_array['openid.' . $key])) {
- $sign_data[$key] = $message_array['openid.' . $key];
- }
- }
- $message = _openid_create_message($sign_data);
- $secret = base64_decode($association->mac_key);
- $signature = _openid_hmac($secret, $message);
- return base64_encode($signature);
- }
- function _openid_hmac($key, $text) {
- if (strlen($key) > OPENID_SHA1_BLOCKSIZE) {
- $key = sha1($key, TRUE);
- }
- $key = str_pad($key, OPENID_SHA1_BLOCKSIZE, chr(0x00));
- $ipad = str_repeat(chr(0x36), OPENID_SHA1_BLOCKSIZE);
- $opad = str_repeat(chr(0x5c), OPENID_SHA1_BLOCKSIZE);
- $hash1 = sha1(($key ^ $ipad) . $text, TRUE);
- $hmac = sha1(($key ^ $opad) . $hash1, TRUE);
- return $hmac;
- }
- function _openid_dh_base64_to_long($str) {
- $b64 = base64_decode($str);
- return _openid_dh_binary_to_long($b64);
- }
- function _openid_dh_long_to_base64($str) {
- return base64_encode(_openid_dh_long_to_binary($str));
- }
- function _openid_dh_binary_to_long($str) {
- $bytes = array_merge(unpack('C*', $str));
- $n = 0;
- foreach ($bytes as $byte) {
- $n = _openid_math_mul($n, pow(2, 8));
- $n = _openid_math_add($n, $byte);
- }
- return $n;
- }
- function _openid_dh_long_to_binary($long) {
- $cmp = _openid_math_cmp($long, 0);
- if ($cmp < 0) {
- return FALSE;
- }
- if ($cmp == 0) {
- return "\x00";
- }
- $bytes = array();
- while (_openid_math_cmp($long, 0) > 0) {
- array_unshift($bytes, _openid_math_mod($long, 256));
- $long = _openid_math_div($long, pow(2, 8));
- }
- if ($bytes && ($bytes[0] > 127)) {
- array_unshift($bytes, 0);
- }
- $string = '';
- foreach ($bytes as $byte) {
- $string .= pack('C', $byte);
- }
- return $string;
- }
- function _openid_dh_xorsecret($shared, $secret) {
- $dh_shared_str = _openid_dh_long_to_binary($shared);
- $sha1_dh_shared = sha1($dh_shared_str, TRUE);
- $xsecret = "";
- for ($i = 0; $i < strlen($secret); $i++) {
- $xsecret .= chr(ord($secret[$i]) ^ ord($sha1_dh_shared[$i]));
- }
- return $xsecret;
- }
- function _openid_dh_rand($stop) {
- $duplicate_cache = &drupal_static(__FUNCTION__, array());
-
- $rbytes = _openid_dh_long_to_binary($stop);
- if (isset($duplicate_cache[$rbytes])) {
- list($duplicate, $nbytes) = $duplicate_cache[$rbytes];
- }
- else {
- if ($rbytes[0] == "\x00") {
- $nbytes = strlen($rbytes) - 1;
- }
- else {
- $nbytes = strlen($rbytes);
- }
- $mxrand = _openid_math_pow(256, $nbytes);
-
-
- $duplicate = _openid_math_mod($mxrand, $stop);
- if (count($duplicate_cache) > 10) {
- $duplicate_cache = array();
- }
- $duplicate_cache[$rbytes] = array($duplicate, $nbytes);
- }
- do {
- $bytes = "\x00" . drupal_random_bytes($nbytes);
- $n = _openid_dh_binary_to_long($bytes);
-
- } while (_openid_math_cmp($n, $duplicate) < 0);
- return _openid_math_mod($n, $stop);
- }
- function _openid_get_bytes($num_bytes) {
- return drupal_random_bytes($num_bytes);
- }
- function _openid_response($str = NULL) {
- $data = array();
- if (isset($_SERVER['REQUEST_METHOD'])) {
- $data = _openid_get_params($_SERVER['QUERY_STRING']);
- if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- $str = file_get_contents('php://input');
- $post = array();
- if ($str !== FALSE) {
- $post = _openid_get_params($str);
- }
- $data = array_merge($data, $post);
- }
- }
- return $data;
- }
- function _openid_get_params($str) {
- $chunks = explode("&", $str);
- $data = array();
- foreach ($chunks as $chunk) {
- $parts = explode("=", $chunk, 2);
- if (count($parts) == 2) {
- list($k, $v) = $parts;
- $data[$k] = urldecode($v);
- }
- }
- return $data;
- }
- function openid_extract_namespace($response, $extension_namespace, $fallback_prefix = NULL, $only_signed = FALSE) {
- $signed_keys = explode(',', $response['openid.signed']);
-
- $prefix = $fallback_prefix;
- foreach ($response as $key => $value) {
- if ($value == $extension_namespace && preg_match('/^openid\.ns\.([^.]+)$/', $key, $matches)) {
- $prefix = $matches[1];
- if ($only_signed && !in_array('ns.' . $matches[1], $signed_keys)) {
-
-
- $prefix = NULL;
- }
- break;
- }
- }
-
- $output = array();
- if (!isset($prefix)) {
- return $output;
- }
- foreach ($response as $key => $value) {
- if (preg_match('/^openid\.' . $prefix . '\.(.+)$/', $key, $matches)) {
- $local_key = $matches[1];
- if (!$only_signed || in_array($prefix . '.' . $local_key, $signed_keys)) {
- $output[$local_key] = $value;
- }
- }
- }
- return $output;
- }
- function openid_extract_ax_values($values, $uris) {
- $output = array();
- foreach ($values as $key => $value) {
- if (in_array($value, $uris) && preg_match('/^type\.([^.]+)$/', $key, $matches)) {
- $alias = $matches[1];
- if (isset($values['count.' . $alias])) {
- for ($i = 1; $i <= $values['count.' . $alias]; $i++) {
- $output[] = $values['value.' . $alias . '.' . $i];
- }
- }
- elseif (isset($values['value.' . $alias])) {
- $output[] = $values['value.' . $alias];
- }
- break;
- }
- }
- return $output;
- }
- function _openid_get_math_library() {
-
-
- static $library;
- if (empty($library)) {
- if (function_exists('gmp_add')) {
- $library = 'gmp';
- }
- elseif (function_exists('bcadd')) {
- $library = 'bcmath';
- }
- }
- return $library;
- }
- function _openid_math_add($x, $y) {
- $library = _openid_get_math_library();
- switch ($library) {
- case 'gmp':
- return gmp_strval(gmp_add($x, $y));
- case 'bcmath':
- return bcadd($x, $y);
- }
- }
- function _openid_math_mul($x, $y) {
- $library = _openid_get_math_library();
- switch ($library) {
- case 'gmp':
- return gmp_mul($x, $y);
- case 'bcmath':
- return bcmul($x, $y);
- }
- }
- function _openid_math_div($x, $y) {
- $library = _openid_get_math_library();
- switch ($library) {
- case 'gmp':
- return gmp_div($x, $y);
- case 'bcmath':
- return bcdiv($x, $y);
- }
- }
- function _openid_math_cmp($x, $y) {
- $library = _openid_get_math_library();
- switch ($library) {
- case 'gmp':
- return gmp_cmp($x, $y);
- case 'bcmath':
- return bccomp($x, $y);
- }
- }
- function _openid_math_mod($x, $y) {
- $library = _openid_get_math_library();
- switch ($library) {
- case 'gmp':
- return gmp_mod($x, $y);
- case 'bcmath':
- return bcmod($x, $y);
- }
- }
- function _openid_math_pow($x, $y) {
- $library = _openid_get_math_library();
- switch ($library) {
- case 'gmp':
- return gmp_pow($x, $y);
- case 'bcmath':
- return bcpow($x, $y);
- }
- }
- function _openid_math_powmod($x, $y, $z) {
- $library = _openid_get_math_library();
- switch ($library) {
- case 'gmp':
- return gmp_powm($x, $y, $z);
- case 'bcmath':
- return bcpowmod($x, $y, $z);
- }
- }
- function _openid_invalid_openid_transition($identity, $response) {
- $account = FALSE;
- $fallback_account = NULL;
- $fallback_identity = $identity;
-
- if (strpos($fallback_identity, '#') !== FALSE) {
- $fallback_identity = preg_replace('/#.*/', '', $fallback_identity);
- $fallback_account = user_external_load($fallback_identity);
- }
-
-
- if (!$fallback_account && strpos($fallback_identity, 'https://') !== FALSE) {
- $fallback_identity = str_replace('https://', 'http://', $fallback_identity);
- $fallback_account = user_external_load($fallback_identity);
- }
-
- if (!$fallback_account && isset($_SESSION['openid']['user_login_values']['openid_identifier'])) {
- $fallback_identity = openid_normalize($_SESSION['openid']['user_login_values']['openid_identifier']);
- $fallback_account = user_external_load($fallback_identity);
- }
- if ($fallback_account) {
-
-
- $email = '';
- $sreg_values = openid_extract_namespace($response, OPENID_NS_SREG, 'sreg', TRUE);
- $ax_values = openid_extract_namespace($response, OPENID_NS_AX, 'ax', TRUE);
- if (!empty($sreg_values['email']) && valid_email_address($sreg_values['email'])) {
- $email = $sreg_values['email'];
- }
- elseif ($ax_mail_values = openid_extract_ax_values($ax_values, array('http://axschema.org/contact/email', 'http://schema.openid.net/contact/email'))) {
- $email = current($ax_mail_values);
- }
-
-
- if ($email && ($email == $fallback_account->mail || $email == $fallback_account->init)) {
- $query = db_insert('authmap')
- ->fields(array(
- 'authname' => $identity,
- 'uid' => $fallback_account->uid,
- 'module' => 'openid',
- ))
- ->execute();
- drupal_set_message(t('New OpenID identifier %identity was added as a replacement for invalid identifier %invalid_identity. To finish the invalid OpenID transition process, please go to your <a href="@openid_url">OpenID identities page</a> and remove the old identifier %invalid_identity.', array('%invalid_identity' => $fallback_identity, '%identity' => $identity, '@openid_url' => 'user/' . $fallback_account->uid . '/openid')));
-
- $account = $fallback_account;
- }
- else {
- drupal_set_message(t('There is already an existing account associated with the OpenID identifier that you have provided. However, due to a bug in the previous version of the authentication system, we can\'t be sure that this account belongs to you. If you are new on this site, please continue registering the new user account. If you already have a registered account on this site associated with the provided OpenID identifier, please try to <a href="@url_password">reset the password</a> or contact the site administrator.', array('@url_password' => 'user/password')), 'warning');
- }
- }
- return $account;
- }
|