includes/sessions.php
changeset 802 59cce2313f9d
parent 801 eb8b23f11744
child 811 5c807fe77020
equal deleted inserted replaced
801:eb8b23f11744 802:59cce2313f9d
   780     if ( $row['old_encryption'] == 1 )
   780     if ( $row['old_encryption'] == 1 )
   781     {
   781     {
   782       // The user's password is stored using the obsolete and insecure MD5 algorithm - we'll update the field with the new password
   782       // The user's password is stored using the obsolete and insecure MD5 algorithm - we'll update the field with the new password
   783       if(md5($password) === $row['password'])
   783       if(md5($password) === $row['password'])
   784       {
   784       {
   785         $hmac_secret = AESCrypt::randkey(20);
   785         if ( !defined('IN_ENANO_UPGRADE') )
   786         $password_hmac = hmac_sha1($password, $hmac_secret);
   786         {
   787         $this->sql('UPDATE '.table_prefix."users SET password = '$password_hmac', password_salt = '$hmac_secret', old_encryption = 0 WHERE user_id={$row['user_id']};");
   787           $hmac_secret = hexencode(AESCrypt::randkey(20), '', '');
       
   788           $password_hmac = hmac_sha1($password, $hmac_secret);
       
   789           $this->sql('UPDATE '.table_prefix."users SET password = '$password_hmac', password_salt = '$hmac_secret', old_encryption = 0 WHERE user_id={$row['user_id']};");
       
   790         }
   788         $success = true;
   791         $success = true;
   789       }
   792       }
   790     }
   793     }
   791     else if ( $row['old_encryption'] == 2 )
   794     else if ( $row['old_encryption'] == 2 || defined('ENANO_UPGRADE_USE_AES_PASSWORDS') )
   792     {
   795     {
   793       // Our password field uses the 1.0RC1-1.1.5 encryption format
   796       // Our password field uses the 1.0RC1-1.1.5 encryption format
   794       $real_pass = $aes->decrypt($row['password'], $this->private_key);
   797       $real_pass = $aes->decrypt($row['password'], $this->private_key);
   795       if($password === $real_pass)
   798       if($password === $real_pass)
   796       {
   799       {
   797         $success = true;
   800         if ( !defined('IN_ENANO_UPGRADE') )
   798         $hmac_secret = AESCrypt::randkey(20);
   801         {
   799         $password_hmac = hmac_sha1($password, $hmac_secret);
   802           $hmac_secret = hexencode(AESCrypt::randkey(20), '', '');
   800         $this->sql('UPDATE '.table_prefix."users SET password = '$password_hmac', password_salt = '$hmac_secret', old_encryption = 0 WHERE user_id={$row['user_id']};");
   803           $password_hmac = hmac_sha1($password, $hmac_secret);
       
   804           $this->sql('UPDATE '.table_prefix."users SET password = '$password_hmac', password_salt = '$hmac_secret', old_encryption = 0 WHERE user_id={$row['user_id']};");
       
   805         }
   801         $success = true;
   806         $success = true;
   802       }
   807       }
   803     }
   808     }
   804     else
   809     else
   805     {
   810     {
   816       if((int)$level > (int)$row['user_level'])
   821       if((int)$level > (int)$row['user_level'])
   817         return array(
   822         return array(
   818           'success' => false,
   823           'success' => false,
   819           'error' => 'too_big_for_britches'
   824           'error' => 'too_big_for_britches'
   820         );
   825         );
   821       $sess = $this->register_session($row['user_id'], $username, $password_hmac, $level, $remember);
   826       $sess = $this->register_session($row['user_id'], $username, ( isset($password_hmac) ? $password_hmac : $password ), $level, $remember);
   822       if($sess)
   827       if($sess)
   823       {
   828       {
   824         if($level > USER_LEVEL_MEMBER)
   829         if($level > USER_LEVEL_MEMBER)
   825           $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_good\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
   830           $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_good\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
   826         else
   831         else
   925     {
   930     {
   926       $salt .= chr(mt_rand(32, 127));
   931       $salt .= chr(mt_rand(32, 127));
   927     }
   932     }
   928     
   933     
   929     // Session key
   934     // Session key
   930     $session_key = hmac_sha1($password_hmac, $salt);
   935     if ( defined('ENANO_UPGRADE_USE_AES_PASSWORDS') )
       
   936     {
       
   937       $session_key = $this->pk_encrypt("u=$username;p=" . sha1($password_hmac) . ";s=$salt");
       
   938     }
       
   939     else
       
   940     {
       
   941       $session_key = hmac_sha1($password_hmac, $salt);
       
   942     }
   931     
   943     
   932     // Type of key
   944     // Type of key
   933     $key_type = ( $level > USER_LEVEL_MEMBER ) ? SK_ELEV : ( $remember ? SK_LONG : SK_SHORT );
   945     $key_type = ( $level > USER_LEVEL_MEMBER ) ? SK_ELEV : ( $remember ? SK_LONG : SK_SHORT );
   934     
   946     
   935     // If we're registering an elevated-privilege key, it needs to be on GET
   947     // If we're registering an elevated-privilege key, it needs to be on GET
   936     if($level > USER_LEVEL_MEMBER)
   948     if($level > USER_LEVEL_MEMBER)
   937     {
   949     {
   938       // Reverse it - cosmetic only ;-)
   950       $this->sid_super = $session_key;
   939       $hexkey = $session_key;
   951       $_GET['auth'] = $session_key;
   940       $this->sid_super = $hexkey;
       
   941       $_GET['auth'] = $hexkey;
       
   942     }
   952     }
   943     else
   953     else
   944     {
   954     {
   945       // Stash it in a cookie
   955       // Stash it in a cookie
   946       // For now, make the cookie last forever, we can change this in 1.1.x
   956       // For now, make the cookie last forever, we can change this in 1.1.x
  1065   protected function validate_aes_session($key)
  1075   protected function validate_aes_session($key)
  1066   {
  1076   {
  1067     global $db, $session, $paths, $template, $plugins; // Common objects
  1077     global $db, $session, $paths, $template, $plugins; // Common objects
  1068     
  1078     
  1069     // No valid use except during upgrades
  1079     // No valid use except during upgrades
  1070     if ( !preg_match('/^upg-/', enano_version()) || !defined('IN_ENANO_UPGRADE') )
  1080     if ( !preg_match('/^upg-/', enano_version()) && !defined('IN_ENANO_UPGRADE') )
  1071       return false;
  1081       return false;
  1072     
  1082     
  1073     $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
  1083     $decrypted_key = $this->pk_decrypt($key);
  1074     $decrypted_key = $aes->decrypt($key, $this->private_key, ENC_HEX);
       
  1075     if ( !$decrypted_key )
  1084     if ( !$decrypted_key )
  1076     {
  1085     {
  1077       // die_semicritical('AES encryption error', '<p>Something went wrong during the AES decryption process.</p><pre>'.print_r($decrypted_key, true).'</pre>');
  1086       // die_semicritical('AES encryption error', '<p>Something went wrong during the AES decryption process.</p><pre>'.print_r($decrypted_key, true).'</pre>');
  1078       return false;
  1087       return false;
  1079     }
  1088     }
  1080     
  1089     
  1081     $n = preg_match('/^u='.$this->valid_username.';p=([A-Fa-f0-9]+?);s=([A-Fa-f0-9]+?)$/', $decrypted_key, $keydata);
  1090     $n = preg_match('/^u='.$this->valid_username.';p=([A-Fa-f0-9]+?);s=(.{32})$/', $decrypted_key, $keydata);
  1082     if($n < 1)
  1091     if($n < 1)
  1083     {
  1092     {
  1084       // echo '(debug) $session->validate_session: Key does not match regex<br />Decrypted key: '.$decrypted_key;
  1093       echo '(debug) $session->validate_session: Key does not match regex<br />Decrypted key: '.$decrypted_key;
  1085       return false;
  1094       return false;
  1086     }
  1095     }
  1087     $keyhash = md5($key);
  1096     $keyhash = md5($key);
  1088     $salt = $db->escape($keydata[3]);
  1097     $salt = $db->escape($keydata[3]);
  1089     
  1098     
  1141       $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,\'\' AS password_salt,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms, 1440 AS user_timezone, \'0;0;0;0;60\' AS user_dst, ' . SK_SHORT . ' AS key_type FROM '.table_prefix.'session_keys AS k
  1150       $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,\'\' AS password_salt,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms, 1440 AS user_timezone, \'0;0;0;0;60\' AS user_dst, ' . SK_SHORT . ' AS key_type FROM '.table_prefix.'session_keys AS k
  1142                              LEFT JOIN '.table_prefix.'users AS u
  1151                              LEFT JOIN '.table_prefix.'users AS u
  1143                                ON ( u.user_id=k.user_id )
  1152                                ON ( u.user_id=k.user_id )
  1144                              LEFT JOIN '.table_prefix.'privmsgs AS p
  1153                              LEFT JOIN '.table_prefix.'privmsgs AS p
  1145                                ON ( p.message_to=u.username AND p.message_read=0 )
  1154                                ON ( p.message_to=u.username AND p.message_read=0 )
  1146                              WHERE k.session_key=\''.$keyhash.'\'
  1155                              WHERE k.session_key=\''.$key.'\'
  1147                                AND k.salt=\''.$salt.'\'
  1156                                AND k.salt=\''.$salt.'\'
  1148                              GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level;');
  1157                              GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level;');
  1149     }
  1158     }
  1150     else if ( !$query )
  1159     else if ( !$query )
  1151     {
  1160     {
  1194       }
  1203       }
  1195     }
  1204     }
  1196     else
  1205     else
  1197     {
  1206     {
  1198       // if this is a "loose call", this only works once (during the final upgrade stage). Destroy the contents of session_keys.
  1207       // if this is a "loose call", this only works once (during the final upgrade stage). Destroy the contents of session_keys.
  1199       if ( $row['auth_level'] == USER_LEVEL_ADMIN )
  1208       if ( $row['auth_level'] == USER_LEVEL_ADMIN && preg_match('/^upg-/', enano_version()) )
  1200         $this->sql('DELETE FROM ' . table_prefix . "session_keys;");
  1209         $this->sql('DELETE FROM ' . table_prefix . "session_keys;");
  1201     }
  1210     }
  1202     
  1211     
  1203     // timestamp check
  1212     // timestamp check
  1204     switch ( $row['key_type'] )
  1213     switch ( $row['key_type'] )