plugins/SpecialUserFuncs.php
changeset 801 eb8b23f11744
parent 799 4629ad98ee88
child 832 7152ca0a0ce9
--- a/plugins/SpecialUserFuncs.php	Sat Jan 03 18:11:18 2009 -0500
+++ b/plugins/SpecialUserFuncs.php	Sun Jan 04 00:55:40 2009 -0500
@@ -12,7 +12,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.5 (Caoineag alpha 5)
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2008 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -121,12 +121,6 @@
   global $__login_status;
   global $lang;
   
-  require_once( ENANO_ROOT . '/includes/diffiehellman.php' );
-  global $dh_supported, $_math;
-  
-  $pubkey = $session->rijndael_genkey();
-  $challenge = $session->dss_rand();
-  
   $locked_out = false;
   // are we locked out?
   $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5;
@@ -436,10 +430,6 @@
          </tr>
       </table>
     </div>
-      <input type="hidden" name="challenge_data" value="<?php echo $challenge; ?>" />
-      <input type="hidden" name="use_crypt" value="no" />
-      <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" />
-      <input type="hidden" name="crypt_data" value="" />
       <input type="hidden" name="auth_level" value="<?php echo (string)$level; ?>" />
       <?php if ( $level <= USER_LEVEL_MEMBER ): ?>
       <script type="text/javascript">
@@ -451,34 +441,11 @@
       </script>
       <?php endif; ?>
       <?php
-      // 1.1.4
-      
-      require_once( ENANO_ROOT . '/includes/diffiehellman.php' );
-      
-      global $dh_supported, $_math;
-      if ( $dh_supported )
-      {
-        $dh_key_priv = dh_gen_private();
-        $dh_key_pub = dh_gen_public($dh_key_priv);
-        $dh_key_priv = $_math->str($dh_key_priv);
-        $dh_key_pub = $_math->str($dh_key_pub);
-        // store the keys in the DB
-        $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );");
-        if ( !$q )
-          $db->_die();
-        
-        echo "<input type=\"hidden\" name=\"dh_supported\" value=\"true\" />
-              <input type=\"hidden\" name=\"dh_public_key\" value=\"$dh_key_pub\" />
-              <input type=\"hidden\" name=\"dh_client_public_key\" value=\"\" />";
-      }
-      else
-      {
-        echo "<input type=\"hidden\" name=\"dh_supported\" value=\"false\" />";
-      }
+      echo $session->generate_aes_form();
       ?>
     </form>
     <?php
-      echo $session->aes_javascript('loginform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data', 'dh_supported', 'dh_public_key', 'dh_client_public_key');
+      echo $session->aes_javascript('loginform', 'pass');
     ?>
   <?php
   $template->footer();
@@ -516,93 +483,28 @@
   }
   if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' )
   {
-    echo 'This version of the Enano LoginAPI is deprecated. Please use the action.json method instead.';
+    echo 'This version of the Enano LoginAPI is deprecated. Please clear your browser\'s cache and try your login again. Developers, please use the action.json method instead.';
     return true;
   }
   if(isset($_POST['login']))
   {
     $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false;
     $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false;
-    if ( $_POST['use_crypt'] == 'yes' )
+    
+    try
     {
-      $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
+      $password = $session->get_aes_post('pass');
     }
-    else if ( $_POST['use_crypt'] == 'yes_dh' )
+    catch ( Exception $e )
     {
-      // retrieve and decrypt the password using DiffieHellman
-      
-      require_once( ENANO_ROOT . '/includes/diffiehellman.php' );
-      global $dh_supported, $_math;
-      
-      if ( !$dh_supported )
-      {
-        die_semicritical('DiffieHellman error', 'Server does not support DiffieHellman, denying logon request');
-      }
-      
-      // Fetch private key
-      $dh_public = $_POST['dh_public_key'];
-      if ( !preg_match('/^[0-9]+$/', $dh_public) )
-      {
-        $__login_status = array(
-          'success' => false,
-          'error' => 'ERR_DH_KEY_NOT_INTEGER',
-          'debug' => "public key: $dh_public"
-        );
-        return false;
-      }
-      $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';");
-      if ( !$q )
-        $db->die_json();
-      
-      if ( $db->numrows() < 1 )
-      {
-        $__login_status = array(
-          'success' => false,
-          'error' => 'ERR_DH_KEY_NOT_FOUND',
-          'debug' => "public key: $dh_public"
-        );
-        return false;
-      }
-      
-      list($dh_private, $dh_key_id) = $db->fetchrow_num();
-      $db->free_result();
-      
-      // We have the private key, now delete the key pair, we no longer need it
-      $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;");
-      if ( !$q )
-        $db->die_json();
-      
-      // Generate the shared secret
-      $dh_secret = dh_gen_shared_secret($dh_private, $_POST['dh_client_public_key']);
-      $dh_secret = $_math->str($dh_secret);
-      
-      // Did we get all our math right?
-      $dh_secret_check = sha1($dh_secret);
-      $dh_hash = $_POST['crypt_key'];
-      if ( $dh_secret_check !== $dh_hash )
-      {
-        $__login_status = array(
-          'success' => false,
-          'error' => 'ERR_DH_HASH_NO_MATCH',
-          'debug' => "dh_secret_check = $dh_secret_check\ndh_hash_input = $dh_hash"
-        );
-        return false;
-      }
-      
-      // All good! Generate the AES key
-      $aes_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 ));
-      
-      // decrypt user info
-      $aes_key = hexdecode($aes_key);
-      $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-      $password = $aes->decrypt($_POST['crypt_data'], $aes_key, ENC_HEX);
-      
-      $result = $session->login_without_crypto($_POST['username'], $password, false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
+      $__login_status = array(
+        'mode' => 'error',
+        'error' => $e->getMessage()
+      );
+      return false;
     }
-    else
-    {
-      $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
-    }
+    
+    $result = $session->login_without_crypto($_POST['username'], $password, false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember']));
    
     if($result['success'])
     {
@@ -1598,6 +1500,9 @@
   $template->header();
   if($paths->getParam(0) == 'stage2')
   {
+    require_once(ENANO_ROOT . '/includes/math.php');
+    require_once(ENANO_ROOT . '/includes/diffiehellman.php');
+    
     $user_id = intval($paths->getParam(1));
     $encpass = $paths->getParam(2);
     if ( $user_id < 2 )
@@ -1613,7 +1518,7 @@
       return false;
     }
     
-    $q = $db->sql_query('SELECT username,temp_password_time FROM '.table_prefix.'users WHERE user_id='.$user_id.' AND temp_password=\'' . $encpass . '\';');
+    $q = $db->sql_query('SELECT username,temp_password_time,temp_password,password_salt FROM '.table_prefix.'users WHERE user_id='.$user_id.';');
     if($db->numrows() < 1)
     {
       echo '<p>Invalid credentials</p>';
@@ -1623,6 +1528,16 @@
     $row = $db->fetchrow();
     $db->free_result();
     
+    $temp_pass = $session->pk_decrypt($encpass);
+    $temp_hmac = hmac_sha1($temp_pass, $row['password_salt']);
+    
+    if ( $temp_hmac !== $row['temp_password'] )
+    {
+      echo '<p>Invalid credentials</p>';
+      $template->footer();
+      return false;
+    }
+    
     if ( ( intval($row['temp_password_time']) + ( 3600 * 24 ) ) < time() )
     {
       echo '<p>' . $lang->get('userfuncs_passreset_err_pass_expired', array('reset_url' => makeUrlNS('Special', 'PasswordReset'))) . '</p>';
@@ -1632,48 +1547,29 @@
     
     if ( isset($_POST['do_stage2']) )
     {
-      $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-      if($_POST['use_crypt'] == 'yes')
-      {
-        $crypt_key = $session->fetch_public_key($_POST['crypt_key']);
-        if(!$crypt_key)
-        {
-          echo $lang->get('user_err_key_not_found');
-          $template->footer();
-          return false;
-        }
-        $crypt_key = hexdecode($crypt_key);
-        $data = $aes->decrypt($_POST['crypt_data'], $crypt_key, ENC_HEX);
-        if(strlen($data) < 6)
-        {
-          echo $lang->get('userfuncs_passreset_err_too_short');
-          $template->footer();
-          return false;
-        }
-      }
-      else
-      {
-        $data = $_POST['pass'];
-        $conf = $_POST['pass_confirm'];
-        if($data != $conf)
-        {
-          echo $lang->get('userfuncs_passreset_err_no_match');
-          $template->footer();
-          return false;
-        }
-        if(strlen($data) < 6)
-        {
-          echo $lang->get('userfuncs_passreset_err_too_short');
-          $template->footer();
-          return false;
-        }
-      }
+      $data = $session->get_aes_post('pass');
+      
       if(empty($data))
       {
         echo 'ERROR: Sanity check failed!';
         $template->footer();
         return false;
       }
+      if ( strlen($data) < 6 )
+      {
+        echo '<p>' . $lang->get('userfuncs_passreset_err_too_short') . '</p>';
+        $template->footer();
+        return false;
+      }
+      if ( $_POST['use_crypt'] == 'no' )
+      {
+        if ( $_POST['pass'] !== $_POST['pass_confirm'] )
+        {
+          echo '<p>' . $lang->get('userfuncs_passreset_err_no_match') . '</p>';
+          $template->footer();
+          return false;
+        }
+      }
       if ( getConfig('pw_strength_enable') == '1' )
       {
         $min_score = intval(getConfig('pw_strength_minimum'));
@@ -1686,8 +1582,10 @@
           return false;
         }
       }
-      $encpass = $session->pk_encrypt($data, ENC_HEX);
-      $q = $db->sql_query('UPDATE '.table_prefix.'users SET password=\'' . $encpass . '\',temp_password=\'\',temp_password_time=0 WHERE user_id='.$user_id.';');
+      
+      $session->set_password($user_id, $data);
+      
+      $q = $db->sql_query('UPDATE '.table_prefix.'users SET temp_password=\'\',temp_password_time=0 WHERE user_id = '.$user_id.';');
       
       if($q)
       {
@@ -1704,10 +1602,8 @@
     }
     
     // Password reset form
-    $pubkey = $session->rijndael_genkey();
-    
     $evt_get_score = ( getConfig('pw_strength_enable') == '1' ) ? 'onkeyup="password_score_field(this);" ' : '';
-    $pw_meter =      ( getConfig('pw_strength_enable') == '1' ) ? '<tr><td class="row1">' . $lang->get('userfuncs_passreset_stage2_lbl_strength') . '</td><td class="row1"><div id="pwmeter"></div><script type="text/javascript">password_score_field(document.forms.resetform.pass);</script></td></tr>' : '';
+    $pw_meter =      ( getConfig('pw_strength_enable') == '1' ) ? '<tr><td class="row1">' . $lang->get('userfuncs_passreset_stage2_lbl_strength') . '</td><td class="row1"><div id="pwmeter"></div></td></tr>' : '';
     $pw_blurb =      ( getConfig('pw_strength_enable') == '1' && intval(getConfig('pw_strength_minimum')) > -10 ) ? '<br /><small>' . $lang->get('userfuncs_passreset_stage2_blurb_strength') . '</small>' : '';
     
     ?>
@@ -1721,86 +1617,23 @@
           <?php echo $pw_meter; ?>
           <tr>
             <td colspan="2" class="row3" style="text-align: center;">
-              <input type="hidden" name="use_crypt" value="no" />
-              <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" />
-              <input type="hidden" name="crypt_data" value="" />
+              
               <input type="submit" name="do_stage2" value="<?php echo $lang->get('userfuncs_passreset_stage2_btn_submit'); ?>" />
             </td>
           </tr>
         </table>
       </div>
+      <?php echo $session->generate_aes_form(); ?>
     </form>
     <script type="text/javascript">
-    if ( !KILL_SWITCH )
-    {
-      disableJSONExts();
-      str = '';
-      for(i=0;i<keySizeInBits/4;i++) str+='0';
-      var key = hexToByteArray(str);
-      var pt = hexToByteArray(str);
-      var ct = rijndaelEncrypt(pt, key, "ECB");
-      var ct = byteArrayToHex(ct);
-      switch(keySizeInBits)
-      {
-        case 128:
-          v = '66e94bd4ef8a2c3b884cfa59ca342b2e';
-          break;
-        case 192:
-          v = 'aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7';
-          break;
-        case 256:
-          v = 'dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087';
-          break;
-      }
-      var testpassed = ( ct == v && md5_vm_test() );
-      var frm = document.forms.resetform;
-      if(testpassed)
+    addOnloadHook(function()
       {
-        frm.use_crypt.value = 'yes';
-        var cryptkey = frm.crypt_key.value;
-        frm.crypt_key.value = hex_md5(cryptkey);
-        cryptkey = hexToByteArray(cryptkey);
-        if(!cryptkey || ( ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ) && cryptkey.length != keySizeInBits / 8 )
-        {
-          frm._login.disabled = true;
-          len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : '';
-          alert('The key is messed up\nType: '+typeof(cryptkey)+len);
-        }
-      }
-      function runEncryption()
-      {
-        var frm = document.forms.resetform;
-        pass1 = frm.pass.value;
-        pass2 = frm.pass_confirm.value;
-        if ( pass1 != pass2 )
-        {
-          alert($lang.get('userfuncs_passreset_err_no_match'));
-          return false;
-        }
-        if ( pass1.length < 6 )
-        {
-          alert($lang.get('userfuncs_passreset_err_too_short'));
-          return false;
-        }
-        if(testpassed)
-        {
-          pass = frm.pass.value;
-          pass = stringToByteArray(pass);
-          cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB');
-          if(!cryptstring)
-          {
-            return false;
-          }
-          cryptstring = byteArrayToHex(cryptstring);
-          frm.crypt_data.value = cryptstring;
-          frm.pass.value = "";
-          frm.pass_confirm.value = "";
-        }
-        return true;
-      }
-    }
+        load_component('pwstrength');
+        password_score_field(document.forms.resetform.pass);
+      });
     </script>
     <?php
+    echo $session->aes_javascript('resetform', 'pass', 'use_crypt', 'crypt_key', 'crypt_data', 'challenge_data', 'dh_supported', 'dh_public_key', 'dh_client_public_key');
     $template->footer();
     return true;
   }