328 </td> |
329 </td> |
329 </tr> |
330 </tr> |
330 <?php |
331 <?php |
331 } |
332 } |
332 ?> |
333 ?> |
333 <tr> |
334 <?php |
334 <td class="row3" colspan="3"> |
335 if ( $level <= USER_LEVEL_MEMBER && ( !isset($_GET['use_crypt']) || ( isset($_GET['use_crypt']) && $_GET['use_crypt']!='0' ) ) ) |
335 <?php |
336 { |
336 if ( $level <= USER_LEVEL_MEMBER && ( !isset($_GET['use_crypt']) || ( isset($_GET['use_crypt']) && $_GET['use_crypt']!='0' ) ) ) |
337 echo '<tr> |
337 { |
338 <td class="row3" colspan="3">'; |
338 $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : ''; |
339 |
339 $nocrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=0", true); |
340 $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : ''; |
340 echo '<p><b>' . $lang->get('user_login_nocrypt_title') . '</b> ' . $lang->get('user_login_nocrypt_body', array('nocrypt_link' => $nocrypt_link)) . '</p>'; |
341 $nocrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=0", true); |
341 echo '<p>' . $lang->get('user_login_nocrypt_countrylist') . '</p>'; |
342 echo '<p><b>' . $lang->get('user_login_nocrypt_title') . '</b> ' . $lang->get('user_login_nocrypt_body', array('nocrypt_link' => $nocrypt_link)) . '</p>'; |
342 } |
343 echo '<p>' . $lang->get('user_login_nocrypt_countrylist') . '</p>'; |
343 else if ( $level <= USER_LEVEL_MEMBER && ( isset($_GET['use_crypt']) && $_GET['use_crypt']=='0' ) ) |
344 |
344 { |
345 echo ' </td> |
345 $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : ''; |
346 </tr>'; |
346 $usecrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=1", true); |
347 } |
347 echo '<p><b>' . $lang->get('user_login_usecrypt_title') . '</b> ' . $lang->get('user_login_usecrypt_body', array('usecrypt_link' => $usecrypt_link)) . '</p>'; |
348 else if ( $level <= USER_LEVEL_MEMBER && ( isset($_GET['use_crypt']) && $_GET['use_crypt']=='0' ) ) |
348 echo '<p>' . $lang->get('user_login_usecrypt_countrylist') . '</p>'; |
349 { |
349 } |
350 echo '<tr> |
350 ?> |
351 <td class="row3" colspan="3">'; |
351 </td> |
352 |
352 </tr> |
353 $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : ''; |
|
354 $usecrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=1", true); |
|
355 echo '<p><b>' . $lang->get('user_login_usecrypt_title') . '</b> ' . $lang->get('user_login_usecrypt_body', array('usecrypt_link' => $usecrypt_link)) . '</p>'; |
|
356 echo '<p>' . $lang->get('user_login_usecrypt_countrylist') . '</p>'; |
|
357 |
|
358 echo ' </td> |
|
359 </tr>'; |
|
360 } |
|
361 ?> |
|
362 |
353 <tr> |
363 <tr> |
354 <th colspan="3" style="text-align: center" class="subhead"><input type="submit" name="login" value="Log in" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '3' : '2'; ?>" /></th> |
364 <th colspan="3" style="text-align: center" class="subhead"><input type="submit" name="login" value="Log in" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '3' : '2'; ?>" /></th> |
355 </tr> |
365 </tr> |
356 </table> |
366 </table> |
357 </div> |
367 </div> |
367 <?php else: ?> |
377 <?php else: ?> |
368 <script type="text/javascript"> |
378 <script type="text/javascript"> |
369 document.forms.loginform.pass.focus(); |
379 document.forms.loginform.pass.focus(); |
370 </script> |
380 </script> |
371 <?php endif; ?> |
381 <?php endif; ?> |
|
382 <?php |
|
383 // 1.1.4 |
|
384 |
|
385 require_once( ENANO_ROOT . '/includes/diffiehellman.php' ); |
|
386 |
|
387 global $dh_supported, $_math; |
|
388 if ( $dh_supported ) |
|
389 { |
|
390 $dh_key_priv = dh_gen_private(); |
|
391 $dh_key_pub = dh_gen_public($dh_key_priv); |
|
392 $dh_key_priv = $_math->str($dh_key_priv); |
|
393 $dh_key_pub = $_math->str($dh_key_pub); |
|
394 // store the keys in the DB |
|
395 $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); |
|
396 if ( !$q ) |
|
397 $db->_die(); |
|
398 |
|
399 echo "<input type=\"hidden\" name=\"dh_supported\" value=\"true\" /> |
|
400 <input type=\"hidden\" name=\"dh_public_key\" value=\"$dh_key_pub\" /> |
|
401 <input type=\"hidden\" name=\"dh_client_public_key\" value=\"\" />"; |
|
402 } |
|
403 else |
|
404 { |
|
405 echo "<input type=\"hidden\" name=\"dh_supported\" value=\"false\" />"; |
|
406 } |
|
407 ?> |
372 </form> |
408 </form> |
373 <?php |
409 <?php |
374 echo $session->aes_javascript('loginform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data'); |
410 echo $session->aes_javascript('loginform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data', 'dh_supported', 'dh_public_key', 'dh_client_public_key'); |
375 ?> |
411 ?> |
376 <?php |
412 <?php |
377 $template->footer(); |
413 $template->footer(); |
378 } |
414 } |
379 |
415 |
405 $db->close(); |
441 $db->close(); |
406 exit; |
442 exit; |
407 } |
443 } |
408 if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' ) |
444 if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' ) |
409 { |
445 { |
410 $plugins->attachHook('login_password_reset', 'SpecialLogin_SendResponse_PasswordReset($row[\'user_id\'], $row[\'temp_password\']);'); |
446 die('This version of the Enano LoginAPI is deprecated. Please use the action.json method instead.'); |
411 $data = enano_json_decode($_POST['params']); |
447 $db->close(); |
412 $captcha_hash = ( isset($data['captcha_hash']) ) ? $data['captcha_hash'] : false; |
448 exit; |
413 $captcha_code = ( isset($data['captcha_code']) ) ? $data['captcha_code'] : false; |
449 } |
414 $level = ( isset($data['level']) ) ? intval($data['level']) : USER_LEVEL_MEMBER; |
450 if(isset($_POST['login'])) |
415 |
451 { |
416 // 1.1.3: Diffie Hellman |
452 $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false; |
417 global $dh_supported; |
453 $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false; |
418 global $_math; |
454 if ( $_POST['use_crypt'] == 'yes' ) |
419 if ( $data['diffiehellman'] && isset($data['publickey_client']) && isset($data['publickey_server']) && isset($data['crypt_key_check']) ) |
455 { |
420 { |
456 $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']), $captcha_hash, $captcha_code); |
|
457 } |
|
458 else if ( $_POST['use_crypt'] == 'yes_dh' ) |
|
459 { |
|
460 // retrieve and decrypt the password using DiffieHellman |
|
461 |
|
462 require_once( ENANO_ROOT . '/includes/diffiehellman.php' ); |
|
463 global $dh_supported, $_math; |
|
464 |
421 if ( !$dh_supported ) |
465 if ( !$dh_supported ) |
422 { |
466 { |
423 die('Special:Login: Illegal request for Diffie Hellman exchange'); |
467 die_semicritical('DiffieHellman error', 'Server does not support DiffieHellman, denying logon request'); |
424 } |
468 } |
425 // retrieve our public key |
|
426 if ( !preg_match('/^[0-9]+$/', $data['publickey_server']) ) |
|
427 { |
|
428 die('Special:Login: Illegal request for Diffie Hellman exchange'); |
|
429 } |
|
430 $pubkey_server =& $data['publickey_server']; |
|
431 |
469 |
432 // retrieve our private key |
470 // Fetch private key |
433 $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$pubkey_server';"); |
471 $dh_public = $_POST['dh_public_key']; |
|
472 if ( !preg_match('/^[0-9]+$/', $dh_public) ) |
|
473 { |
|
474 die_semicritical('DiffieHellman error', 'Public key not integer: ' . $dh_public); |
|
475 } |
|
476 $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';"); |
434 if ( !$q ) |
477 if ( !$q ) |
435 $db->die_json(); |
478 $db->die_json(); |
436 |
479 |
437 if ( $db->numrows() < 1 ) |
480 if ( $db->numrows() < 1 ) |
438 { |
481 { |
439 die('Special:Login: Couldn\'t lookup Diffie Hellman key: ' . $pubkey_server); |
482 die_semicritical('DiffieHellman error', 'ERR_DH_KEY_NOT_FOUND'); |
440 } |
483 } |
441 list($privkey_server, $key_id) = $db->fetchrow_num(); |
484 |
|
485 list($dh_private, $dh_key_id) = $db->fetchrow_num(); |
442 $db->free_result(); |
486 $db->free_result(); |
443 |
487 |
444 // get shared secret |
488 // We have the private key, now delete the key pair, we no longer need it |
445 $dh_secret = dh_gen_shared_secret($privkey_server, $data['publickey_client']); |
489 $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;"); |
|
490 if ( !$q ) |
|
491 $db->die_json(); |
|
492 |
|
493 // Generate the shared secret |
|
494 $dh_secret = dh_gen_shared_secret($dh_private, $_POST['dh_client_public_key']); |
446 $dh_secret = $_math->str($dh_secret); |
495 $dh_secret = $_math->str($dh_secret); |
447 $secret_check = sha1($dh_secret); |
496 |
448 if ( $secret_check !== $data['crypt_key_check'] ) |
497 // Did we get all our math right? |
449 { |
498 $dh_secret_check = sha1($dh_secret); |
450 die(enano_json_encode(array( |
499 $dh_hash = $_POST['crypt_key']; |
451 'mode' => 'error', |
500 if ( $dh_secret_check !== $dh_hash ) |
452 'error' => 'Diffie Hellman redundancy check failed, couldn\'t rebuild the AES key.', |
501 { |
453 'debug' => array( |
502 die_semicritical('DiffieHellman error', 'ERR_DH_HASH_NO_MATCH'); |
454 'server private key' => $privkey_server, |
503 } |
455 'client public key' => $data['publickey_client'], |
504 |
456 'expected sha1' => $data['crypt_key_check'], |
505 // All good! Generate the AES key |
457 'actual sha1' => $secret_check |
506 $aes_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 )); |
458 ) |
507 |
459 ))); |
508 // decrypt user info |
460 } |
509 $aes_key = hexdecode($aes_key); |
461 // we have the secret, now get the sha256 hash |
510 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
462 $crypt_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 )); |
511 $password = $aes->decrypt($_POST['crypt_data'], $aes_key, ENC_HEX); |
463 } |
512 |
464 else if ( !$data['diffiehellman'] && isset($data['crypt_key']) && isset($data['crypt_data']) ) |
513 $result = $session->login_without_crypto($_POST['username'], $password, false, intval($_POST['auth_level']), $captcha_hash, $captcha_code); |
465 { |
|
466 $crypt_key = $data['crypt_key']; |
|
467 } |
|
468 else |
|
469 { |
|
470 die('Special:Login: Illegal request'); |
|
471 } |
|
472 |
|
473 $result = $session->login_with_crypto($data['username'], $data['crypt_data'], $crypt_key, $data['challenge'], $level, $captcha_hash, $captcha_code, !$dh_supported); |
|
474 |
|
475 if ( $result['success'] ) |
|
476 { |
|
477 $response = Array( |
|
478 'result' => 'success', |
|
479 'key' => $session->sid_super // ( ( $session->sid_super ) ? $session->sid_super : $session->sid ) |
|
480 ); |
|
481 } |
|
482 else |
|
483 { |
|
484 $captcha = ''; |
|
485 if ( $result['error'] == 'locked_out' && $result['lockout_policy'] == 'captcha' ) |
|
486 { |
|
487 $session->kill_captcha(); |
|
488 $captcha = $session->make_captcha(); |
|
489 } |
|
490 $response = Array( |
|
491 'result' => 'error', |
|
492 'data' => $result, |
|
493 'captcha' => $captcha |
|
494 ); |
|
495 } |
|
496 $response = enano_json_encode($response); |
|
497 echo $response; |
|
498 $db->close(); |
|
499 exit; |
|
500 } |
|
501 if(isset($_POST['login'])) { |
|
502 $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false; |
|
503 $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false; |
|
504 if($_POST['use_crypt'] == 'yes') |
|
505 { |
|
506 $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']), $captcha_hash, $captcha_code); |
|
507 } |
514 } |
508 else |
515 else |
509 { |
516 { |
510 $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code); |
517 $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code); |
511 } |
518 } |