102 global $__login_status; |
102 global $__login_status; |
103 |
103 |
104 $pubkey = $session->rijndael_genkey(); |
104 $pubkey = $session->rijndael_genkey(); |
105 $challenge = $session->dss_rand(); |
105 $challenge = $session->dss_rand(); |
106 |
106 |
|
107 $locked_out = false; |
|
108 // are we locked out? |
|
109 $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5; |
|
110 $duration = ( $_ = getConfig('lockout_duration') ) ? intval($_) : 15; |
|
111 // convert to minutes |
|
112 $duration = $duration * 60; |
|
113 $policy = ( $x = getConfig('lockout_policy') && in_array(getConfig('lockout_policy'), array('lockout', 'disable', 'captcha')) ) ? getConfig('lockout_policy') : 'lockout'; |
|
114 if ( $policy != 'disable' ) |
|
115 { |
|
116 $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); |
|
117 $timestamp_cutoff = time() - $duration; |
|
118 $q = $session->sql('SELECT timestamp FROM '.table_prefix.'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;'); |
|
119 $fails = $db->numrows(); |
|
120 if ( $fails >= $threshold ) |
|
121 { |
|
122 $row = $db->fetchrow(); |
|
123 $locked_out = true; |
|
124 $lockdata = array( |
|
125 'locked_out' => true, |
|
126 'lockout_threshold' => $threshold, |
|
127 'lockout_duration' => ( $duration / 60 ), |
|
128 'lockout_fails' => $fails, |
|
129 'lockout_policy' => $policy, |
|
130 'lockout_last_time' => $row['timestamp'], |
|
131 'server_time' => time(), |
|
132 'captcha' => '' |
|
133 ); |
|
134 if ( $policy == 'captcha' ) |
|
135 { |
|
136 $lockdata['captcha'] = $session->make_captcha(); |
|
137 } |
|
138 } |
|
139 $db->free_result(); |
|
140 } |
|
141 |
107 if ( isset($_GET['act']) && $_GET['act'] == 'getkey' ) |
142 if ( isset($_GET['act']) && $_GET['act'] == 'getkey' ) |
108 { |
143 { |
109 $username = ( $session->user_logged_in ) ? $session->username : false; |
144 $username = ( $session->user_logged_in ) ? $session->username : false; |
110 $response = Array( |
145 $response = Array( |
111 'username' => $username, |
146 'username' => $username, |
112 'key' => $pubkey, |
147 'key' => $pubkey, |
113 'challenge' => $challenge |
148 'challenge' => $challenge, |
|
149 'locked_out' => false |
114 ); |
150 ); |
|
151 |
|
152 if ( $locked_out ) |
|
153 { |
|
154 foreach ( $lockdata as $x => $y ) |
|
155 { |
|
156 $response[$x] = $y; |
|
157 } |
|
158 unset($x, $y); |
|
159 } |
|
160 |
115 $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); |
161 $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); |
116 $response = $json->encode($response); |
162 $response = $json->encode($response); |
117 echo $response; |
163 echo $response; |
118 return null; |
164 return null; |
119 } |
165 } |
136 $template->header(); |
182 $template->header(); |
137 echo '<form action="'.makeUrl($paths->nslist['Special'].'Login').'" method="post" name="loginform" onsubmit="runEncryption();">'; |
183 echo '<form action="'.makeUrl($paths->nslist['Special'].'Login').'" method="post" name="loginform" onsubmit="runEncryption();">'; |
138 $header = ( $level > USER_LEVEL_MEMBER ) ? 'Please re-enter your login details' : 'Please enter your username and password to log in.'; |
184 $header = ( $level > USER_LEVEL_MEMBER ) ? 'Please re-enter your login details' : 'Please enter your username and password to log in.'; |
139 if ( isset($_POST['login']) ) |
185 if ( isset($_POST['login']) ) |
140 { |
186 { |
141 echo '<p>'.$__login_status.'</p>'; |
187 $errstring = $__login_status['error']; |
|
188 switch($__login_status['error']) |
|
189 { |
|
190 case 'key_not_found': |
|
191 $errstring = 'Enano couldn\'t look up the encryption key used to encrypt your password. This most often happens if a cache rotation occurred during your login attempt, or if you refreshed the login page.'; |
|
192 break; |
|
193 case 'key_wrong_length': |
|
194 $errstring = 'The encryption key was the wrong length.'; |
|
195 break; |
|
196 case 'too_big_for_britches': |
|
197 $errstring = 'You are trying to authenticate at a level that your user account does not permit.'; |
|
198 break; |
|
199 case 'invalid_credentials': |
|
200 $errstring = 'You have entered an invalid username or password. Please enter your login details again.'; |
|
201 if ( $__login_status['lockout_policy'] == 'lockout' ) |
|
202 { |
|
203 $errstring .= ' You have used up '.$__login_status['lockout_fails'].' out of '.$__login_status['lockout_threshold'].' login attempts. After you have used up all '.$data['lockout_threshold'].' login attempts, you will be locked out from logging in for '.$__login_status['lockout_duration'].' minutes.'; |
|
204 } |
|
205 else if ( $__login_status['lockout_policy'] == 'captcha' ) |
|
206 { |
|
207 $errstring .= ' You have used up '.$__login_status['lockout_fails'].' out of '.$__login_status['lockout_threshold'].' login attempts. After you have used up all '.$data['lockout_threshold'].' login attempts, you will have to enter a visual confirmation code before logging in, effective for '.$__login_status['lockout_duration'].' minutes.'; |
|
208 } |
|
209 break; |
|
210 case 'backend_fail': |
|
211 $errstring = 'You entered the right credentials and everything was validated, but for some reason Enano couldn\'t register your session. This is an internal problem with the site and you are encouraged to contact site administration.'; |
|
212 break; |
|
213 case 'locked_out': |
|
214 $attempts = intval($__login_status['lockout_fails']); |
|
215 if ( $attempts > $__login_status['lockout_threshold']) |
|
216 $attempts = $__login_status['lockout_threshold']; |
|
217 $time_rem = ( $__login_status['lockout_last_time'] % ( $__login_status['lockout_duration'] * 60 ) ); |
|
218 $time_rem = $__login_status['lockout_duration'] - round($time_rem / 60); |
|
219 $s = ( $time_rem == 1 ) ? '' : 's'; |
|
220 $errstring = "You have used up all {$__login_status['lockout_threshold']} allowed login attempts. Please wait {$time_rem} minute$s before attempting to log in again"; |
|
221 if ( $__login_status['lockout_policy'] == 'captcha' ) |
|
222 $errstring .= ', or enter the visual confirmation code shown above in the appropriate box'; |
|
223 $errstring .= '.'; |
|
224 break; |
|
225 } |
|
226 echo '<div class="error-box-mini">'.$errstring.'</div>'; |
142 } |
227 } |
143 if ( $p = $paths->getAllParams() ) |
228 if ( $p = $paths->getAllParams() ) |
144 { |
229 { |
145 echo '<input type="hidden" name="return_to" value="'.$p.'" />'; |
230 echo '<input type="hidden" name="return_to" value="'.$p.'" />'; |
146 } |
231 } |
187 echo 'value="' . $session->username . '"'; |
272 echo 'value="' . $session->username . '"'; |
188 } |
273 } |
189 ?> /> |
274 ?> /> |
190 </td> |
275 </td> |
191 <?php if ( $level <= USER_LEVEL_MEMBER ) { ?> |
276 <?php if ( $level <= USER_LEVEL_MEMBER ) { ?> |
192 <td rowspan="2" class="row3"> |
277 <td rowspan="<?php echo ( ( $locked_out && $lockdata['lockout_policy'] == 'captcha' ) ) ? '4' : '2'; ?>" class="row3"> |
193 <small>Forgot your password? <a href="<?php echo makeUrlNS('Special', 'PasswordReset'); ?>">No problem.</a><br /> |
278 <small>Forgot your password? <a href="<?php echo makeUrlNS('Special', 'PasswordReset'); ?>">No problem.</a><br /> |
194 Maybe you need to <a href="<?php echo makeUrlNS('Special', 'Register'); ?>">create an account</a>.</small> |
279 Maybe you need to <a href="<?php echo makeUrlNS('Special', 'Register'); ?>">create an account</a>.</small> |
195 </td> |
280 </td> |
196 <?php } ?> |
281 <?php } ?> |
197 </tr> |
282 </tr> |
198 <tr> |
283 <tr> |
199 <td class="row2">Password:<br /></td><td class="row1"><input name="pass" size="25" type="password" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '2' : '1'; ?>" /></td> |
284 <td class="row2">Password:<br /></td><td class="row1"><input name="pass" size="25" type="password" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '2' : '1'; ?>" /></td> |
200 </tr> |
285 </tr> |
|
286 <?php |
|
287 if ( $locked_out && $lockdata['lockout_policy'] == 'captcha' ) |
|
288 { |
|
289 ?> |
|
290 <tr> |
|
291 <td class="row2" rowspan="2">Code in image:<br /></td><td class="row1"><input type="hidden" name="captcha_hash" value="<?php echo $lockdata['captcha']; ?>" /><input name="captcha_code" size="25" type="text" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '3' : '4'; ?>" /></td> |
|
292 </tr> |
|
293 <tr> |
|
294 <td class="row3"> |
|
295 <img src="<?php echo makeUrlNS('Special', 'Captcha/' . $lockdata['captcha']) ?>" onclick="this.src=this.src+'/a';" style="cursor: pointer;" /> |
|
296 </td> |
|
297 </tr> |
|
298 <?php |
|
299 } |
|
300 ?> |
201 <?php if ( $level <= USER_LEVEL_MEMBER ) { ?> |
301 <?php if ( $level <= USER_LEVEL_MEMBER ) { ?> |
202 <tr> |
302 <tr> |
203 <td class="row3" colspan="3"> |
303 <td class="row3" colspan="3"> |
204 <p><b>Important note regarding cryptography:</b> Some countries do not allow the import or use of cryptographic technology. If you live in one of the countries listed below, you should <a href="<?php if($p=$paths->getParam(0))$u='/'.$p;else $u='';echo makeUrl($paths->page.$u, 'level='.$level.'&use_crypt=0', true); ?>">log in without using encryption</a>.</p> |
304 <p><b>Important note regarding cryptography:</b> Some countries do not allow the import or use of cryptographic technology. If you live in one of the countries listed below, you should <a href="<?php if($p=$paths->getParam(0))$u='/'.$p;else $u='';echo makeUrl($paths->page.$u, 'level='.$level.'&use_crypt=0', true); ?>">log in without using encryption</a>.</p> |
205 <p>This restriction applies to the following countries: Belarus, China, India, Israel, Kazakhstan, Mongolia, Pakistan, Russia, Saudi Arabia, Singapore, Tunisia, Venezuela, and Vietnam.</p> |
305 <p>This restriction applies to the following countries: Belarus, China, India, Israel, Kazakhstan, Mongolia, Pakistan, Russia, Saudi Arabia, Singapore, Tunisia, Venezuela, and Vietnam.</p> |
240 if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' ) |
340 if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' ) |
241 { |
341 { |
242 $plugins->attachHook('login_password_reset', 'SpecialLogin_SendResponse_PasswordReset($row[\'user_id\'], $row[\'temp_password\']);'); |
342 $plugins->attachHook('login_password_reset', 'SpecialLogin_SendResponse_PasswordReset($row[\'user_id\'], $row[\'temp_password\']);'); |
243 $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); |
343 $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); |
244 $data = $json->decode($_POST['params']); |
344 $data = $json->decode($_POST['params']); |
|
345 $captcha_hash = ( isset($data['captcha_hash']) ) ? $data['captcha_hash'] : false; |
|
346 $captcha_code = ( isset($data['captcha_code']) ) ? $data['captcha_code'] : false; |
245 $level = ( isset($data['level']) ) ? intval($data['level']) : USER_LEVEL_MEMBER; |
347 $level = ( isset($data['level']) ) ? intval($data['level']) : USER_LEVEL_MEMBER; |
246 $result = $session->login_with_crypto($data['username'], $data['crypt_data'], $data['crypt_key'], $data['challenge'], $level); |
348 $result = $session->login_with_crypto($data['username'], $data['crypt_data'], $data['crypt_key'], $data['challenge'], $level, $captcha_hash, $captcha_code); |
247 $session->start(); |
349 $session->start(); |
248 //echo "$result\n$session->sid_super"; |
350 if ( $result['success'] ) |
249 //exit; |
|
250 if ( $result == 'success' ) |
|
251 { |
351 { |
252 $response = Array( |
352 $response = Array( |
253 'result' => 'success', |
353 'result' => 'success', |
254 'key' => $session->sid_super // ( ( $session->sid_super ) ? $session->sid_super : $session->sid ) |
354 'key' => $session->sid_super // ( ( $session->sid_super ) ? $session->sid_super : $session->sid ) |
255 ); |
355 ); |
256 } |
356 } |
257 else |
357 else |
258 { |
358 { |
|
359 $captcha = ''; |
|
360 if ( $result['error'] == 'locked_out' && $result['lockout_policy'] == 'captcha' ) |
|
361 { |
|
362 $session->kill_captcha(); |
|
363 $captcha = $session->make_captcha(); |
|
364 } |
259 $response = Array( |
365 $response = Array( |
260 'result' => 'error', |
366 'result' => 'error', |
261 'error' => $result |
367 'data' => $result, |
|
368 'captcha' => $captcha |
262 ); |
369 ); |
263 } |
370 } |
264 $response = $json->encode($response); |
371 $response = $json->encode($response); |
265 echo $response; |
372 echo $response; |
266 $db->close(); |
373 $db->close(); |
267 exit; |
374 exit; |
268 } |
375 } |
269 if(isset($_POST['login'])) { |
376 if(isset($_POST['login'])) { |
|
377 $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false; |
|
378 $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false; |
270 if($_POST['use_crypt'] == 'yes') |
379 if($_POST['use_crypt'] == 'yes') |
271 { |
380 { |
272 $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level'])); |
381 $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']), $captcha_hash, $captcha_code); |
273 } |
382 } |
274 else |
383 else |
275 { |
384 { |
276 $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level'])); |
385 $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code); |
277 } |
386 } |
278 $session->start(); |
387 $session->start(); |
279 $paths->init(); |
388 $paths->init(); |
280 if($result == 'success') |
389 if($result['success']) |
281 { |
390 { |
282 $template->load_theme($session->theme, $session->style); |
391 $template->load_theme($session->theme, $session->style); |
283 if(isset($_POST['return_to'])) |
392 if(isset($_POST['return_to'])) |
284 { |
393 { |
285 $name = ( isset($paths->pages[$_POST['return_to']]['name']) ) ? $paths->pages[$_POST['return_to']]['name'] : $_POST['return_to']; |
394 $name = ( isset($paths->pages[$_POST['return_to']]['name']) ) ? $paths->pages[$_POST['return_to']]['name'] : $_POST['return_to']; |