PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/id/MyID.php

https://github.com/bryanveloso/sayonarane
PHP | 1595 lines | 920 code | 327 blank | 348 comment | 203 complexity | d59152cf2763a5eed89a7abb73777cf2 MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. // PLEASE DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING!
  3. /**
  4. * phpMyID - A standalone, single user, OpenID Identity Provider
  5. *
  6. * @package phpMyID
  7. * @author CJ Niemira <siege (at) siege (dot) org>
  8. * @copyright 2006-2007
  9. * @license http://www.gnu.org/licenses/gpl.html GNU Public License
  10. * @url http://siege.org/projects/phpMyID
  11. * @version 0.6
  12. */
  13. /**
  14. * Set a constant to indicate that phpMyID is running
  15. */
  16. define('PHPMYID_STARTED', true);
  17. /**
  18. * List the known types and modes
  19. * @name $known
  20. * @global array $GLOBALS['known']
  21. */
  22. $GLOBALS['known'] = array(
  23. 'assoc_types' => array('HMAC-SHA1'),
  24. 'openid_modes' => array('associate',
  25. 'authorize',
  26. 'cancel',
  27. 'checkid_immediate',
  28. 'checkid_setup',
  29. 'check_authentication',
  30. 'error',
  31. 'id_res',
  32. 'login',
  33. 'logout',
  34. 'test'),
  35. 'session_types' => array('',
  36. 'DH-SHA1'),
  37. 'bigmath_types' => array('DH-SHA1'),
  38. );
  39. /**
  40. * Defined by OpenID spec
  41. * @name $g
  42. * @global integer $GLOBALS['g']
  43. */
  44. $GLOBALS['g'] = 2;
  45. /**
  46. * Defined by OpenID spec
  47. * @name $p
  48. * @global integer $GLOBALS['p']
  49. */
  50. $GLOBALS['p'] = '155172898181473697471232257763715539915724801966915404479707' .
  51. '7953140576293785419175806512274236981889937278161526466314385615958256881888' .
  52. '8995127215884267541995034125870655654980358010487053768147672651325574704076' .
  53. '5857479291291572334510643245094715007229621094194349783925984760375594985848' .
  54. '253359305585439638443';
  55. // Runmode functions
  56. /**
  57. * Perform an association with a consumer
  58. * @global array $known
  59. * @global array $profile
  60. * @global integer $g
  61. * @global integer $p
  62. */
  63. function associate_mode () {
  64. global $g, $known, $p, $profile;
  65. // Validate the request
  66. if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'associate')
  67. error_400();
  68. // Get the request options, using defaults as necessary
  69. $assoc_type = (@strlen($_REQUEST['openid_assoc_type'])
  70. && in_array($_REQUEST['openid_assoc_type'], $known['assoc_types']))
  71. ? $_REQUEST['openid_assoc_type']
  72. : 'HMAC-SHA1';
  73. $session_type = (@strlen($_REQUEST['openid_session_type'])
  74. && in_array($_REQUEST['openid_session_type'], $known['session_types']))
  75. ? $_REQUEST['openid_session_type']
  76. : '';
  77. $dh_modulus = (@strlen($_REQUEST['openid_dh_modulus']))
  78. ? long(base64_decode($_REQUEST['openid_dh_modulus']))
  79. : ($session_type == 'DH-SHA1'
  80. ? $p
  81. : null);
  82. $dh_gen = (@strlen($_REQUEST['openid_dh_gen']))
  83. ? long(base64_decode($_REQUEST['openid_dh_gen']))
  84. : ($session_type == 'DH-SHA1'
  85. ? $g
  86. : null);
  87. $dh_consumer_public = (@strlen($_REQUEST['openid_dh_consumer_public']))
  88. ? $_REQUEST['openid_dh_consumer_public']
  89. : ($session_type == 'DH-SHA1'
  90. ? error_post('dh_consumer_public was not specified')
  91. : null);
  92. $lifetime = time() + $profile['lifetime'];
  93. // Create standard keys
  94. $keys = array(
  95. 'assoc_type' => $assoc_type,
  96. 'expires_in' => $profile['lifetime']
  97. );
  98. // If I can't handle bigmath, default to plaintext sessions
  99. if (in_array($session_type, $known['bigmath_types']) && $profile['use_bigmath'] === false)
  100. $session_type = null;
  101. // Add response keys based on the session type
  102. switch ($session_type) {
  103. case 'DH-SHA1':
  104. // Create the associate id and shared secret now
  105. list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
  106. // Compute the Diffie-Hellman stuff
  107. $private_key = random($dh_modulus);
  108. $public_key = bmpowmod($dh_gen, $private_key, $dh_modulus);
  109. $remote_key = long(base64_decode($dh_consumer_public));
  110. $ss = bmpowmod($remote_key, $private_key, $dh_modulus);
  111. $keys['assoc_handle'] = $assoc_handle;
  112. $keys['session_type'] = $session_type;
  113. $keys['dh_server_public'] = base64_encode(bin($public_key));
  114. $keys['enc_mac_key'] = base64_encode(x_or(sha1_20(bin($ss)), $shared_secret));
  115. break;
  116. default:
  117. // Create the associate id and shared secret now
  118. list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
  119. $keys['assoc_handle'] = $assoc_handle;
  120. $keys['mac_key'] = base64_encode($shared_secret);
  121. }
  122. // Return the keys
  123. wrap_kv($keys);
  124. }
  125. /**
  126. * Perform a user authorization
  127. * @global array $profile
  128. */
  129. function authorize_mode () {
  130. global $profile;
  131. // this is a user session
  132. user_session();
  133. // the user needs refresh urls in their session to access this mode
  134. if (! isset($_SESSION['post_auth_url']) || ! isset($_SESSION['cancel_auth_url']))
  135. error_500('You may not access this mode directly.');
  136. // try to get the digest headers - what a PITA!
  137. if (function_exists('apache_request_headers') && ini_get('safe_mode') == false) {
  138. $arh = apache_request_headers();
  139. $hdr = $arh['Authorization'];
  140. } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
  141. $hdr = $_SERVER['PHP_AUTH_DIGEST'];
  142. } elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) {
  143. $hdr = $_SERVER['HTTP_AUTHORIZATION'];
  144. } elseif (isset($_ENV['PHP_AUTH_DIGEST'])) {
  145. $hdr = $_ENV['PHP_AUTH_DIGEST'];
  146. } elseif (isset($_REQUEST['auth'])) {
  147. $hdr = stripslashes(urldecode($_REQUEST['auth']));
  148. } else {
  149. $hdr = null;
  150. }
  151. debug('Authorization header: ' . $hdr);
  152. $digest = substr($hdr,0,7) == 'Digest '
  153. ? substr($hdr, strpos($hdr, ' ') + 1)
  154. : $hdr;
  155. $stale = false;
  156. // is the user trying to log in?
  157. if (! is_null($digest) && $profile['authorized'] === false) {
  158. debug('Digest headers: ' . $digest);
  159. $hdr = array();
  160. // decode the Digest authorization headers
  161. preg_match_all('/(\w+)=(?:"([^"]+)"|([^\s,]+))/', $digest, $mtx, PREG_SET_ORDER);
  162. foreach ($mtx as $m)
  163. $hdr[$m[1]] = $m[2] ? $m[2] : $m[3];
  164. debug($hdr, 'Parsed digest headers:');
  165. if (isset($_SESSION['uniqid']) && $hdr['nonce'] != $_SESSION['uniqid']) {
  166. $stale = true;
  167. unset($_SESSION['uniqid']);
  168. }
  169. if (! isset($_SESSION['failures']))
  170. $_SESSION['failures'] = 0;
  171. if ($profile['auth_username'] == $hdr['username'] && ! $stale) {
  172. // the entity body should always be null in this case
  173. $entity_body = '';
  174. $a1 = strtolower($profile['auth_password']);
  175. $a2 = $hdr['qop'] == 'auth-int'
  176. ? md5(implode(':', array($_SERVER['REQUEST_METHOD'], $hdr['uri'], md5($entity_body))))
  177. : md5(implode(':', array($_SERVER['REQUEST_METHOD'], $hdr['uri'])));
  178. $ok = md5(implode(':', array($a1, $hdr['nonce'], $hdr['nc'], $hdr['cnonce'], $hdr['qop'], $a2)));
  179. // successful login!
  180. if ($hdr['response'] == $ok) {
  181. debug('Authentication successful');
  182. debug('User session is: ' . session_id());
  183. $_SESSION['auth_username'] = $hdr['username'];
  184. $_SESSION['auth_url'] = $profile['idp_url'];
  185. $profile['authorized'] = true;
  186. // return to the refresh url if they get in
  187. wrap_refresh($_SESSION['post_auth_url']);
  188. // too many failures
  189. } elseif (strcmp($hdr['nc'], 4) > 0 || $_SESSION['failures'] > 4) {
  190. debug('Too many password failures');
  191. error_get($_SESSION['cancel_auth_url'], 'Too many password failures. Double check your authorization realm. You must restart your browser to try again.');
  192. // failed login
  193. } else {
  194. $_SESSION['failures']++;
  195. debug('Login failed: ' . $hdr['response'] . ' != ' . $ok);
  196. debug('Fail count: ' . $_SESSION['failures']);
  197. }
  198. }
  199. } elseif (is_null($digest) && $profile['authorized'] === false && isset($_SESSION['uniqid'])) {
  200. error_500('Missing expected authorization header.');
  201. }
  202. // if we get this far the user is not authorized, so send the headers
  203. $uid = uniqid(mt_rand(1,9));
  204. $_SESSION['uniqid'] = $uid;
  205. debug('Prompting user to log in. Stale? ' . $stale);
  206. header('HTTP/1.0 401 Unauthorized');
  207. header(sprintf('WWW-Authenticate: Digest qop="auth-int, auth", realm="%s", domain="%s", nonce="%s", opaque="%s", stale="%s", algorithm="MD5"', $profile['auth_realm'], $profile['auth_domain'], $uid, md5($profile['auth_realm']), $stale ? 'true' : 'false'));
  208. $q = strpos($_SESSION['cancel_auth_url'], '?') ? '&' : '?';
  209. wrap_refresh($_SESSION['cancel_auth_url'] . $q . 'openid.mode=cancel');
  210. }
  211. /**
  212. * Handle a consumer's request for cancellation.
  213. */
  214. function cancel_mode () {
  215. wrap_html('Request cancelled.');
  216. }
  217. /**
  218. * Handle a consumer's request to see if the user is authenticated
  219. */
  220. function check_authentication_mode () {
  221. // Validate the request
  222. if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'check_authentication')
  223. error_400();
  224. $assoc_handle = @strlen($_REQUEST['openid_assoc_handle'])
  225. ? $_REQUEST['openid_assoc_handle']
  226. : error_post('Missing assoc_handle');
  227. $sig = @strlen($_REQUEST['openid_sig'])
  228. ? $_REQUEST['openid_sig']
  229. : error_post('Missing sig');
  230. $signed = @strlen($_REQUEST['openid_signed'])
  231. ? $_REQUEST['openid_signed']
  232. : error_post('Missing signed');
  233. // Prepare the return keys
  234. $keys = array(
  235. 'openid.mode' => 'id_res'
  236. );
  237. // Invalidate the assoc handle if we need to
  238. if (@strlen($_REQUEST['openid_invalidate_handle'])) {
  239. destroy_assoc_handle($_REQUEST['openid_invalidate_handle']);
  240. $keys['invalidate_handle'] = $_REQUEST['openid_invalidate_handle'];
  241. }
  242. // Validate the sig by recreating the kv pair and signing
  243. $_REQUEST['openid_mode'] = 'id_res';
  244. $tokens = '';
  245. foreach (explode(',', $signed) as $param) {
  246. $post = preg_replace('/\./', '_', $param);
  247. $tokens .= sprintf("%s:%s\n", $param, $_REQUEST['openid_' . $post]);
  248. }
  249. // Add the sreg stuff, if we've got it
  250. foreach (explode(',', $sreg_required) as $key) {
  251. if (! isset($sreg[$key]))
  252. continue;
  253. $skey = 'sreg.' . $key;
  254. $tokens .= sprintf("%s:%s\n", $skey, $sreg[$key]);
  255. $keys[$skey] = $sreg[$key];
  256. $fields[] = $skey;
  257. }
  258. // Look up the consumer's shared_secret and timeout
  259. list ($shared_secret, $expires) = secret($assoc_handle);
  260. // if I can't verify the assoc_handle, or if it's expired
  261. if ($shared_secret == false || (is_numeric($expires) && $expires < time())) {
  262. $keys['is_valid'] = 'false';
  263. } else {
  264. $ok = base64_encode(hmac($shared_secret, $tokens));
  265. $keys['is_valid'] = ($sig == $ok) ? 'true' : 'false';
  266. }
  267. // Return the keys
  268. wrap_kv($keys);
  269. }
  270. /**
  271. * Handle a consumer's request to see if the end user is logged in
  272. * @global array $known
  273. * @global array $profile
  274. * @global array $sreg
  275. */
  276. function checkid ( $wait ) {
  277. debug("checkid: wait? $wait");
  278. global $known, $profile, $sreg;
  279. // This is a user session
  280. user_session();
  281. // Get the options, use defaults as necessary
  282. $return_to = @strlen($_REQUEST['openid_return_to'])
  283. ? $_REQUEST['openid_return_to']
  284. : error_400('Missing return_to');
  285. $identity = @strlen($_REQUEST['openid_identity'])
  286. ? $_REQUEST['openid_identity']
  287. : error_get($return_to, 'Missing identity');
  288. $assoc_handle = @strlen($_REQUEST['openid_assoc_handle'])
  289. ? $_REQUEST['openid_assoc_handle']
  290. : null;
  291. $trust_root = @strlen($_REQUEST['openid_trust_root'])
  292. ? $_REQUEST['openid_trust_root']
  293. : $return_to;
  294. $sreg_required = @strlen($_REQUEST['openid_sreg_required'])
  295. ? $_REQUEST['openid_sreg_required']
  296. : '';
  297. $sreg_optional = @strlen($_REQUEST['openid_sreg_optional'])
  298. ? $_REQUEST['openid_sreg_optional']
  299. : '';
  300. // required and optional make no difference to us
  301. $sreg_required .= ',' . $sreg_optional;
  302. // make sure i am this identifier
  303. if ($identity != $profile['idp_url'])
  304. error_get($return_to, "Invalid identity: '$identity'");
  305. // begin setting up return keys
  306. $keys = array(
  307. 'mode' => 'id_res'
  308. );
  309. // if the user is not logged in, transfer to the authorization mode
  310. if ($profile['authorized'] === false || $identity != $_SESSION['auth_url']) {
  311. // users can only be logged in to one url at a time
  312. $_SESSION['auth_username'] = null;
  313. $_SESSION['auth_url'] = null;
  314. if ($wait) {
  315. unset($_SESSION['uniqid']);
  316. $_SESSION['cancel_auth_url'] = $return_to;
  317. $_SESSION['post_auth_url'] = $profile['req_url'];
  318. debug('Transferring to authorization mode.');
  319. debug('Cancel URL: ' . $_SESSION['cancel_auth_url']);
  320. debug('Post URL: ' . $_SESSION['post_auth_url']);
  321. $q = strpos($profile['idp_url'], '?') ? '&' : '?';
  322. wrap_refresh($profile['idp_url'] . $q . 'openid.mode=authorize');
  323. } else {
  324. $keys['user_setup_url'] = $profile['idp_url'];
  325. }
  326. // the user is logged in
  327. } else {
  328. // remove the refresh URLs if set
  329. unset($_SESSION['cancel_auth_url']);
  330. unset($_SESSION['post_auth_url']);
  331. // check the assoc handle
  332. list($shared_secret, $expires) = secret($assoc_handle);
  333. // if I can't verify the assoc_handle, or if it's expired
  334. if ($shared_secret == false || (is_numeric($expires) && $expires < time())) {
  335. debug("Session expired or missing key: $expires < " . time());
  336. if ($assoc_handle != null) {
  337. $keys['invalidate_handle'] = $assoc_handle;
  338. destroy_assoc_handle($assoc_handle);
  339. }
  340. $lifetime = time() + $profile['lifetime'];
  341. list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
  342. }
  343. $keys['identity'] = $profile['idp_url'];
  344. $keys['assoc_handle'] = $assoc_handle;
  345. $keys['return_to'] = $return_to;
  346. $fields = array_keys($keys);
  347. $tokens = '';
  348. foreach ($fields as $key)
  349. $tokens .= sprintf("%s:%s\n", $key, $keys[$key]);
  350. // add sreg keys
  351. foreach (explode(',', $sreg_required) as $key) {
  352. if (! isset($sreg[$key]))
  353. continue;
  354. $skey = 'sreg.' . $key;
  355. $tokens .= sprintf("%s:%s\n", $skey, $sreg[$key]);
  356. $keys[$skey] = $sreg[$key];
  357. $fields[] = $skey;
  358. }
  359. $keys['signed'] = implode(',', $fields);
  360. $keys['sig'] = base64_encode(hmac($shared_secret, $tokens));
  361. }
  362. wrap_location($return_to, $keys);
  363. }
  364. /**
  365. * Handle a consumer's request to see if the user is already logged in
  366. */
  367. function checkid_immediate_mode () {
  368. if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'checkid_immediate')
  369. error_500();
  370. checkid(false);
  371. }
  372. /**
  373. * Handle a consumer's request to see if the user is logged in, but be willing
  374. * to wait for them to perform a login if they're not
  375. */
  376. function checkid_setup_mode () {
  377. if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'checkid_setup')
  378. error_500();
  379. checkid(true);
  380. }
  381. /**
  382. * Handle errors
  383. */
  384. function error_mode () {
  385. isset($_REQUEST['openid_error'])
  386. ? wrap_html($_REQUEST['openid_error'])
  387. : error_500();
  388. }
  389. /**
  390. * Show a user if they are logged in or not
  391. * @global array $profile
  392. */
  393. function id_res_mode () {
  394. global $profile;
  395. user_session();
  396. if ($profile['authorized'])
  397. wrap_html('You are logged in as ' . $_SESSION['auth_username']);
  398. wrap_html('You are not logged in');
  399. }
  400. /**
  401. * Allow a user to perform a static login
  402. * @global array $profile
  403. */
  404. function login_mode () {
  405. global $profile;
  406. user_session();
  407. if ($profile['authorized'])
  408. id_res_mode();
  409. $keys = array(
  410. 'mode' => 'checkid_setup',
  411. 'identity' => $profile['idp_url'],
  412. 'return_to' => $profile['idp_url']
  413. );
  414. wrap_location($profile['idp_url'], $keys);
  415. }
  416. /**
  417. * Allow a user to perform a static logout
  418. * @global array $profile
  419. */
  420. function logout_mode () {
  421. global $profile;
  422. user_session();
  423. if (! $profile['authorized'])
  424. wrap_html('You were not logged in');
  425. $_SESSION = array();
  426. session_destroy();
  427. debug('User session destroyed.');
  428. header('HTTP/1.0 401 Unauthorized');
  429. wrap_refresh($profile['idp_url']);
  430. }
  431. /**
  432. * The default information screen
  433. * @global array $profile
  434. */
  435. function no_mode () {
  436. global $profile;
  437. wrap_html('This is an OpenID server endpoint. For more information, see http://openid.net/<br/>Server: <b>' . $profile['idp_url'] . '</b><br/>Realm: <b>' . $profile['php_realm'] . '</b><br/><a href="' . $profile['idp_url'] . '?openid.mode=login">Login</a>' . ($profile['allow_test'] === true ? ' | <a href="' . $profile['idp_url'] . '?openid.mode=test">Test</a>' : null));
  438. }
  439. /**
  440. * Testing for setup
  441. * @global array $profile
  442. */
  443. function test_mode () {
  444. global $profile, $p, $g;
  445. if ($profile['allow_test'] != true)
  446. error_403();
  447. @ini_set('max_execution_time', 180);
  448. $test_expire = time() + 120;
  449. $test_ss_enc = 'W7hvmld2yEYdDb0fHfSkKhQX+PM=';
  450. $test_ss = base64_decode($test_ss_enc);
  451. $test_token = "alpha:bravo\ncharlie:delta\necho:foxtrot";
  452. $test_server_private = '11263846781670293092494395517924811173145217135753406847875706165886322533899689335716152496005807017390233667003995430954419468996805220211293016296351031812246187748601293733816011832462964410766956326501185504714561648498549481477143603650090931135412673422192550825523386522507656442905243832471167330268';
  453. $test_client_public = base64_decode('AL63zqI5a5p8HdXZF5hFu8p+P9GOb816HcHuvNOhqrgkKdA3fO4XEzmldlb37nv3+xqMBgWj6gxT7vfuFerEZLBvuWyVvR7IOGZmx0BAByoq3fxYd3Fpe2Coxngs015vK37otmH8e83YyyGo5Qua/NAf13yz1PVuJ5Ctk7E+YdVc');
  454. $res = array();
  455. // bcmath
  456. $res['bcmath'] = extension_loaded('bcmath')
  457. ? 'pass' : 'warn - not loaded';
  458. // gmp
  459. if ($profile['allow_gmp']) {
  460. $res['gmp'] = extension_loaded('gmp')
  461. ? 'pass' : 'warn - not loaded';
  462. } else {
  463. $res['gmp'] = 'pass - n/a';
  464. }
  465. // sys_get_temp_dir
  466. $res['logfile'] = is_writable($profile['logfile'])
  467. ? 'pass' : "warn - log is not writable";
  468. // session & new_assoc
  469. user_session();
  470. list($test_assoc, $test_new_ss) = new_assoc($test_expire);
  471. $res['session'] = ($test_assoc != session_id())
  472. ? 'pass' : 'fail';
  473. // secret
  474. @session_unregister('shared_secret');
  475. list($check, $check2) = secret($test_assoc);
  476. $res['secret'] = ($check == $test_new_ss)
  477. ? 'pass' : 'fail';
  478. // expire
  479. $res['expire'] = ($check2 <= $test_expire)
  480. ? 'pass' : 'fail';
  481. // base64
  482. $res['base64'] = (base64_encode($test_ss) == $test_ss_enc)
  483. ? 'pass' : 'fail';
  484. // hmac
  485. $test_sig = base64_decode('/VXgHvZAOdoz/OTa5+XJXzSGhjs=');
  486. $check = hmac($test_ss, $test_token);
  487. $res['hmac'] = ($check == $test_sig)
  488. ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
  489. if ($profile['use_bigmath']) {
  490. // bigmath powmod
  491. $test_server_public = '102773334773637418574009974502372885384288396853657336911033649141556441102566075470916498748591002884433213640712303846640842555822818660704173387461364443541327856226098159843042567251113889701110175072389560896826887426539315893475252988846151505416694218615764823146765717947374855806613410142231092856731';
  492. $check = bmpowmod($g, $test_server_private, $p);
  493. $res['bmpowmod-1'] = ($check == $test_server_public)
  494. ? 'pass' : sprintf("fail - '%s'", $check);
  495. // long
  496. $test_client_long = '133926731803116519408547886573524294471756220428015419404483437186057383311250738749035616354107518232016420809434801736658109316293127101479053449990587221774635063166689561125137927607200322073086097478667514042144489248048756916881344442393090205172004842481037581607299263456852036730858519133859409417564';
  497. $res['long'] = (long($test_client_public) == $test_client_long)
  498. ? 'pass' : 'fail';
  499. // bigmath powmod 2
  500. $test_client_share = '19333275433742428703546496981182797556056709274486796259858099992516081822015362253491867310832140733686713353304595602619444380387600756677924791671971324290032515367930532292542300647858206600215875069588627551090223949962823532134061941805446571307168890255137575975911397744471376862555181588554632928402';
  501. $check = bmpowmod($test_client_long, $test_server_private, $p);
  502. $res['bmpowmod-2'] = ($check == $test_client_share)
  503. ? 'pass' : sprintf("fail - '%s'", $check);
  504. // bin
  505. $test_client_mac_s1 = base64_decode('G4gQQkYM6QmAzhKbVKSBahFesPL0nL3F2MREVwEtnVRRYI0ifl9zmPklwTcvURt3QTiGBd+9Dn3ESLk5qka6IO5xnILcIoBT8nnGVPiOZvTygfuzKp4tQ2mXuIATJoa7oXRGmBWtlSdFapH5Zt6NJj4B83XF/jzZiRwdYuK4HJI=');
  506. $check = bin($test_client_share);
  507. $res['bin'] = ($check == $test_client_mac_s1)
  508. ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
  509. } else {
  510. $res['bigmath'] = 'fail - big math functions are not available.';
  511. }
  512. // sha1_20
  513. $test_client_mac_s1 = base64_decode('G4gQQkYM6QmAzhKbVKSBahFesPL0nL3F2MREVwEtnVRRYI0ifl9zmPklwTcvURt3QTiGBd+9Dn3ESLk5qka6IO5xnILcIoBT8nnGVPiOZvTygfuzKp4tQ2mXuIATJoa7oXRGmBWtlSdFapH5Zt6NJj4B83XF/jzZiRwdYuK4HJI=');
  514. $test_client_mac_s2 = base64_decode('0Mb2t9d/HvAZyuhbARJPYdx3+v4=');
  515. $check = sha1_20($test_client_mac_s1);
  516. $res['sha1_20'] = ($check == $test_client_mac_s2)
  517. ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
  518. // x_or
  519. $test_client_mac_s3 = base64_decode('i36ZLYAJ1rYEx1VEHObrS8hgAg0=');
  520. $check = x_or($test_client_mac_s2, $test_ss);
  521. $res['x_or'] = ($check == $test_client_mac_s3)
  522. ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
  523. $out = "<table border=1 cellpadding=4>\n";
  524. foreach ($res as $test => $stat) {
  525. $code = substr($stat, 0, 4);
  526. $color = ($code == 'pass') ? '#9f9'
  527. : (($code == 'warn') ? '#ff9' : '#f99');
  528. $out .= sprintf("<tr><th>%s</th><td style='background:%s'>%s</td></tr>\n", $test, $color, $stat);
  529. }
  530. $out .= "</table>";
  531. wrap_html( $out );
  532. }
  533. // Support functions
  534. /**
  535. * Prefix the keys of an array with 'openid.'
  536. * @param array $array
  537. * @return array
  538. */
  539. function append_openid ($array) {
  540. $keys = array_keys($array);
  541. $vals = array_values($array);
  542. $r = array();
  543. for ($i=0; $i<sizeof($keys); $i++)
  544. $r['openid.' . $keys[$i]] = $vals[$i];
  545. return $r;
  546. }
  547. /**
  548. * Create a big math addition function
  549. * @param string $l
  550. * @param string $r
  551. * @return string
  552. * @url http://www.icosaedro.it/bigint Inspired by
  553. */
  554. function bmadd($l, $r) {
  555. if (function_exists('bcadd'))
  556. return bcadd($l, $r);
  557. global $profile;
  558. if ($profile['use_gmp'])
  559. return gmp_strval(gmp_add($l, $r));
  560. $l = strval($l); $r = strval($r);
  561. $ll = strlen($l); $rl = strlen($r);
  562. if ($ll < $rl) {
  563. $l = str_repeat("0", $rl-$ll) . $l;
  564. $o = $rl;
  565. } elseif ( $ll > $rl ) {
  566. $r = str_repeat("0", $ll-$rl) . $r;
  567. $o = $ll;
  568. } else {
  569. $o = $ll;
  570. }
  571. $v = '';
  572. $carry = 0;
  573. for ($i = $o-1; $i >= 0; $i--) {
  574. $d = (int)$l[$i] + (int)$r[$i] + $carry;
  575. if ($d <= 9) {
  576. $carry = 0;
  577. } else {
  578. $carry = 1;
  579. $d -= 10;
  580. }
  581. $v = (string) $d . $v;
  582. }
  583. if ($carry > 0)
  584. $v = "1" . $v;
  585. return $v;
  586. }
  587. /**
  588. * Create a big math comparison function
  589. * @param string $l
  590. * @param string $r
  591. * @return string
  592. */
  593. function bmcomp($l, $r) {
  594. if (function_exists('bccomp'))
  595. return bccomp($l, $r);
  596. global $profile;
  597. if ($profile['use_gmp'])
  598. return gmp_strval(gmp_cmp($l, $r));
  599. $l = strval($l); $r = strval($r);
  600. $ll = strlen($l); $lr = strlen($r);
  601. if ($ll != $lr)
  602. return ($ll > $lr) ? 1 : -1;
  603. return strcmp($l, $r);
  604. }
  605. /**
  606. * Create a big math division function
  607. * @param string $l
  608. * @param string $r
  609. * @param int $z
  610. * @return string
  611. * @url http://www.icosaedro.it/bigint Inspired by
  612. */
  613. function bmdiv($l, $r, $z = 0) {
  614. if (function_exists('bcdiv'))
  615. return ($z == 0) ? bcdiv($l, $r) : bcmod($l, $r);
  616. global $profile;
  617. if ($profile['use_gmp'])
  618. return gmp_strval(($z == 0) ? gmp_div_q($l, $r) : gmp_mod($l, $r));
  619. $l = strval($l); $r = strval($r);
  620. $v = '0';
  621. while (true) {
  622. if( bmcomp($l, $r) < 0 )
  623. break;
  624. $delta = strlen($l) - strlen($r);
  625. if ($delta >= 1) {
  626. $zeroes = str_repeat("0", $delta);
  627. $r2 = $r . $zeroes;
  628. if (strcmp($l, $r2) >= 0) {
  629. $v = bmadd($v, "1" . $zeroes);
  630. $l = bmsub($l, $r2);
  631. } else {
  632. $zeroes = str_repeat("0", $delta - 1);
  633. $v = bmadd($v, "1" . $zeroes);
  634. $l = bmsub($l, $r . $zeroes);
  635. }
  636. } else {
  637. $l = bmsub($l, $r);
  638. $v = bmadd($v, "1");
  639. }
  640. }
  641. return ($z == 0) ? $v : $l;
  642. }
  643. /**
  644. * Create a big math multiplication function
  645. * @param string $l
  646. * @param string $r
  647. * @return string
  648. * @url http://www.icosaedro.it/bigint Inspired by
  649. */
  650. function bmmul($l, $r) {
  651. if (function_exists('bcmul'))
  652. return bcmul($l, $r);
  653. global $profile;
  654. if ($profile['use_gmp'])
  655. return gmp_strval(gmp_mul($l, $r));
  656. $l = strval($l); $r = strval($r);
  657. $v = '0';
  658. $z = '';
  659. for( $i = strlen($r)-1; $i >= 0; $i-- ){
  660. $bd = (int) $r[$i];
  661. $carry = 0;
  662. $p = "";
  663. for( $j = strlen($l)-1; $j >= 0; $j-- ){
  664. $ad = (int) $l[$j];
  665. $pd = $ad * $bd + $carry;
  666. if( $pd <= 9 ){
  667. $carry = 0;
  668. } else {
  669. $carry = (int) ($pd / 10);
  670. $pd = $pd % 10;
  671. }
  672. $p = (string) $pd . $p;
  673. }
  674. if( $carry > 0 )
  675. $p = (string) $carry . $p;
  676. $p = $p . $z;
  677. $z .= "0";
  678. $v = bmadd($v, $p);
  679. }
  680. return $v;
  681. }
  682. /**
  683. * Create a big math modulus function
  684. * @param string $value
  685. * @param string $mod
  686. * @return string
  687. */
  688. function bmmod( $value, $mod ) {
  689. if (function_exists('bcmod'))
  690. return bcmod($value, $mod);
  691. global $profile;
  692. if ($profile['use_gmp'])
  693. return gmp_strval(gmp_mod($value, $mod));
  694. $r = bmdiv($value, $mod, 1);
  695. return $r;
  696. }
  697. /**
  698. * Create a big math power function
  699. * @param string $value
  700. * @param string $exponent
  701. * @return string
  702. */
  703. function bmpow ($value, $exponent) {
  704. if (function_exists('bcpow'))
  705. return bcpow($value, $exponent);
  706. global $profile;
  707. if ($profile['use_gmp'])
  708. return gmp_strval(gmp_pow($value, $exponent));
  709. $r = '1';
  710. while ($exponent) {
  711. $r = bmmul($r, $value, 100);
  712. $exponent--;
  713. }
  714. return (string)rtrim($r, '0.');
  715. }
  716. /**
  717. * Create a big math 'powmod' function
  718. * @param string $value
  719. * @param string $exponent
  720. * @param string $mod
  721. * @return string
  722. * @url http://php.net/manual/en/function.bcpowmod.php#72704 Borrowed from
  723. */
  724. function bmpowmod ($value, $exponent, $mod) {
  725. if (function_exists('bcpowmod'))
  726. return bcpowmod($value, $exponent, $mod);
  727. global $profile;
  728. if ($profile['use_gmp'])
  729. return gmp_strval(gmp_powm($value, $exponent, $mod));
  730. $r = '';
  731. while ($exponent != '0') {
  732. $t = bmmod($exponent, '4096');
  733. $r = substr("000000000000" . decbin(intval($t)), -12) . $r;
  734. $exponent = bmdiv($exponent, '4096');
  735. }
  736. $r = preg_replace("!^0+!","",$r);
  737. if ($r == '')
  738. $r = '0';
  739. $value = bmmod($value, $mod);
  740. $erb = strrev($r);
  741. $q = '1';
  742. $a[0] = $value;
  743. for ($i = 1; $i < strlen($erb); $i++) {
  744. $a[$i] = bmmod( bmmul($a[$i-1], $a[$i-1]), $mod );
  745. }
  746. for ($i = 0; $i < strlen($erb); $i++) {
  747. if ($erb[$i] == "1") {
  748. $q = bmmod( bmmul($q, $a[$i]), $mod );
  749. }
  750. }
  751. return($q);
  752. }
  753. /**
  754. * Create a big math subtraction function
  755. * @param string $l
  756. * @param string $r
  757. * @return string
  758. * @url http://www.icosaedro.it/bigint Inspired by
  759. */
  760. function bmsub($l, $r) {
  761. if (function_exists('bcsub'))
  762. return bcsub($l, $r);
  763. global $profile;
  764. if ($profile['use_gmp'])
  765. return gmp_strval(gmp_sub($l, $r));
  766. $l = strval($l); $r = strval($r);
  767. $ll = strlen($l); $rl = strlen($r);
  768. if ($ll < $rl) {
  769. $l = str_repeat("0", $rl-$ll) . $l;
  770. $o = $rl;
  771. } elseif ( $ll > $rl ) {
  772. $r = str_repeat("0", $ll-$rl) . (string)$r;
  773. $o = $ll;
  774. } else {
  775. $o = $ll;
  776. }
  777. if (strcmp($l, $r) >= 0) {
  778. $sign = '';
  779. } else {
  780. $x = $l; $l = $r; $r = $x;
  781. $sign = '-';
  782. }
  783. $v = '';
  784. $carry = 0;
  785. for ($i = $o-1; $i >= 0; $i--) {
  786. $d = ($l[$i] - $r[$i]) - $carry;
  787. if ($d < 0) {
  788. $carry = 1;
  789. $d += 10;
  790. } else {
  791. $carry = 0;
  792. }
  793. $v = (string) $d . $v;
  794. }
  795. return $sign . ltrim($v, '0');
  796. }
  797. /**
  798. * Get a binary value
  799. * @param integer $n
  800. * @return string
  801. * @url http://openidenabled.com Borrowed from PHP-OpenID
  802. */
  803. function bin ($n) {
  804. $bytes = array();
  805. while (bmcomp($n, 0) > 0) {
  806. array_unshift($bytes, bmmod($n, 256));
  807. $n = bmdiv($n, bmpow(2,8));
  808. }
  809. if ($bytes && ($bytes[0] > 127))
  810. array_unshift($bytes, 0);
  811. $b = '';
  812. foreach ($bytes as $byte)
  813. $b .= pack('C', $byte);
  814. return $b;
  815. }
  816. /**
  817. * Debug logging
  818. * @param mixed $x
  819. * @param string $m
  820. */
  821. function debug ($x, $m = null) {
  822. global $profile;
  823. if (! isset($profile['debug']) || $profile['debug'] === false)
  824. return true;
  825. if (! is_writable(dirname($profile['logfile'])) &! is_writable($profile['logfile']))
  826. error_500('Cannot write to debug log: ' . $profile['logfile']);
  827. if (is_array($x)) {
  828. ob_start();
  829. print_r($x);
  830. $x = $m . ($m != null ? "\n" : '') . ob_get_clean();
  831. } else {
  832. $x .= "\n";
  833. }
  834. error_log($x . "\n", 3, $profile['logfile']);
  835. }
  836. /**
  837. * Destroy a consumer's assoc handle
  838. * @param string $id
  839. */
  840. function destroy_assoc_handle ( $id ) {
  841. debug("Destroying session: $id");
  842. $sid = session_id();
  843. session_write_close();
  844. session_id($id);
  845. session_start();
  846. session_destroy();
  847. session_id($sid);
  848. session_start();
  849. }
  850. /**
  851. * Return an error message to the user
  852. * @param string $message
  853. */
  854. function error_400 ( $message = 'Bad Request' ) {
  855. header("HTTP/1.1 400 Bad Request");
  856. wrap_html($message);
  857. }
  858. /**
  859. * Return an error message to the user
  860. * @param string $message
  861. */
  862. function error_403 ( $message = 'Forbidden' ) {
  863. header("HTTP/1.1 403 Forbidden");
  864. wrap_html($message);
  865. }
  866. /**
  867. * Return an error message to the user
  868. * @param string $message
  869. */
  870. function error_500 ( $message = 'Internal Server Error' ) {
  871. header("HTTP/1.1 500 Internal Server Error");
  872. wrap_html($message);
  873. }
  874. /**
  875. * Return an error message to the consumer
  876. * @param string $message
  877. */
  878. function error_get ( $url, $message = 'Bad Request') {
  879. wrap_location($url, array('mode' => 'error', 'error' => $message));
  880. }
  881. /**
  882. * Return an error message to the consumer
  883. * @param string $message
  884. */
  885. function error_post ( $message = 'Bad Request' ) {
  886. header("HTTP/1.1 400 Bad Request");
  887. echo ('error:' . $message);
  888. exit(0);
  889. }
  890. /**
  891. * Do an HMAC
  892. * @param string $key
  893. * @param string $data
  894. * @param string $hash
  895. * @return string
  896. * @url http://php.net/manual/en/function.sha1.php#39492 Borrowed from
  897. */
  898. function hmac($key, $data, $hash = 'sha1_20') {
  899. $blocksize=64;
  900. if (strlen($key) > $blocksize)
  901. $key = $hash($key);
  902. $key = str_pad($key, $blocksize,chr(0x00));
  903. $ipad = str_repeat(chr(0x36),$blocksize);
  904. $opad = str_repeat(chr(0x5c),$blocksize);
  905. $h1 = $hash(($key ^ $ipad) . $data);
  906. $hmac = $hash(($key ^ $opad) . $h1);
  907. return $hmac;
  908. }
  909. if (! function_exists('http_build_query')) {
  910. /**
  911. * Create function if missing
  912. * @param array $array
  913. * @return string
  914. */
  915. function http_build_query ($array) {
  916. $r = array();
  917. foreach ($array as $key => $val)
  918. $r[] = sprintf('%s=%s', urlencode($key), urlencode($val));
  919. return implode('&', $r);
  920. }}
  921. /**
  922. * Turn a binary back into a long
  923. * @param string $b
  924. * @return integer
  925. * @url http://openidenabled.com Borrowed from PHP-OpenID
  926. */
  927. function long($b) {
  928. $bytes = array_merge(unpack('C*', $b));
  929. $n = 0;
  930. foreach ($bytes as $byte) {
  931. $n = bmmul($n, bmpow(2,8));
  932. $n = bmadd($n, $byte);
  933. }
  934. return $n;
  935. }
  936. /**
  937. * Create a new consumer association
  938. * @param integer $expiration
  939. * @return array
  940. */
  941. function new_assoc ( $expiration ) {
  942. if (is_array($_SESSION)) {
  943. $sid = session_id();
  944. $dat = session_encode();
  945. session_write_close();
  946. }
  947. session_start();
  948. session_regenerate_id('false');
  949. $id = session_id();
  950. $shared_secret = new_secret();
  951. debug('Started new assoc session: ' . $id);
  952. $_SESSION = array();
  953. $_SESSION['expiration'] = $expiration;
  954. $_SESSION['shared_secret'] = base64_encode($shared_secret);
  955. session_write_close();
  956. if (isset($sid)) {
  957. session_id($sid);
  958. session_start();
  959. $_SESSION = array();
  960. session_decode($dat);
  961. }
  962. return array($id, $shared_secret);
  963. }
  964. /**
  965. * Create a new shared secret
  966. * @return string
  967. */
  968. function new_secret () {
  969. $r = '';
  970. for($i=0; $i<20; $i++)
  971. $r .= chr(mt_rand(0, 255));
  972. debug("Generated new key: hash = '" . md5($r) . "', length = '" . strlen($r) . "'");
  973. return $r;
  974. }
  975. /**
  976. * Random number generation
  977. * @param integer max
  978. * @return integer
  979. */
  980. function random ( $max ) {
  981. if (strlen($max) < 4)
  982. return mt_rand(1, $max - 1);
  983. $r = '';
  984. for($i=1; $i<strlen($max) - 1; $i++)
  985. $r .= mt_rand(0,9);
  986. $r .= mt_rand(1,9);
  987. return $r;
  988. }
  989. /**
  990. * Get the shared secret and expiration time for the specified assoc_handle
  991. * @param string $handle assoc_handle to look up
  992. * @return array (shared_secret, expiration_time)
  993. */
  994. function secret ( $handle ) {
  995. if (! preg_match('/^\w+$/', $handle))
  996. return array(false, 0);
  997. if (is_array($_SESSION)) {
  998. $sid = session_id();
  999. $dat = session_encode();
  1000. session_write_close();
  1001. }
  1002. session_id($handle);
  1003. session_start();
  1004. debug('Started session to acquire key: ' . session_id());
  1005. $secret = session_is_registered('shared_secret')
  1006. ? base64_decode($_SESSION['shared_secret'])
  1007. : false;
  1008. $expiration = session_is_registered('expiration')
  1009. ? $_SESSION['expiration']
  1010. : null;
  1011. session_write_close();
  1012. if (isset($sid)) {
  1013. session_id($sid);
  1014. session_start();
  1015. $_SESSION = array();
  1016. session_decode($dat);
  1017. }
  1018. debug("Found key: hash = '" . md5($secret) . "', length = '" . strlen($secret) . "', expiration = '$expiration'");
  1019. return array($secret, $expiration);
  1020. }
  1021. /**
  1022. * Do an internal self check
  1023. * @global array $profile
  1024. * @global array $sreg
  1025. */
  1026. function self_check () {
  1027. global $profile, $sreg;
  1028. if (! isset($profile) || ! is_array($profile))
  1029. error_500('No configuration found, you shouldn\'t access this file directly.');
  1030. if (version_compare(phpversion(), '4.2.0', 'lt'))
  1031. error_500('The required minimum version of PHP is 4.2.0, you are running ' . phpversion());
  1032. $extensions = array('session', 'pcre');
  1033. foreach ($extensions as $x) {
  1034. if (! extension_loaded($x))
  1035. @dl($x);
  1036. if (! extension_loaded($x))
  1037. error_500("Required extension '$x' is missing.");
  1038. }
  1039. $keys = array('auth_username', 'auth_password');
  1040. foreach ($keys as $key) {
  1041. if (! array_key_exists($key, $profile))
  1042. error_500("'$key' is missing from your profile.");
  1043. }
  1044. if (! is_writable(ini_get('session.save_path')))
  1045. error_500("PHP cannot save sessions.");
  1046. if (! isset($sreg) || ! is_array($sreg))
  1047. $sreg = array();
  1048. }
  1049. /**
  1050. * Do SHA1 20 byte encryption
  1051. * @param string $v
  1052. * @return string
  1053. * @url http://openidenabled.com Borrowed from PHP-OpenID
  1054. */
  1055. function sha1_20 ($v) {
  1056. if (version_compare(phpversion(), '5.0.0', 'ge'))
  1057. return sha1($v, true);
  1058. $hex = sha1($v);
  1059. $r = '';
  1060. for ($i = 0; $i < 40; $i += 2) {
  1061. $hexcode = substr($hex, $i, 2);
  1062. $charcode = base_convert($hexcode, 16, 10);
  1063. $r .= chr($charcode);
  1064. }
  1065. return $r;
  1066. }
  1067. if (! function_exists('sys_get_temp_dir') && ini_get('open_basedir') == false) {
  1068. /**
  1069. * Create function if missing
  1070. * @return string
  1071. */
  1072. function sys_get_temp_dir () {
  1073. $keys = array('TMP', 'TMPDIR', 'TEMP');
  1074. foreach ($keys as $key) {
  1075. if (isset($_ENV[$key]) && is_dir($_ENV[$key]) && is_writable($_ENV[$key]))
  1076. return realpath($_ENV[$key]);
  1077. }
  1078. $tmp = tempnam(false, null);
  1079. if (file_exists($tmp)) {
  1080. $dir = realpath(dirname($tmp));
  1081. unlink($tmp);
  1082. return realpath($dir);
  1083. }
  1084. return realpath(dirname(__FILE__));
  1085. }} elseif (! function_exists('sys_get_temp_dir')) {
  1086. function sys_get_temp_dir () {
  1087. return realpath(dirname(__FILE__));
  1088. }}
  1089. /**
  1090. * Create a user session
  1091. * @global array $profile
  1092. * @global array $proto
  1093. */
  1094. function user_session () {
  1095. global $proto, $profile;
  1096. session_name('phpMyID_Server');
  1097. @session_start();
  1098. $profile['authorized'] = (isset($_SESSION['auth_username'])
  1099. && $_SESSION['auth_username'] == $profile['auth_username'])
  1100. ? true
  1101. : false;
  1102. debug('Started user session: ' . session_id() . ' Auth? ' . $profile['authorized']);
  1103. }
  1104. /**
  1105. * Return HTML
  1106. * @global string $charset
  1107. * @param string $message
  1108. */
  1109. function wrap_html ( $message ) {
  1110. global $charset, $profile;
  1111. header('Content-Type: text/html; charset=' . $charset);
  1112. echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  1113. <html>
  1114. <head>
  1115. <title>phpMyID</title>
  1116. <link rel="openid.server" href="' . $profile['req_url'] . '" />
  1117. <link rel="openid.delegate" href="' . $profile['idp_url'] . '" />
  1118. <meta name="charset" content="' . $charset . '" />
  1119. <meta name="robots" content="noindex,nofollow" />
  1120. </head>
  1121. <body>
  1122. <p>' . $message . '</p>
  1123. </body>
  1124. </html>
  1125. ';
  1126. exit(0);
  1127. }
  1128. /**
  1129. * Return a key-value pair in plain text
  1130. * @global string $charset
  1131. * @param array $keys
  1132. */
  1133. function wrap_kv ( $keys ) {
  1134. global $charset;
  1135. debug($keys, 'Wrapped key/vals');
  1136. header('Content-Type: text/plain; charset=' . $charset);
  1137. foreach ($keys as $key => $value)
  1138. printf("%s:%s\n", $key, $value);
  1139. exit(0);
  1140. }
  1141. /**
  1142. * Return an HTML refresh, with OpenID keys
  1143. * @param string $url
  1144. * @param array @keys
  1145. */
  1146. function wrap_location ($url, $keys) {
  1147. $keys = append_openid($keys);
  1148. debug($keys, 'Location keys');
  1149. $q = strpos($url, '?') ? '&' : '?';
  1150. header('Location: ' . $url . $q . http_build_query($keys));
  1151. debug('Location: ' . $url . $q . http_build_query($keys));
  1152. exit(0);
  1153. }
  1154. /**
  1155. * Return an HTML refresh
  1156. * @global string $charset
  1157. * @param string $url
  1158. */
  1159. function wrap_refresh ($url) {
  1160. global $charset;
  1161. header('Content-Type: text/html; charset=' . $charset);
  1162. echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  1163. <html>
  1164. <head>
  1165. <title>phpMyID</title>
  1166. <meta http-equiv="refresh" content="0;url=' . $url . '">
  1167. </head>
  1168. <body>
  1169. <p>Redirecting to <a href="' . $url . '">' . $url . '</a></p>
  1170. </body>
  1171. </html>
  1172. ';
  1173. debug('Refresh: ' . $url);
  1174. exit(0);
  1175. }
  1176. /**
  1177. * Implement binary x_or
  1178. * @param string $a
  1179. * @param string $b
  1180. * @return string
  1181. */
  1182. function x_or ($a, $b) {
  1183. $r = "";
  1184. for ($i = 0; $i < strlen($b); $i++)
  1185. $r .= $a[$i] ^ $b[$i];
  1186. debug("Xor size: " . strlen($r));
  1187. return $r;
  1188. }
  1189. /*
  1190. * App Initialization
  1191. */
  1192. // Determine the charset to use
  1193. $GLOBALS['charset'] = 'iso-8859-1';
  1194. // Set the internal encoding
  1195. if (function_exists('mb_internal_encoding'))
  1196. mb_internal_encoding($charset);
  1197. // Do a check to be sure everything is set up correctly
  1198. self_check();
  1199. /**
  1200. * Determine the HTTP request port
  1201. * @name $port
  1202. * @global integer $GLOBALS['port']
  1203. */
  1204. $GLOBALS['port'] = ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' && $_SERVER['SERVER_PORT'] == 443)
  1205. || $_SERVER['SERVER_PORT'] == 80)
  1206. ? ''
  1207. : ':' . $_SERVER['SERVER_PORT'];
  1208. /**
  1209. * Determine the HTTP request protocol
  1210. * @name $proto
  1211. * @global string $GLOBALS['proto']
  1212. */
  1213. $GLOBALS['proto'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
  1214. // Set the authorization state - DO NOT OVERRIDE
  1215. $profile['authorized'] = false;
  1216. // Set a default IDP URL
  1217. if (! array_key_exists('idp_url', $profile))
  1218. $profile['idp_url'] = sprintf("%s://%s%s%s",
  1219. $proto,
  1220. $_SERVER['SERVER_NAME'],
  1221. $port,
  1222. $_SERVER['PHP_SELF']);
  1223. // Determine the requested URL - DO NOT OVERRIDE
  1224. $profile['req_url'] = sprintf("%s://%s%s%s",
  1225. $proto,
  1226. $_SERVER['SERVER_NAME'],
  1227. $port,
  1228. $_SERVER["REQUEST_URI"]);
  1229. // Set the default allowance for testing
  1230. if (! array_key_exists('allow_test', $profile))
  1231. $profile['allow_test'] = false;
  1232. // Set the default allowance for gmp
  1233. if (! array_key_exists('allow_gmp', $profile))
  1234. $profile['allow_gmp'] = false;
  1235. // Set the default force bigmath - BAD IDEA to override this
  1236. if (! array_key_exists('force_bigmath', $profile))
  1237. $profile['force_bigmath'] = false;
  1238. // Determine if GMP is usable
  1239. $profile['use_gmp'] = (extension_loaded('gmp') && $profile['allow_gmp']) ? true : false;
  1240. // Determine if I can perform big math functions
  1241. $profile['use_bigmath'] = (extension_loaded('bcmath') || $profile['use_gmp'] || $profile['force_bigmath']) ? true : false;
  1242. // Set a default authentication domain
  1243. if (! array_key_exists('auth_domain', $profile))
  1244. $profile['auth_domain'] = $profile['req_url'] . ' ' . $profile['idp_url'];
  1245. // Set a default authentication realm
  1246. if (! array_key_exists('auth_realm', $profile))
  1247. $profile['auth_realm'] = 'phpMyID';
  1248. // Determine the realm for digest authentication - DO NOT OVERRIDE
  1249. $profile['php_realm'] = $profile['auth_realm'] . (ini_get('safe_mode') ? '-' . getmyuid() : '');
  1250. // Set a default lifetime - the lesser of GC and cache time
  1251. if (! array_key_exists('lifetime', $profile)) {
  1252. $sce = session_cache_expire() * 60;
  1253. $gcm = ini_get('session.gc_maxlifetime');
  1254. $profile['lifetime'] = $sce < $gcm ? $sce : $gcm;
  1255. }
  1256. // Set a default log file
  1257. if (! array_key_exists('logfile', $profile))
  1258. $profile['logfile'] = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $profile['auth_realm'] . '.debug.log';
  1259. // Decide which runmode, based on user request or default
  1260. $run_mode = (isset($_REQUEST['openid_mode'])
  1261. && in_array($_REQUEST['openid_mode'], $known['openid_modes']))
  1262. ? $_REQUEST['openid_mode']
  1263. : 'no';
  1264. // Run in the determined runmode
  1265. debug("Run mode: $run_mode at: " . time());
  1266. debug($_REQUEST, 'Request params');
  1267. eval($run_mode . '_mode();');
  1268. ?>