46 $__login_status = ''; |
46 $__login_status = ''; |
47 |
47 |
48 function page_Special_Login() |
48 function page_Special_Login() |
49 { |
49 { |
50 global $db, $session, $paths, $template, $plugins; // Common objects |
50 global $db, $session, $paths, $template, $plugins; // Common objects |
51 global $__login_status; |
51 global $login_result; |
52 global $lang; |
52 global $lang, $output; |
53 |
53 |
54 require_once(ENANO_ROOT . '/includes/math.php'); |
54 // Determine which level we're going up to |
55 require_once(ENANO_ROOT . '/includes/diffiehellman.php'); |
|
56 global $dh_supported; |
|
57 |
|
58 $locked_out = false; |
|
59 // are we locked out? |
|
60 $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5; |
|
61 $duration = ( $_ = getConfig('lockout_duration') ) ? intval($_) : 15; |
|
62 // convert to minutes |
|
63 $duration = $duration * 60; |
|
64 $policy = ( $x = getConfig('lockout_policy') && in_array(getConfig('lockout_policy'), array('lockout', 'disable', 'captcha')) ) ? getConfig('lockout_policy') : 'lockout'; |
|
65 if ( $policy != 'disable' ) |
|
66 { |
|
67 $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']); |
|
68 $timestamp_cutoff = time() - $duration; |
|
69 $q = $session->sql('SELECT timestamp FROM '.table_prefix.'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;'); |
|
70 $fails = $db->numrows(); |
|
71 if ( $fails >= $threshold ) |
|
72 { |
|
73 $row = $db->fetchrow(); |
|
74 $locked_out = true; |
|
75 $lockdata = array( |
|
76 'locked_out' => true, |
|
77 'lockout_threshold' => $threshold, |
|
78 'lockout_duration' => ( $duration / 60 ), |
|
79 'lockout_fails' => $fails, |
|
80 'lockout_policy' => $policy, |
|
81 'lockout_last_time' => $row['timestamp'], |
|
82 'time_rem' => ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ), |
|
83 'captcha' => '' |
|
84 ); |
|
85 if ( $policy == 'captcha' ) |
|
86 { |
|
87 $lockdata['captcha'] = $session->make_captcha(); |
|
88 } |
|
89 } |
|
90 $db->free_result(); |
|
91 } |
|
92 |
|
93 if ( isset($_GET['act']) && $_GET['act'] == 'getkey' ) |
|
94 { |
|
95 header('Content-type: text/javascript'); |
|
96 $username = ( $session->user_logged_in ) ? $session->username : false; |
|
97 $response = Array( |
|
98 'username' => $username, |
|
99 'key' => $pubkey, |
|
100 'challenge' => $challenge, |
|
101 'locked_out' => false |
|
102 ); |
|
103 |
|
104 if ( $locked_out ) |
|
105 { |
|
106 foreach ( $lockdata as $x => $y ) |
|
107 { |
|
108 $response[$x] = $y; |
|
109 } |
|
110 unset($x, $y); |
|
111 } |
|
112 |
|
113 // 1.1.3: generate diffie hellman key |
|
114 $response['dh_supported'] = $dh_supported; |
|
115 if ( $dh_supported ) |
|
116 { |
|
117 $dh_key_priv = dh_gen_private(); |
|
118 $dh_key_pub = dh_gen_public($dh_key_priv); |
|
119 $dh_key_priv = $_math->str($dh_key_priv); |
|
120 $dh_key_pub = $_math->str($dh_key_pub); |
|
121 $response['dh_public_key'] = $dh_key_pub; |
|
122 // store the keys in the DB |
|
123 $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );"); |
|
124 if ( !$q ) |
|
125 $db->die_json(); |
|
126 } |
|
127 |
|
128 $response = enano_json_encode($response); |
|
129 echo $response; |
|
130 return null; |
|
131 } |
|
132 |
|
133 $level = ( isset($_GET['level']) && in_array($_GET['level'], array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ) ) ? intval($_GET['level']) : USER_LEVEL_MEMBER; |
55 $level = ( isset($_GET['level']) && in_array($_GET['level'], array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ) ) ? intval($_GET['level']) : USER_LEVEL_MEMBER; |
134 if ( isset($_POST['login']) ) |
56 if ( isset($_POST['login']) ) |
135 { |
57 { |
136 if ( in_array($_POST['auth_level'], array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ) ) |
58 if ( in_array($_POST['level'], array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ) ) |
137 { |
59 { |
138 $level = intval($_POST['auth_level']); |
60 $level = intval($_POST['level']); |
139 } |
61 } |
140 } |
62 } |
141 |
63 // Don't allow going from guest straight to elevated |
|
64 // FIXME do we want to allow this with a CSRF check? |
142 if ( $level > USER_LEVEL_MEMBER && !$session->user_logged_in ) |
65 if ( $level > USER_LEVEL_MEMBER && !$session->user_logged_in ) |
143 { |
66 { |
144 $level = USER_LEVEL_MEMBER; |
67 $level = USER_LEVEL_MEMBER; |
145 } |
68 } |
|
69 |
|
70 // If we're already at or above this level, redirect to the target page or, if no target |
|
71 // specified, back to the main page. |
146 if ( $level <= USER_LEVEL_MEMBER && $session->user_logged_in ) |
72 if ( $level <= USER_LEVEL_MEMBER && $session->user_logged_in ) |
147 { |
73 { |
148 if ( $target = $paths->getAllParams() ) |
74 if ( $target = $paths->getAllParams() ) |
149 { |
75 { |
150 redirect(makeUrl($target), '', '', 0); |
76 redirect(makeUrl($target), '', '', 0); |
151 } |
77 } |
152 $paths->main_page(); |
78 $paths->main_page(); |
153 } |
79 } |
154 |
80 |
155 $template->header(); |
81 // Lockout aliasing |
156 echo '<form action="'.makeUrl($paths->nslist['Special'].'Login').'" method="post" name="loginform" onsubmit="try{runEncryption();}catch(e){};">'; |
82 $lockout =& $login_result['lockout']; |
157 $header = ( $level > USER_LEVEL_MEMBER ) ? $lang->get('user_login_message_short_elev') : $lang->get('user_login_message_short'); |
83 |
158 if ( isset($_POST['login']) ) |
84 $output->header(); |
159 { |
85 echo '<form action="' . makeUrl($paths->nslist['Special'].'Login') . '" method="post" name="loginform" onsubmit="try { return runEncryption(); } catch(e) { console.error(e); };">'; |
160 $errstring = $__login_status['error']; |
86 |
161 switch($__login_status['error']) |
|
162 { |
|
163 case 'key_not_found': |
|
164 $errstring = $lang->get('user_err_key_not_found'); |
|
165 break; |
|
166 case 'ERR_DH_KEY_NOT_FOUND': |
|
167 $errstring = $lang->get('user_err_dh_key_not_found'); // . " -- {$__login_status['debug']}"; |
|
168 break; |
|
169 case 'ERR_DH_KEY_NOT_INTEGER': |
|
170 $errstring = $lang->get('user_err_dh_key_not_numeric'); |
|
171 break; |
|
172 case 'key_wrong_length': |
|
173 $errstring = $lang->get('user_err_key_wrong_length'); |
|
174 break; |
|
175 case 'too_big_for_britches': |
|
176 $errstring = $lang->get('user_err_too_big_for_britches'); |
|
177 break; |
|
178 case 'invalid_credentials': |
|
179 $errstring = $lang->get('user_err_invalid_credentials'); |
|
180 if ( getConfig('lockout_policy', 'lockout') == 'lockout' ) |
|
181 { |
|
182 $errstring .= $lang->get('user_err_invalid_credentials_lockout', array('fails' => $__login_status['lockout_fails'])); |
|
183 } |
|
184 else if ( getConfig('lockout_policy', 'lockout') == 'captcha' ) |
|
185 { |
|
186 $errstring .= $lang->get('user_err_invalid_credentials_lockout_captcha', array('fails' => $__login_status['lockout_fails'])); |
|
187 } |
|
188 break; |
|
189 case 'backend_fail': |
|
190 $errstring = $lang->get('user_err_backend_fail'); |
|
191 break; |
|
192 case 'locked_out': |
|
193 $attempts = intval($__login_status['lockout_fails']); |
|
194 if ( $attempts > $__login_status['lockout_threshold']) |
|
195 $attempts = $__login_status['lockout_threshold']; |
|
196 |
|
197 $server_time = time(); |
|
198 $time_rem = ( intval(@$__login_status['lockout_last_time']) == time() ) ? $__login_status['lockout_duration'] : $__login_status['lockout_duration'] - round( ( $server_time - $__login_status['lockout_last_time'] ) / 60 ); |
|
199 if ( $time_rem < 1 ) |
|
200 $time_rem = $__login_status['lockout_duration']; |
|
201 |
|
202 $s = ( $time_rem == 1 ) ? '' : $lang->get('meta_plural'); |
|
203 |
|
204 $captcha_string = ( $__login_status['lockout_policy'] == 'captcha' ) ? $lang->get('user_err_locked_out_captcha_blurb') : ''; |
|
205 $errstring = $lang->get('user_err_locked_out', array('plural' => $s, 'captcha_blurb' => $captcha_string, 'time_rem' => $time_rem)); |
|
206 |
|
207 break; |
|
208 default: |
|
209 $errstring = $lang->get($errstring); |
|
210 break; |
|
211 } |
|
212 echo '<div class="error-box-mini">'.$errstring.'</div>'; |
|
213 } |
|
214 if ( $p = $paths->getAllParams() ) |
87 if ( $p = $paths->getAllParams() ) |
215 { |
88 { |
216 echo '<input type="hidden" name="return_to" value="'.$p.'" />'; |
89 echo '<input type="hidden" name="return_to" value="' . htmlspecialchars($p) . '" />'; |
217 } |
90 } |
218 else if ( isset($_POST['login']) && isset($_POST['return_to']) ) |
91 else if ( isset($_POST['login']) && isset($_POST['return_to']) ) |
219 { |
92 { |
220 echo '<input type="hidden" name="return_to" value="'.htmlspecialchars($_POST['return_to']).'" />'; |
93 echo '<input type="hidden" name="return_to" value="' . htmlspecialchars($_POST['return_to']) . '" />'; |
221 } |
94 } |
|
95 |
|
96 // determine what the "remember me" checkbox should say |
|
97 $session_time = intval(getConfig('session_remember_time', '30')); |
|
98 if ( $session_time === 0 ) |
|
99 { |
|
100 // sessions are infinite |
|
101 $text_remember = $lang->get('user_login_check_remember_infinite'); |
|
102 } |
|
103 else |
|
104 { |
|
105 // is the number of days evenly divisible by 7? if so, use weeks |
|
106 if ( $session_time % 7 == 0 ) |
|
107 { |
|
108 $session_time = $session_time / 7; |
|
109 $unit = 'week'; |
|
110 } |
|
111 else |
|
112 { |
|
113 $unit = 'day'; |
|
114 } |
|
115 // if it's not equal to 1, pluralize it |
|
116 if ( $session_time != 1 ) |
|
117 { |
|
118 $unit .= $lang->get('meta_plural'); |
|
119 } |
|
120 $text_remember = $lang->get('user_login_check_remember', array( |
|
121 'session_length' => $session_time, |
|
122 'length_units' => $lang->get("etc_unit_$unit") |
|
123 )); |
|
124 } |
|
125 |
|
126 if ( $error_text = login_get_error($login_result) ) |
|
127 { |
|
128 echo '<div class="error-box-mini">' . htmlspecialchars($error_text) . '</div>'; |
|
129 } |
|
130 |
|
131 // |
|
132 // START FORM |
|
133 // |
222 ?> |
134 ?> |
223 <div class="tblholder"> |
135 <div class="tblholder"> |
224 <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4"> |
136 <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4"> |
225 <tr> |
137 <tr> |
226 <th colspan="3"><?php echo $header; ?></th> |
138 <th colspan="3"> |
|
139 <!-- Table header: "Please enter..." --> |
|
140 <?php echo ( $level > USER_LEVEL_MEMBER ) ? $lang->get('user_login_message_short_elev') : $lang->get('user_login_message_short'); ?> |
|
141 </th> |
227 </tr> |
142 </tr> |
228 <tr> |
143 <tr> |
229 <td colspan="3" class="row1"> |
144 <td colspan="3" class="row1"> |
|
145 <!-- Introduction text --> |
230 <?php |
146 <?php |
231 if ( $level <= USER_LEVEL_MEMBER ) |
147 if ( $level <= USER_LEVEL_MEMBER ) |
232 { |
|
233 echo '<p>' . $lang->get('user_login_body', array('reg_link' => makeUrlNS('Special', 'Register'))) . '</p>'; |
148 echo '<p>' . $lang->get('user_login_body', array('reg_link' => makeUrlNS('Special', 'Register'))) . '</p>'; |
234 } |
|
235 else |
149 else |
236 { |
|
237 echo '<p>' . $lang->get('user_login_body_elev') . '</p>'; |
150 echo '<p>' . $lang->get('user_login_body_elev') . '</p>'; |
238 } |
|
239 ?> |
151 ?> |
240 </td> |
152 </td> |
241 </tr> |
153 </tr> |
242 <tr> |
154 <tr> |
|
155 <!-- Username field --> |
243 <td class="row2"> |
156 <td class="row2"> |
244 <?php echo $lang->get('user_login_field_username'); ?>: |
157 <?php echo $lang->get('user_login_field_username'); ?>: |
245 </td> |
158 </td> |
246 <td class="row1"> |
159 <td class="row1"> |
247 <input name="username" size="25" type="text" <?php |
160 <input name="username" size="25" type="text" value="<?php echo $session->user_logged_in ? htmlspecialchars($session->username) : ''; ?>" /> |
248 if ( $level <= USER_LEVEL_MEMBER ) |
|
249 { |
|
250 echo 'tabindex="1" '; |
|
251 } |
|
252 else |
|
253 { |
|
254 echo 'tabindex="3" '; |
|
255 } |
|
256 if ( $session->user_logged_in ) |
|
257 { |
|
258 echo 'value="' . $session->username . '"'; |
|
259 } |
|
260 ?> /> |
|
261 </td> |
161 </td> |
262 <?php if ( $level <= USER_LEVEL_MEMBER ) { ?> |
162 <?php if ( $level <= USER_LEVEL_MEMBER ): ?> |
263 <td rowspan="<?php echo ( ( $locked_out && $lockdata['lockout_policy'] == 'captcha' ) ) ? '4' : '2'; ?>" class="row3"> |
163 <!-- Forgot password / create account links --> |
|
164 <td rowspan="<?php echo ( ( $lockout['active'] && $lockout['policy'] == 'captcha' ) ) ? '4' : '2'; ?>" class="row3"> |
264 <small><?php echo $lang->get('user_login_forgotpass_blurb', array('forgotpass_link' => makeUrlNS('Special', 'PasswordReset'))); ?><br /> |
165 <small><?php echo $lang->get('user_login_forgotpass_blurb', array('forgotpass_link' => makeUrlNS('Special', 'PasswordReset'))); ?><br /> |
265 <?php echo $lang->get('user_login_createaccount_blurb', array('reg_link' => makeUrlNS('Special', 'Register'))); ?></small> |
166 <?php echo $lang->get('user_login_createaccount_blurb', array('reg_link' => makeUrlNS('Special', 'Register'))); ?></small> |
266 </td> |
167 </td> |
267 <?php } ?> |
168 <?php endif; ?> |
268 </tr> |
169 </tr> |
269 <tr> |
170 <tr> |
|
171 <!-- Password field --> |
270 <td class="row2"> |
172 <td class="row2"> |
271 <?php echo $lang->get('user_login_field_password'); ?>: |
173 <?php echo $lang->get('user_login_field_password'); ?>: |
272 </td><td class="row1"><input name="pass" size="25" type="password" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '2' : '1'; ?>" /></td> |
174 </td><td class="row1"><input name="password" size="25" type="password" /></td> |
273 </tr> |
175 </tr> |
|
176 |
274 <?php |
177 <?php |
275 if ( $locked_out && $lockdata['lockout_policy'] == 'captcha' ) |
178 // CAPTCHA? |
|
179 if ( $lockout['active'] && $lockout['policy'] == 'captcha' ) |
276 { |
180 { |
277 ?> |
181 ?> |
|
182 <!-- CAPTCHA --> |
278 <tr> |
183 <tr> |
279 <td class="row2" rowspan="2"><?php echo $lang->get('user_login_field_captcha'); ?>:<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> |
184 <td class="row2" rowspan="2"> |
|
185 <?php echo $lang->get('user_login_field_captcha'); ?>: |
|
186 <br /> |
|
187 </td> |
|
188 <td class="row1"> |
|
189 <input type="hidden" name="captcha_hash" value="<?php echo $lockout['captcha']; ?>" /> |
|
190 <input name="captcha_code" size="25" type="text" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '3' : '4'; ?>" /> |
|
191 </td> |
280 </tr> |
192 </tr> |
281 <tr> |
193 <tr> |
282 <td class="row3"> |
194 <td class="row3"> |
283 <img src="<?php echo makeUrlNS('Special', 'Captcha/' . $lockdata['captcha']) ?>" onclick="this.src=this.src+'/a';" style="cursor: pointer;" /> |
195 <img src="<?php echo makeUrlNS('Special', 'Captcha/' . $lockout['captcha']) ?>" onclick="this.src=this.src+'/a';" style="cursor: pointer;" /> |
284 </td> |
196 </td> |
285 </tr> |
197 </tr> |
286 <?php |
198 <?php |
287 } |
199 } |
|
200 |
|
201 // Run hooks |
288 $code = $plugins->setHook('login_form_html'); |
202 $code = $plugins->setHook('login_form_html'); |
289 foreach ( $code as $cmd ) |
203 foreach ( $code as $cmd ) |
290 { |
204 { |
291 eval($cmd); |
205 eval($cmd); |
292 } |
206 } |
|
207 |
|
208 // level-2 only: "Remember me" switch |
293 if ( $level <= USER_LEVEL_MEMBER ) |
209 if ( $level <= USER_LEVEL_MEMBER ) |
294 { |
210 { |
295 // "remember me" switch |
|
296 // first order of business is to determine what the checkbox should say |
|
297 $session_time = intval(getConfig('session_remember_time', '30')); |
|
298 if ( $session_time === 0 ) |
|
299 { |
|
300 // sessions are infinite |
|
301 $text_remember = $lang->get('user_login_check_remember_infinite'); |
|
302 } |
|
303 else |
|
304 { |
|
305 // is the number of days evenly divisible by 7? if so, use weeks |
|
306 if ( $session_time % 7 == 0 ) |
|
307 { |
|
308 $session_time = $session_time / 7; |
|
309 $unit = 'week'; |
|
310 } |
|
311 else |
|
312 { |
|
313 $unit = 'day'; |
|
314 } |
|
315 // if it's not equal to 1, pluralize it |
|
316 if ( $session_time != 1 ) |
|
317 { |
|
318 $unit .= 's'; |
|
319 } |
|
320 $text_remember = $lang->get('user_login_check_remember', array( |
|
321 'session_length' => $session_time, |
|
322 'length_units' => $lang->get("etc_unit_$unit") |
|
323 )); |
|
324 } |
|
325 ?> |
211 ?> |
326 <tr> |
212 <tr> |
327 <td class="row2"> |
213 <td class="row2"> |
328 <?php echo $lang->get('user_login_field_remember'); ?> |
214 <?php echo $lang->get('user_login_field_remember'); ?> |
329 </td> |
215 </td> |
457 echo enano_json_encode($session->process_login_request($request)); |
355 echo enano_json_encode($session->process_login_request($request)); |
458 |
356 |
459 $db->close(); |
357 $db->close(); |
460 exit; |
358 exit; |
461 } |
359 } |
462 if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' ) |
360 |
463 { |
361 // No. Process incoming results from the HTML version. |
464 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.'; |
362 if ( isset($_POST['login']) ) |
465 return true; |
363 { |
466 } |
364 $_POST['password'] = $session->get_aes_post(); |
467 if(isset($_POST['login'])) |
365 |
468 { |
366 $result = $session->process_login_request(array( |
469 $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false; |
367 'mode' => 'login_pt', |
470 $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false; |
368 'userinfo' => $_POST, |
471 |
369 'level' => $_POST['level'], |
472 try |
370 'captcha_hash' => isset($_POST['captcha_hash']) ? $_POST['captcha_hash'] : false, |
473 { |
371 'captcha_code' => isset($_POST['captcha_code']) ? $_POST['captcha_code'] : false |
474 $password = $session->get_aes_post('pass'); |
372 )); |
475 } |
373 |
476 catch ( Exception $e ) |
374 if ( $result['mode'] === 'login_success' ) |
477 { |
375 { |
478 $__login_status = array( |
376 // |
479 'mode' => 'error', |
377 // LOGIN SUCCESS. |
480 'error' => $e->getMessage() |
378 // Redirect as necessary. |
481 ); |
379 // |
482 return false; |
380 |
483 } |
381 // Load our preferences |
484 |
|
485 // These are to allow auth plugins to work universally between JSON and HTML login forms |
|
486 $userinfo =& $_POST; |
|
487 $userinfo['password'] =& $password; |
|
488 $req = array( |
|
489 'level' => intval($_POST['auth_level']), |
|
490 'remember' => isset($_POST['remember']) |
|
491 ); |
|
492 |
|
493 // At this point if any extra fields were injected into the login form, we need to let plugins process it |
|
494 |
|
495 /** |
|
496 * Called upon processing an incoming login request from the plain HTML login form.. If you added anything to the form, |
|
497 * that will be in the $userinfo array here and on $_POST. Expected return values are: true if your plugin has |
|
498 * not only succeeded but ALSO issued a session key (bypass the whole Enano builtin login process) and an associative array |
|
499 * with "mode" set to "error" and an error string in "error" to send an error back to the client. Any return value other |
|
500 * than these will be ignored. |
|
501 * @hook login_process_userdata_json |
|
502 */ |
|
503 |
|
504 $skip_normal_login = false; |
|
505 |
|
506 $code = $plugins->setHook('login_process_userdata_json'); |
|
507 foreach ( $code as $cmd ) |
|
508 { |
|
509 $result = eval($cmd); |
|
510 if ( $result === true ) |
|
511 { |
|
512 $skip_normal_login = true; |
|
513 $result = array('success' => true); |
|
514 break; |
|
515 } |
|
516 else if ( is_array($result) ) |
|
517 { |
|
518 if ( isset($result['mode']) && $result['mode'] === 'error' && isset($result['error']) ) |
|
519 { |
|
520 $__login_status = array( |
|
521 'mode' => 'error', |
|
522 'error' => $result['error'] |
|
523 ); |
|
524 return false; |
|
525 } |
|
526 } |
|
527 } |
|
528 |
|
529 if ( !$skip_normal_login ) |
|
530 { |
|
531 $result = $session->login_without_crypto($_POST['username'], $password, false, intval($_POST['auth_level']), $captcha_hash, $captcha_code, isset($_POST['remember'])); |
|
532 } |
|
533 |
|
534 if($result['success']) |
|
535 { |
|
536 $session->start(); |
382 $session->start(); |
537 |
383 |
|
384 // Decode get_add |
538 $get_add = false; |
385 $get_add = false; |
539 if ( isset($_POST['get_fwd']) ) |
386 if ( isset($_POST['get_fwd']) ) |
540 { |
387 { |
541 try |
388 try |
542 { |
389 { |
551 catch ( Exception $e ) |
398 catch ( Exception $e ) |
552 { |
399 { |
553 } |
400 } |
554 } |
401 } |
555 |
402 |
556 $template->load_theme($session->theme, $session->style); |
403 // Going to a user-specified page? |
557 if(isset($_POST['return_to'])) |
404 if ( isset($_POST['return_to']) ) |
558 { |
405 { |
|
406 // yea |
559 $name = get_page_title($_POST['return_to']); |
407 $name = get_page_title($_POST['return_to']); |
560 $subst = array( |
408 $subst = array( |
561 'username' => $session->username, |
409 'username' => $session->username, |
562 'redir_target' => $name |
410 'redir_target' => $name |
563 ); |
411 ); |
564 redirect( makeUrl($_POST['return_to'], $get_add), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) ); |
412 redirect( makeUrl($_POST['return_to'], $get_add), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) ); |
565 } |
413 } |
566 else |
414 else |
567 { |
415 { |
|
416 // No, redirect them to the main page |
568 $subst = array( |
417 $subst = array( |
569 'username' => $session->username, |
418 'username' => $session->username, |
570 'redir_target' => $lang->get('user_login_success_body_mainpage') |
419 'redir_target' => $lang->get('user_login_success_body_mainpage') |
571 ); |
420 ); |
572 redirect( makeUrl(get_main_page(), $get_add), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) ); |
421 redirect( makeUrl(get_main_page(), $get_add), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) ); |
573 } |
422 } |
574 } |
423 } |
575 else |
424 else if ( $result['mode'] === 'login_success_reset' ) |
576 { |
425 { |
577 if ( $result['error'] === 'valid_reset' ) |
426 // They logged in with a temporary password; send them to the reset form |
578 { |
427 redirect($result['redirect_url'], '', '', 0); |
579 header('HTTP/1.1 302 Temporary Redirect'); |
428 } |
580 header('Location: ' . $result['redirect_url']); |
429 // Otherwise, the result is likely an error. |
581 |
430 $login_result = $result; |
582 $db->close(); |
431 } |
583 exit(); |
432 else |
584 } |
433 { |
585 $GLOBALS['__login_status'] = $result; |
434 $login_result = $session->process_login_request(array( |
586 } |
435 'mode' => 'getkey' |
|
436 )); |
|
437 } |
|
438 |
|
439 // This is a bit of a hack. The login form generates AES and DiffieHellman keys on its |
|
440 // own, so we need to clean up the ones from the login request API. |
|
441 if ( !empty($login_result['crypto']) ) |
|
442 { |
|
443 $session->process_login_request(array( |
|
444 'mode' => 'clean_key', |
|
445 'key_aes' => $login_result['crypto']['aes_key'], |
|
446 'key_dh' => $login_result['crypto']['dh_public_key'], |
|
447 )); |
587 } |
448 } |
588 } |
449 } |
589 |
450 |
590 function SpecialLogin_SendResponse_PasswordReset($user_id, $passkey) |
451 /** |
|
452 * Given a Login API response, find the appropriate error text, if any. |
|
453 * @param array LoginAPI response |
|
454 * @return mixed Error string, or bool(false) if no error. |
|
455 */ |
|
456 |
|
457 function login_get_error($response) |
591 { |
458 { |
592 $response = Array( |
459 global $lang; |
593 'result' => 'success_reset', |
460 |
594 'user_id' => $user_id, |
461 if ( !empty($response['lockout']) ) |
595 'temppass' => $passkey |
462 { |
596 ); |
463 // set this pluralality thing |
597 |
464 $response['lockout']['plural'] = $response['lockout']['time_rem'] == 1 ? '' : $lang->get('meta_plural'); |
598 $response = enano_json_encode($response); |
465 } |
599 echo $response; |
466 |
600 |
467 if ( $response['mode'] == 'initial' ) |
601 $db->close(); |
468 { |
602 exit; |
469 // Just showing the box for the first time. If there's an error now, it's based on a preexisting lockout. |
|
470 if ( $response['lockout']['active'] ) |
|
471 { |
|
472 return $lang->get('user_err_locked_out_initial_' . $response['lockout']['policy'], $response['lockout']); |
|
473 } |
|
474 return false; |
|
475 } |
|
476 else |
|
477 { |
|
478 // An attempt was made. |
|
479 switch($response['mode']) |
|
480 { |
|
481 case 'login_failure': |
|
482 // Generic login user error. |
|
483 $error = ''; |
|
484 if ( ($x = $lang->get($response['error'])) != $response['error'] ) |
|
485 $error = $x; |
|
486 else |
|
487 $error = $lang->get('user_err_' . $response['error']); |
|
488 if ( $response['lockout']['active'] && $response['lockout']['policy'] == 'lockout' ) |
|
489 { |
|
490 // Lockout enforcement was just activated. |
|
491 return $lang->get('user_err_locked_out_initial_' . $response['lockout']['policy'], $response['lockout']); |
|
492 } |
|
493 else if ( $response['lockout']['policy'] != 'disable' && !$response['lockout']['active'] && $response['lockout']['fails'] > 0 ) |
|
494 { |
|
495 // Lockout is in a warning state. |
|
496 $error .= ' ' . $lang->get('user_err_invalid_credentials_' . $response['lockout']['policy'], $response['lockout']); |
|
497 } |
|
498 return $error; |
|
499 break; |
|
500 case 'api_error': |
|
501 // Error in the API. |
|
502 return $lang->get('user_err_login_generic_title') + ': ' + $lang->get('user_' . strtolower($response['error'])); |
|
503 break; |
|
504 } |
|
505 } |
|
506 |
|
507 return is_string($response['error']) ? $response['error'] : false; |
603 } |
508 } |
604 |
509 |
605 function page_Special_Logout() |
510 function page_Special_Logout() |
606 { |
511 { |
607 global $db, $session, $paths, $template, $plugins; // Common objects |
512 global $db, $session, $paths, $template, $plugins; // Common objects |