674 * Technically it still uses crypto, but it only decrypts the password already stored, which is (obviously) required for authentication |
674 * Technically it still uses crypto, but it only decrypts the password already stored, which is (obviously) required for authentication |
675 * @param string $username The username |
675 * @param string $username The username |
676 * @param string $password The password -OR- the MD5 hash of the password if $already_md5ed is true |
676 * @param string $password The password -OR- the MD5 hash of the password if $already_md5ed is true |
677 * @param bool $already_md5ed This should be set to true if $password is an MD5 hash, and should be false if it's plaintext. Defaults to false. |
677 * @param bool $already_md5ed This should be set to true if $password is an MD5 hash, and should be false if it's plaintext. Defaults to false. |
678 * @param int $level The privilege level we're authenticating for, defaults to 0 |
678 * @param int $level The privilege level we're authenticating for, defaults to 0 |
679 * @param string $captcha_hash Optional. If we're locked out and the lockout policy is captcha, this should be the identifier for the code. |
|
680 * @param string $captcha_code Optional. If we're locked out and the lockout policy is captcha, this should be the code the user entered. |
|
681 * @param bool $remember Optional. If true, remembers the session for X days. Otherwise, assigns a short session. Defaults to false. |
679 * @param bool $remember Optional. If true, remembers the session for X days. Otherwise, assigns a short session. Defaults to false. |
682 */ |
680 */ |
683 |
681 |
684 function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false, $remember = false) |
682 function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $remember = false) |
685 { |
683 { |
686 global $db, $session, $paths, $template, $plugins; // Common objects |
684 global $db, $session, $paths, $template, $plugins; // Common objects |
687 |
685 |
688 if ( $already_md5ed ) |
686 if ( $already_md5ed ) |
689 { |
687 { |
700 |
698 |
701 // Perhaps we're upgrading Enano? |
699 // Perhaps we're upgrading Enano? |
702 if($this->compat) |
700 if($this->compat) |
703 { |
701 { |
704 return $this->login_compat($username, md5($password), $level); |
702 return $this->login_compat($username, md5($password), $level); |
705 } |
|
706 |
|
707 // Lockout check |
|
708 if ( !defined('IN_ENANO_INSTALL') ) |
|
709 { |
|
710 $lockout_data = $this->get_lockout_info($lockout_data); |
|
711 |
|
712 $captcha_good = false; |
|
713 if ( $lockout_data['lockout_policy'] == 'captcha' && $captcha_hash && $captcha_code ) |
|
714 { |
|
715 // policy is captcha -- check if it's correct, and if so, bypass lockout check |
|
716 $real_code = $this->get_captcha($captcha_hash); |
|
717 if ( strtolower($real_code) === strtolower($captcha_code) ) |
|
718 { |
|
719 $captcha_good = true; |
|
720 } |
|
721 } |
|
722 if ( $lockout_data['lockout_policy'] != 'disable' && !$captcha_good ) |
|
723 { |
|
724 if ( $lockout_data['lockout_fails'] >= $lockout_data['lockout_threshold'] ) |
|
725 { |
|
726 // ooh boy, somebody's in trouble ;-) |
|
727 return array( |
|
728 'success' => false, |
|
729 'error' => 'locked_out', |
|
730 'lockout_threshold' => $lockout_data['lockout_threshold'], |
|
731 'lockout_duration' => ( $lockout_data['lockout_duration'] ), |
|
732 'lockout_fails' => $lockout_data['lockout_fails'], |
|
733 'lockout_policy' => $lockout_data['lockout_policy'], |
|
734 'time_rem' => $lockout_data['time_rem'], |
|
735 'lockout_last_time' => $lockout_data['lockout_last_time'] |
|
736 ); |
|
737 } |
|
738 } |
|
739 } |
703 } |
740 |
704 |
741 // Instanciate the Rijndael encryption object |
705 // Instanciate the Rijndael encryption object |
742 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
706 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
743 |
707 |
764 $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary) VALUES\n" |
728 $this->sql('INSERT INTO ' . table_prefix . "logs(log_type,action,time_id,date_string,author,edit_summary) VALUES\n" |
765 . ' (\'security\', \'auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', ' |
729 . ' (\'security\', \'auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', ' |
766 . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); |
730 . '\''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); |
767 |
731 |
768 // Do we also need to increment the lockout countdown? |
732 // Do we also need to increment the lockout countdown? |
769 if ( @$lockout_data['lockout_policy'] != 'disable' && !defined('IN_ENANO_INSTALL') ) |
733 if ( !defined('IN_ENANO_INSTALL') ) |
|
734 $lockout_data = $this->get_lockout_info(); |
|
735 else |
|
736 $lockout_data = array( |
|
737 'lockout_policy' => 'disable' |
|
738 ); |
|
739 |
|
740 if ( $lockout_data['lockout_policy'] != 'disable' && !defined('IN_ENANO_INSTALL') ) |
770 { |
741 { |
771 $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); |
742 $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); |
772 // increment fail count |
743 // increment fail count |
773 $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); |
744 $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); |
774 $lockout_data['lockout_fails']++; |
745 $lockout_data['lockout_fails']++; |
889 $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')'); |
860 $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')'); |
890 else |
861 else |
891 $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); |
862 $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')'); |
892 |
863 |
893 // Do we also need to increment the lockout countdown? |
864 // Do we also need to increment the lockout countdown? |
894 if ( !defined('IN_ENANO_INSTALL') && $lockout_data['lockout_policy'] != 'disable' ) |
865 if ( !defined('IN_ENANO_INSTALL') && getConfig('lockout_policy', 'lockout') !== 'disable' ) |
895 { |
866 { |
896 $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); |
867 $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); |
897 // increment fail count |
868 // increment fail count |
898 $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); |
869 $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');'); |
899 $lockout_data['lockout_fails']++; |
|
900 return array( |
|
901 'success' => false, |
|
902 'error' => ( $lockout_data['lockout_fails'] >= $lockout_data['lockout_threshold'] ) ? 'locked_out' : 'invalid_credentials', |
|
903 'lockout_threshold' => $lockout_data['lockout_threshold'], |
|
904 'lockout_duration' => ( $lockout_data['lockout_duration'] ), |
|
905 'lockout_fails' => $lockout_data['lockout_fails'], |
|
906 'lockout_policy' => $lockout_data['lockout_policy'] |
|
907 ); |
|
908 } |
870 } |
909 |
871 |
910 return array( |
872 return array( |
911 'success' => false, |
873 'success' => false, |
912 'error' => 'invalid_credentials' |
874 'error' => 'invalid_credentials' |
1094 $q = $this->sql('SELECT timestamp FROM ' . table_prefix . 'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;'); |
1056 $q = $this->sql('SELECT timestamp FROM ' . table_prefix . 'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;'); |
1095 $fails = $db->numrows($q); |
1057 $fails = $db->numrows($q); |
1096 $row = $db->fetchrow($q); |
1058 $row = $db->fetchrow($q); |
1097 $locked_out = ( $fails >= $threshold ); |
1059 $locked_out = ( $fails >= $threshold ); |
1098 $lockdata = array( |
1060 $lockdata = array( |
1099 'locked_out' => $locked_out, |
1061 'active' => $locked_out, |
1100 'lockout_threshold' => $threshold, |
1062 'threshold' => $threshold, |
1101 'lockout_duration' => ( $duration / 60 ), |
1063 'duration' => ( $duration / 60 ), |
1102 'lockout_fails' => $fails, |
1064 'fails' => $fails, |
1103 'lockout_policy' => $policy, |
1065 'policy' => $policy, |
1104 'lockout_last_time' => $row['timestamp'], |
1066 'last_time' => $row['timestamp'], |
1105 'time_rem' => $locked_out ? ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ) : 0, |
1067 'time_rem' => $locked_out ? ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ) : 0, |
1106 'captcha' => '' |
1068 'captcha' => $policy == 'captcha' ? $this->make_captcha() : '' |
1107 ); |
1069 ); |
1108 $db->free_result(); |
1070 $db->free_result(); |
1109 } |
1071 } |
1110 else |
1072 else |
1111 { |
1073 { |
1112 // disabled; send back default dataset |
1074 // disabled; send back default dataset |
1113 $lockdata = array( |
1075 $lockdata = array( |
1114 'locked_out' => false, |
1076 'active' => false, |
1115 'lockout_threshold' => $threshold, |
1077 'threshold' => $threshold, |
1116 'lockout_duration' => ( $duration / 60 ), |
1078 'duration' => ( $duration / 60 ), |
1117 'lockout_fails' => 0, |
1079 'fails' => 0, |
1118 'lockout_policy' => $policy, |
1080 'policy' => $policy, |
1119 'lockout_last_time' => 0, |
1081 'last_time' => 0, |
1120 'time_rem' => 0, |
1082 'time_rem' => 0, |
1121 'captcha' => '' |
1083 'captcha' => '' |
1122 ); |
1084 ); |
1123 } |
1085 } |
1124 return $lockdata; |
1086 return $lockdata; |
3867 global $_math; |
3829 global $_math; |
3868 |
3830 |
3869 // Check for the mode |
3831 // Check for the mode |
3870 if ( !isset($req['mode']) ) |
3832 if ( !isset($req['mode']) ) |
3871 { |
3833 { |
3872 return array( |
3834 return $this->get_login_response('api_error', 'ERR_JSON_NO_MODE'); |
3873 'mode' => 'error', |
|
3874 'error' => 'ERR_JSON_NO_MODE' |
|
3875 ); |
|
3876 } |
3835 } |
3877 |
3836 |
3878 // Main processing switch |
3837 // Main processing switch |
3879 switch ( $req['mode'] ) |
3838 switch ( $req['mode'] ) |
3880 { |
3839 { |
3881 default: |
3840 default: |
3882 return array( |
3841 return $this->get_login_response('api_error', 'ERR_JSON_INVALID_MODE'); |
3883 'mode' => 'error', |
|
3884 'error' => 'ERR_JSON_INVALID_MODE' |
|
3885 ); |
|
3886 break; |
3842 break; |
3887 case 'getkey': |
3843 case 'getkey': |
3888 |
3844 |
3889 $this->start(); |
3845 $this->start(); |
3890 |
3846 |
3891 $locked_out = $this->get_lockout_info($lockdata); |
3847 return $this->get_login_response('initial'); |
3892 |
|
3893 $response = array('mode' => 'build_box'); |
|
3894 $response['allow_diffiehellman'] = $dh_supported; |
|
3895 |
|
3896 $response['username'] = ( $this->user_logged_in ) ? $this->username : false; |
|
3897 $response['aes_key'] = $this->rijndael_genkey(); |
|
3898 |
|
3899 $response['extended_time'] = intval(getConfig('session_remember_time', '30')); |
|
3900 |
|
3901 // Lockout info |
|
3902 $response['locked_out'] = $locked_out; |
|
3903 |
|
3904 $response['lockout_info'] = $lockdata; |
|
3905 if ( $lockdata['lockout_policy'] == 'captcha' && $locked_out ) |
|
3906 { |
|
3907 $response['lockout_info']['captcha'] = $this->make_captcha(); |
|
3908 } |
|
3909 |
|
3910 // Can we do Diffie-Hellman? If so, generate and stash a public/private key pair. |
|
3911 if ( $dh_supported ) |
|
3912 { |
|
3913 $dh_key_priv = dh_gen_private(); |
|
3914 $dh_key_pub = dh_gen_public($dh_key_priv); |
|
3915 $dh_key_priv = $_math->str($dh_key_priv); |
|
3916 $dh_key_pub = $_math->str($dh_key_pub); |
|
3917 $response['dh_public_key'] = $dh_key_pub; |
|
3918 // store the keys in the DB |
|
3919 $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); |
|
3920 if ( !$q ) |
|
3921 $db->die_json(); |
|
3922 } |
|
3923 |
|
3924 return $response; |
|
3925 break; |
3848 break; |
3926 case 'login_dh': |
3849 case 'login_dh': |
3927 // User is requesting a login and has sent Diffie-Hellman data. |
3850 // User is requesting a login and has sent Diffie-Hellman data. |
3928 |
3851 |
3929 // |
3852 // |
3935 $dh_hash = $req['dh_secret_hash']; |
3858 $dh_hash = $req['dh_secret_hash']; |
3936 |
3859 |
3937 // Check the key |
3860 // Check the key |
3938 if ( !ctype_digit($dh_public) || !ctype_digit($req['dh_client_key']) ) |
3861 if ( !ctype_digit($dh_public) || !ctype_digit($req['dh_client_key']) ) |
3939 { |
3862 { |
3940 return array( |
3863 return $this->get_login_response('api_error', 'ERR_DH_KEY_NOT_NUMERIC'); |
3941 'mode' => 'error', |
|
3942 'error' => 'ERR_DH_KEY_NOT_NUMERIC' |
|
3943 ); |
|
3944 } |
3864 } |
3945 |
3865 |
3946 // Fetch private key |
3866 // Fetch private key |
3947 $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';"); |
3867 $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';"); |
3948 if ( !$q ) |
3868 if ( !$q ) |
3949 $db->die_json(); |
3869 $db->die_json(); |
3950 |
3870 |
3951 if ( $db->numrows() < 1 ) |
3871 if ( $db->numrows() < 1 ) |
3952 { |
3872 { |
3953 return array( |
3873 return $this->get_login_response('api_error', 'ERR_DH_KEY_NOT_FOUND'); |
3954 'mode' => 'error', |
|
3955 'error' => 'ERR_DH_KEY_NOT_FOUND' |
|
3956 ); |
|
3957 } |
3874 } |
3958 |
3875 |
3959 list($dh_private, $dh_key_id) = $db->fetchrow_num(); |
3876 list($dh_private, $dh_key_id) = $db->fetchrow_num(); |
3960 $db->free_result(); |
3877 $db->free_result(); |
3961 |
3878 |
4001 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
3912 $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE); |
4002 // using "true" here disables caching of the decrypted login info (which includes the password) |
3913 // using "true" here disables caching of the decrypted login info (which includes the password) |
4003 $userinfo_json = $aes->decrypt($userinfo_crypt, $aes_key, ENC_HEX, true); |
3914 $userinfo_json = $aes->decrypt($userinfo_crypt, $aes_key, ENC_HEX, true); |
4004 if ( !$userinfo_json ) |
3915 if ( !$userinfo_json ) |
4005 { |
3916 { |
4006 return array( |
3917 return $this->get_login_response('api_error', 'ERR_AES_DECRYPT_FAILED'); |
4007 'mode' => 'error', |
|
4008 'error' => 'ERR_AES_DECRYPT_FAILED' |
|
4009 ); |
|
4010 } |
3918 } |
4011 // de-JSON user info |
3919 // de-JSON user info |
4012 try |
3920 try |
4013 { |
3921 { |
4014 $userinfo = enano_json_decode($userinfo_json); |
3922 $userinfo = enano_json_decode($userinfo_json); |
4015 } |
3923 } |
4016 catch ( Exception $e ) |
3924 catch ( Exception $e ) |
4017 { |
3925 { |
4018 return array( |
3926 return $this->get_login_response('api_error', 'ERR_USERINFO_DECODE_FAILED'); |
4019 'mode' => 'error', |
3927 } |
4020 'error' => 'ERR_USERINFO_DECODE_FAILED' |
3928 |
4021 ); |
3929 case 'login_pt': |
|
3930 // plaintext login |
|
3931 if ( $req['mode'] == 'login_pt' ) |
|
3932 { |
|
3933 $userinfo = isset($req['userinfo']) ? $req['userinfo'] : array(); |
4022 } |
3934 } |
4023 |
3935 |
4024 if ( !isset($userinfo['username']) || !isset($userinfo['password']) ) |
3936 if ( !isset($userinfo['username']) || !isset($userinfo['password']) ) |
4025 { |
3937 { |
4026 return array( |
3938 return $this->get_login_response('api_error', 'ERR_USERINFO_MISSING_VALUES'); |
4027 'mode' => 'error', |
|
4028 'error' => 'ERR_USERINFO_MISSING_VALUES' |
|
4029 ); |
|
4030 } |
3939 } |
4031 |
3940 |
4032 $username =& $userinfo['username']; |
3941 $username =& $userinfo['username']; |
4033 $password =& $userinfo['password']; |
3942 $password =& $userinfo['password']; |
|
3943 |
|
3944 // locked out? check captcha |
|
3945 $lockout_data = $this->get_lockout_info(); |
|
3946 if ( $lockout_data['policy'] == 'captcha' && $lockout_data['active'] ) |
|
3947 { |
|
3948 // policy is captcha -- check if it's correct, and if so, bypass lockout check |
|
3949 $real_code = $this->get_captcha($req['captcha_hash']); |
|
3950 if ( strtolower($real_code) !== strtolower($req['captcha_code']) ) |
|
3951 { |
|
3952 // captcha is bad |
|
3953 return $this->get_login_response('login_failure', 'lockout_bad_captcha'); |
|
3954 } |
|
3955 } |
|
3956 else if ( $lockout_data['policy'] == 'lockout' && $lockout_data['active'] ) |
|
3957 { |
|
3958 // we're fully locked out |
|
3959 return $this->get_login_response('login_failure', 'lockout_request_denied'); |
|
3960 } |
4034 |
3961 |
4035 // At this point if any extra info was injected into the login data packet, we need to let plugins process it |
3962 // At this point if any extra info was injected into the login data packet, we need to let plugins process it |
4036 /** |
3963 /** |
4037 * Called upon processing an incoming login request. If you added anything to the userinfo object during the jshook |
3964 * Called upon processing an incoming login request. If you added anything to the userinfo object during the jshook |
4038 * login_build_userinfo, that will be in the $userinfo array here. Expected return values are: true if your plugin has |
3965 * login_build_userinfo, that will be in the $userinfo array here. Expected return values are: true if your plugin has |
4047 foreach ( $code as $cmd ) |
3974 foreach ( $code as $cmd ) |
4048 { |
3975 { |
4049 $result = eval($cmd); |
3976 $result = eval($cmd); |
4050 if ( $result === true ) |
3977 if ( $result === true ) |
4051 { |
3978 { |
4052 return array( |
3979 return $this->get_login_response('login_success', false, array( |
4053 'mode' => 'login_success', |
3980 'key' => $this->sid_super, |
4054 'key' => ( $this->sid_super ) ? $this->sid_super : false, |
|
4055 'user_id' => $this->user_id, |
3981 'user_id' => $this->user_id, |
4056 'user_level' => $this->user_level |
3982 'user_level' => $this->user_level, |
4057 ); |
3983 'reset' => false |
|
3984 )); |
4058 } |
3985 } |
4059 else if ( is_array($result) ) |
3986 else if ( is_array($result) ) |
4060 { |
3987 { |
4061 if ( isset($result['mode']) && $result['mode'] === 'error' && isset($result['error']) ) |
3988 if ( isset($result['mode']) && $result['mode'] === 'error' && isset($result['error']) ) |
4062 { |
3989 { |
4063 // Pass back any additional information from the error response |
3990 // Pass back any additional information from the error response |
4064 $append = $result; |
3991 $append = $result; |
4065 unset($append['mode'], $append['error']); |
3992 unset($append['mode'], $append['error']); |
|
3993 $append['from_plugin'] = true; |
4066 |
3994 |
4067 $return = array( |
3995 return $this->get_login_response('login_failure', $result['error'], $append); |
4068 'mode' => 'login_failure', |
|
4069 'error_code' => $result['error'], |
|
4070 // Use this to provide a way to respawn the login box |
|
4071 'respawn_info' => $this->process_login_request(array('mode' => 'getkey')) |
|
4072 ); |
|
4073 |
|
4074 $return = array_merge($append, $return); |
|
4075 return $return; |
|
4076 } |
3996 } |
4077 } |
3997 } |
4078 } |
3998 } |
4079 |
3999 |
4080 // If we're logging in with a temp password, attach to the login_password_reset hook to send our JSON response |
|
4081 // A bit hackish since it just dies with the response :-( |
|
4082 $plugins->attachHook('login_password_reset', '$this->process_login_request(array(\'mode\' => \'respond_password_reset\', \'user_id\' => $row[\'user_id\'], \'temp_password\' => $this->pk_encrypt($password)));'); |
|
4083 |
|
4084 // attempt the login |
4000 // attempt the login |
4085 // function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false) |
4001 $login_result = $this->login_without_crypto($username, $password, false, intval($req['level']), @$req['remember']); |
4086 $login_result = $this->login_without_crypto($username, $password, false, intval($req['level']), @$req['captcha_hash'], @$req['captcha_code'], @$req['remember']); |
|
4087 |
4002 |
4088 if ( $login_result['success'] ) |
4003 if ( $login_result['success'] ) |
4089 { |
4004 { |
4090 return array( |
4005 return $this->get_login_response('login_success', false, array( |
4091 'mode' => 'login_success', |
4006 'key' => $this->sid_super, |
4092 'key' => ( $this->sid_super ) ? $this->sid_super : false, |
|
4093 'user_id' => $this->user_id, |
4007 'user_id' => $this->user_id, |
4094 'user_level' => $this->user_level |
4008 'user_level' => $this->user_level, |
4095 ); |
4009 )); |
|
4010 } |
|
4011 else if ( !$login_result['success'] && $login_result['error'] === 'valid_reset' ) |
|
4012 { |
|
4013 return $this->get_login_response('reset_pass_used', false, array( |
|
4014 'redirect_url' => $login_result['redirect_url'] |
|
4015 )); |
4096 } |
4016 } |
4097 else |
4017 else |
4098 { |
4018 { |
4099 return array( |
4019 return $this->get_login_response('login_failure', 'invalid_credentials'); |
4100 'mode' => 'login_failure', |
|
4101 'error_code' => $login_result['error'], |
|
4102 // Use this to provide a way to respawn the login box |
|
4103 'respawn_info' => $this->process_login_request(array('mode' => 'getkey')) |
|
4104 ); |
|
4105 } |
4020 } |
4106 |
4021 |
4107 break; |
4022 break; |
4108 case 'clean_key': |
4023 case 'clean_key': |
4109 // Clean out a key, since it won't be used. |
4024 // Clean out a key, since it won't be used. |
4162 break; |
4077 break; |
4163 } |
4078 } |
4164 |
4079 |
4165 } |
4080 } |
4166 |
4081 |
|
4082 /** |
|
4083 * Generate a packet to send to the client for logins. |
|
4084 * @param string mode |
|
4085 * @param array |
|
4086 * @return array |
|
4087 */ |
|
4088 |
|
4089 function get_login_response($mode, $error = false, $base = array()) |
|
4090 { |
|
4091 $this->start(); |
|
4092 |
|
4093 // init |
|
4094 $response = $base; |
|
4095 // modules in the packet |
|
4096 $response['mode'] = $mode; |
|
4097 $response['error'] = $error; |
|
4098 $response['crypto'] = $mode !== 'login_success' ? $this->get_login_crypto_packet() : false; |
|
4099 $response['lockout'] = $mode !== 'login_success' ? $this->get_lockout_info() : false; |
|
4100 $response['extended_time'] = intval(getConfig('session_remember_time', '30')); |
|
4101 $response['username'] = $this->user_logged_in ? $this->username : false; |
|
4102 return $response; |
|
4103 } |
|
4104 |
|
4105 /** |
|
4106 * Get a packet of crypto flags for login. |
|
4107 * @return array |
|
4108 */ |
|
4109 |
|
4110 function get_login_crypto_packet() |
|
4111 { |
|
4112 global $dh_supported, $_math; |
|
4113 |
|
4114 $response = array(); |
|
4115 |
|
4116 $response['dh_enable'] = $dh_supported; |
|
4117 $response['aes_key'] = $this->rijndael_genkey(); |
|
4118 |
|
4119 // Can we do Diffie-Hellman? If so, generate and stash a public/private key pair. |
|
4120 if ( $dh_supported ) |
|
4121 { |
|
4122 $dh_key_priv = dh_gen_private(); |
|
4123 $dh_key_pub = dh_gen_public($dh_key_priv); |
|
4124 $dh_key_priv = $_math->str($dh_key_priv); |
|
4125 $dh_key_pub = $_math->str($dh_key_pub); |
|
4126 $response['dh_public_key'] = $dh_key_pub; |
|
4127 // store the keys in the DB |
|
4128 $this->sql('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); |
|
4129 } |
|
4130 |
|
4131 return $response; |
|
4132 } |
|
4133 |
4167 } |
4134 } |
4168 |
4135 |
4169 /** |
4136 /** |
4170 * Class used to fetch permissions for a specific page. Used internally by SessionManager. |
4137 * Class used to fetch permissions for a specific page. Used internally by SessionManager. |
4171 * @package Enano |
4138 * @package Enano |