[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/modules/openid/ -> openid.inc (source)

   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  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7