| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: openid.inc,v 1.8.2.3 2010/03/01 11:06:41 goba Exp $ 3 4 /** 5 * @file 6 * OpenID utility functions. 7 */ 8 9 // Diffie-Hellman Key Exchange Default Value. 10 define('OPENID_DH_DEFAULT_MOD', '155172898181473697471232257763715539915724801'. 11 '966915404479707795314057629378541917580651227423698188993727816152646631'. 12 '438561595825688188889951272158842675419950341258706556549803580104870537'. 13 '681476726513255747040765857479291291572334510643245094715007229621094194'. 14 '349783925984760375594985848253359305585439638443'); 15 16 // Constants for Diffie-Hellman key exchange computations. 17 define('OPENID_DH_DEFAULT_GEN', '2'); 18 define('OPENID_SHA1_BLOCKSIZE', 64); 19 define('OPENID_RAND_SOURCE', '/dev/urandom'); 20 21 // OpenID namespace URLs 22 define('OPENID_NS_2_0', 'http://specs.openid.net/auth/2.0'); 23 define('OPENID_NS_1_1', 'http://openid.net/signon/1.1'); 24 define('OPENID_NS_1_0', 'http://openid.net/signon/1.0'); 25 26 /** 27 * Performs an HTTP 302 redirect (for the 1.x protocol). 28 */ 29 function openid_redirect_http($url, $message) { 30 $query = array(); 31 foreach ($message as $key => $val) { 32 $query[] = $key .'='. urlencode($val); 33 } 34 35 $sep = (strpos($url, '?') === FALSE) ? '?' : '&'; 36 header('Location: '. $url . $sep . implode('&', $query), TRUE, 302); 37 exit; 38 } 39 40 /** 41 * Creates a js auto-submit redirect for (for the 2.x protocol) 42 */ 43 function openid_redirect($url, $message) { 44 $output = '<html><head><title>'. t('OpenID redirect') ."</title></head>\n<body>"; 45 $output .= drupal_get_form('openid_redirect_form', $url, $message); 46 $output .= '<script type="text/javascript">document.getElementById("openid-redirect-form").submit();</script>'; 47 $output .= "</body></html>\n"; 48 print $output; 49 exit; 50 } 51 52 function openid_redirect_form(&$form_state, $url, $message) { 53 $form = array(); 54 $form['#action'] = $url; 55 $form['#method'] = "post"; 56 foreach ($message as $key => $value) { 57 $form[$key] = array( 58 '#type' => 'hidden', 59 '#name' => $key, 60 '#value' => $value, 61 ); 62 } 63 $form['submit'] = array( 64 '#type' => 'submit', 65 '#prefix' => '<noscript>', 66 '#suffix' => '</noscript>', 67 '#value' => t('Send'), 68 ); 69 70 return $form; 71 } 72 73 /** 74 * Determine if the given identifier is an XRI ID. 75 */ 76 function _openid_is_xri($identifier) { 77 // Strip the xri:// scheme from the identifier if present. 78 if (strpos(strtolower($identifier), 'xri://') !== FALSE) { 79 $identifier = substr($identifier, 6); 80 } 81 82 // Test whether the identifier starts with an XRI global context symbol or (. 83 $firstchar = substr($identifier, 0, 1); 84 if (strpos("=@+$!(", $firstchar) !== FALSE) { 85 return TRUE; 86 } 87 88 return FALSE; 89 } 90 91 /** 92 * Normalize the given identifier as per spec. 93 */ 94 function _openid_normalize($identifier) { 95 if (_openid_is_xri($identifier)) { 96 return _openid_normalize_xri($identifier); 97 } 98 else { 99 return _openid_normalize_url($identifier); 100 } 101 } 102 103 function _openid_normalize_xri($xri) { 104 $normalized_xri = $xri; 105 if (stristr($xri, 'xri://') !== FALSE) { 106 $normalized_xri = substr($xri, 6); 107 } 108 return $normalized_xri; 109 } 110 111 function _openid_normalize_url($url) { 112 $normalized_url = $url; 113 114 if (stristr($url, '://') === FALSE) { 115 $normalized_url = 'http://'. $url; 116 } 117 118 // Strip the fragment and fragment delimiter if present. 119 $normalized_url = strtok($normalized_url, '#'); 120 121 if (substr_count($normalized_url, '/') < 3) { 122 $normalized_url .= '/'; 123 } 124 125 return $normalized_url; 126 } 127 128 /** 129 * Create a serialized message packet as per spec: $key:$value\n . 130 */ 131 function _openid_create_message($data) { 132 $serialized = ''; 133 134 foreach ($data as $key => $value) { 135 if ((strpos($key, ':') !== FALSE) || (strpos($key, "\n") !== FALSE) || (strpos($value, "\n") !== FALSE)) { 136 return null; 137 } 138 $serialized .= "$key:$value\n"; 139 } 140 return $serialized; 141 } 142 143 /** 144 * Encode a message from _openid_create_message for HTTP Post 145 */ 146 function _openid_encode_message($message) { 147 $encoded_message = ''; 148 149 $items = explode("\n", $message); 150 foreach ($items as $item) { 151 $parts = explode(':', $item, 2); 152 153 if (count($parts) == 2) { 154 if ($encoded_message != '') { 155 $encoded_message .= '&'; 156 } 157 $encoded_message .= rawurlencode(trim($parts[0])) .'='. rawurlencode(trim($parts[1])); 158 } 159 } 160 161 return $encoded_message; 162 } 163 164 /** 165 * Convert a direct communication message 166 * into an associative array. 167 */ 168 function _openid_parse_message($message) { 169 $parsed_message = array(); 170 171 $items = explode("\n", $message); 172 foreach ($items as $item) { 173 $parts = explode(':', $item, 2); 174 175 if (count($parts) == 2) { 176 $parsed_message[$parts[0]] = $parts[1]; 177 } 178 } 179 180 return $parsed_message; 181 } 182 183 /** 184 * Return a nonce value - formatted per OpenID spec. 185 */ 186 function _openid_nonce() { 187 // YYYY-MM-DDThh:mm:ssTZD UTC, plus some optional extra unique chars 188 return gmstrftime('%Y-%m-%dT%H:%M:%S%Z') . 189 chr(mt_rand(0, 25) + 65) . 190 chr(mt_rand(0, 25) + 65) . 191 chr(mt_rand(0, 25) + 65) . 192 chr(mt_rand(0, 25) + 65); 193 } 194 195 /** 196 * Pull the href attribute out of an html link element. 197 */ 198 function _openid_link_href($rel, $html) { 199 $rel = preg_quote($rel); 200 preg_match('|<link\s+rel=["\'](.*)'. $rel .'(.*)["\'](.*)/?>|iUs', $html, $matches); 201 if (isset($matches[3])) { 202 preg_match('|href=["\']([^"]+)["\']|iU', $matches[3], $href); 203 return trim($href[1]); 204 } 205 return FALSE; 206 } 207 208 /** 209 * Pull the http-equiv attribute out of an html meta element 210 */ 211 function _openid_meta_httpequiv($equiv, $html) { 212 preg_match('|<meta\s+http-equiv=["\']'. $equiv .'["\'](.*)/?>|iUs', $html, $matches); 213 if (isset($matches[1])) { 214 preg_match('|content=["\']([^"]+)["\']|iUs', $matches[1], $content); 215 if (isset($content[1])) { 216 return $content[1]; 217 } 218 } 219 return FALSE; 220 } 221 222 /** 223 * Sign certain keys in a message 224 * @param $association - object loaded from openid_association or openid_server_association table 225 * - important fields are ->assoc_type and ->mac_key 226 * @param $message_array - array of entire message about to be sent 227 * @param $keys_to_sign - keys in the message to include in signature (without 228 * 'openid.' appended) 229 */ 230 function _openid_signature($association, $message_array, $keys_to_sign) { 231 $signature = ''; 232 $sign_data = array(); 233 234 foreach ($keys_to_sign as $key) { 235 if (isset($message_array['openid.'. $key])) { 236 $sign_data[$key] = $message_array['openid.'. $key]; 237 } 238 } 239 240 $message = _openid_create_message($sign_data); 241 $secret = base64_decode($association->mac_key); 242 $signature = _openid_hmac($secret, $message); 243 244 return base64_encode($signature); 245 } 246 247 function _openid_hmac($key, $text) { 248 if (strlen($key) > OPENID_SHA1_BLOCKSIZE) { 249 $key = _openid_sha1($key, true); 250 } 251 252 $key = str_pad($key, OPENID_SHA1_BLOCKSIZE, chr(0x00)); 253 $ipad = str_repeat(chr(0x36), OPENID_SHA1_BLOCKSIZE); 254 $opad = str_repeat(chr(0x5c), OPENID_SHA1_BLOCKSIZE); 255 $hash1 = _openid_sha1(($key ^ $ipad) . $text, true); 256 $hmac = _openid_sha1(($key ^ $opad) . $hash1, true); 257 258 return $hmac; 259 } 260 261 function _openid_sha1($text) { 262 $hex = sha1($text); 263 $raw = ''; 264 for ($i = 0; $i < 40; $i += 2) { 265 $hexcode = substr($hex, $i, 2); 266 $charcode = (int)base_convert($hexcode, 16, 10); 267 $raw .= chr($charcode); 268 } 269 return $raw; 270 } 271 272 function _openid_dh_base64_to_long($str) { 273 $b64 = base64_decode($str); 274 275 return _openid_dh_binary_to_long($b64); 276 } 277 278 function _openid_dh_long_to_base64($str) { 279 return base64_encode(_openid_dh_long_to_binary($str)); 280 } 281 282 function _openid_dh_binary_to_long($str) { 283 $bytes = array_merge(unpack('C*', $str)); 284 285 $n = 0; 286 foreach ($bytes as $byte) { 287 $n = bcmul($n, pow(2, 8)); 288 $n = bcadd($n, $byte); 289 } 290 291 return $n; 292 } 293 294 function _openid_dh_long_to_binary($long) { 295 $cmp = bccomp($long, 0); 296 if ($cmp < 0) { 297 return FALSE; 298 } 299 300 if ($cmp == 0) { 301 return "\x00"; 302 } 303 304 $bytes = array(); 305 306 while (bccomp($long, 0) > 0) { 307 array_unshift($bytes, bcmod($long, 256)); 308 $long = bcdiv($long, pow(2, 8)); 309 } 310 311 if ($bytes && ($bytes[0] > 127)) { 312 array_unshift($bytes, 0); 313 } 314 315 $string = ''; 316 foreach ($bytes as $byte) { 317 $string .= pack('C', $byte); 318 } 319 320 return $string; 321 } 322 323 function _openid_dh_xorsecret($shared, $secret) { 324 $dh_shared_str = _openid_dh_long_to_binary($shared); 325 $sha1_dh_shared = _openid_sha1($dh_shared_str); 326 $xsecret = ""; 327 for ($i = 0; $i < strlen($secret); $i++) { 328 $xsecret .= chr(ord($secret[$i]) ^ ord($sha1_dh_shared[$i])); 329 } 330 331 return $xsecret; 332 } 333 334 function _openid_dh_rand($stop) { 335 static $duplicate_cache = array(); 336 337 // Used as the key for the duplicate cache 338 $rbytes = _openid_dh_long_to_binary($stop); 339 340 if (array_key_exists($rbytes, $duplicate_cache)) { 341 list($duplicate, $nbytes) = $duplicate_cache[$rbytes]; 342 } 343 else { 344 if ($rbytes[0] == "\x00") { 345 $nbytes = strlen($rbytes) - 1; 346 } 347 else { 348 $nbytes = strlen($rbytes); 349 } 350 351 $mxrand = bcpow(256, $nbytes); 352 353 // If we get a number less than this, then it is in the 354 // duplicated range. 355 $duplicate = bcmod($mxrand, $stop); 356 357 if (count($duplicate_cache) > 10) { 358 $duplicate_cache = array(); 359 } 360 361 $duplicate_cache[$rbytes] = array($duplicate, $nbytes); 362 } 363 364 do { 365 $bytes = "\x00". _openid_get_bytes($nbytes); 366 $n = _openid_dh_binary_to_long($bytes); 367 // Keep looping if this value is in the low duplicated range. 368 } while (bccomp($n, $duplicate) < 0); 369 370 return bcmod($n, $stop); 371 } 372 373 function _openid_get_bytes($num_bytes) { 374 static $f = null; 375 $bytes = ''; 376 if (!isset($f)) { 377 $f = @fopen(OPENID_RAND_SOURCE, "r"); 378 } 379 if (!$f) { 380 // pseudorandom used 381 $bytes = ''; 382 for ($i = 0; $i < $num_bytes; $i += 4) { 383 $bytes .= pack('L', mt_rand()); 384 } 385 $bytes = substr($bytes, 0, $num_bytes); 386 } 387 else { 388 $bytes = fread($f, $num_bytes); 389 } 390 return $bytes; 391 } 392 393 function _openid_response($str = NULL) { 394 $data = array(); 395 396 if (isset($_SERVER['REQUEST_METHOD'])) { 397 $data = _openid_get_params($_SERVER['QUERY_STRING']); 398 399 if ($_SERVER['REQUEST_METHOD'] == 'POST') { 400 $str = file_get_contents('php://input'); 401 402 $post = array(); 403 if ($str !== false) { 404 $post = _openid_get_params($str); 405 } 406 407 $data = array_merge($data, $post); 408 } 409 } 410 411 return $data; 412 } 413 414 function _openid_get_params($str) { 415 $chunks = explode("&", $str); 416 417 $data = array(); 418 foreach ($chunks as $chunk) { 419 $parts = explode("=", $chunk, 2); 420 421 if (count($parts) == 2) { 422 list($k, $v) = $parts; 423 $data[$k] = urldecode($v); 424 } 425 } 426 return $data; 427 } 428 429 /** 430 * Provide bcpowmod support for PHP4. 431 */ 432 if (!function_exists('bcpowmod')) { 433 function bcpowmod($base, $exp, $mod) { 434 $square = bcmod($base, $mod); 435 $result = 1; 436 while (bccomp($exp, 0) > 0) { 437 if (bcmod($exp, 2)) { 438 $result = bcmod(bcmul($result, $square), $mod); 439 } 440 $square = bcmod(bcmul($square, $square), $mod); 441 $exp = bcdiv($exp, 2); 442 } 443 return $result; 444 } 445 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |