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