Commit | Line | Data |
---|---|---|
133aecbe RK |
1 | <?php |
2 | /* This Source Code Form is subject to the terms of the Mozilla Public | |
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, | |
4 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
5 | ||
6 | // Include the common auth system files (including the OAuth2 Server object). | |
7 | require_once(__DIR__.'/authsystem.inc.php'); | |
8 | ||
4c6d8064 | 9 | $errors = $utils->checkForSecureConnection(); |
b0e48c35 | 10 | $utils->sendSecurityHeaders(); |
d26d08a1 | 11 | |
7be13777 | 12 | // Initialize the HTML document with our basic elements. |
3f24953f | 13 | extract($utils->initHTMLDocument(sprintf(_('%s Authentication Server'), $utils->settings['operator_name']))); // sets $document, $html, $head, $title, $body |
d26d08a1 RK |
14 | |
15 | if (!count($errors)) { | |
4c6d8064 | 16 | $session = $utils->initSession(); // Read session or create new session and set cookie. |
d26d08a1 | 17 | $user = array('id' => 0, 'email' => ''); |
b19743bc | 18 | $pagetype = 'default'; |
4c6d8064 | 19 | if (is_null($session)) { |
3f24953f RK |
20 | $errors[] = _('The session system is not working.').' ' |
21 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
4c6d8064 RK |
22 | } |
23 | elseif (array_key_exists('logout', $_GET)) { | |
24 | $result = $db->prepare('UPDATE `auth_sessions` SET `logged_in` = FALSE WHERE `id` = :sessid;'); | |
25 | if (!$result->execute(array(':sessid' => $session['id']))) { | |
26 | $utils->log('logout_failure', 'session: '.$session['id']); | |
b217e836 | 27 | $errors[] = _('Unexpected error while logging out.'); |
4c6d8064 RK |
28 | } |
29 | $session['logged_in'] = 0; | |
30 | } | |
31 | elseif (array_key_exists('email', $_POST)) { | |
fb7b39f0 | 32 | if (!preg_match('/^[^@]+@([^@]+\.[^@]+|localhost)$/', $_POST['email'])) { |
4c6d8064 RK |
33 | $errors[] = _('The email address is invalid.'); |
34 | } | |
d42db7c5 RK |
35 | elseif ($utils->verifyTimeCode($_POST['tcode'] ?? '', $session)) { |
36 | $result = $db->prepare('SELECT `id`, `pwdhash`, `email`, `status`, `verify_hash`, `group_id`, `hcheck_question`, `hcheck_solution` FROM `auth_users` WHERE `email` = :email;'); | |
4c6d8064 | 37 | $result->execute(array(':email' => $_POST['email'])); |
d42db7c5 RK |
38 | $user_data = $result->fetch(PDO::FETCH_ASSOC); |
39 | if ($user_data) { | |
40 | $user = $user_data; | |
41 | } | |
60e46184 RK |
42 | // If we need to add the email to a group, note here which user's group we should be added to - otherwise, set to 0. |
43 | $addgroup = (array_key_exists('grouptoexisting', $_POST) && intval($session['user']) && ($session['user'] != @$user['id'])) ? $session['user'] : 0; | |
d42db7c5 | 44 | if ($user['id'] && $user['status'] != 'unchecked' && array_key_exists('pwd', $_POST)) { |
4c6d8064 RK |
45 | // existing user, check password |
46 | if (($user['status'] == 'ok') && $utils->pwdVerify(@$_POST['pwd'], $user)) { | |
47 | // Check if a newer hashing algorithm is available | |
48 | // or the cost has changed | |
49 | if ($utils->pwdNeedsRehash($user)) { | |
50 | // If so, create a new hash, and replace the old one | |
51 | $newHash = $utils->pwdHash($_POST['pwd']); | |
52 | $result = $db->prepare('UPDATE `auth_users` SET `pwdhash` = :pwdhash WHERE `id` = :userid;'); | |
53 | if (!$result->execute(array(':pwdhash' => $newHash, ':userid' => $user['id']))) { | |
54 | $utils->log('user_hash_save_failure', 'user: '.$user['id']); | |
55 | } | |
56 | else { | |
57 | $utils->log('pwd_rehash_success', 'user: '.$user['id']); | |
58 | } | |
59 | } | |
d26d08a1 | 60 | |
4c6d8064 RK |
61 | // Log user in - update session key for that, see https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines#Login |
62 | $utils->log('login', 'user: '.$user['id']); | |
60e46184 RK |
63 | $prev_session = $session; |
64 | $session = $utils->getLoginSession($user['id'], $session); | |
4c6d8064 RK |
65 | // If a verify_hash if set on a verified user, a password reset had been requested. As a login works right now, cancel that reset request by deleting the hash. |
66 | if (strlen(@$user['verify_hash'])) { | |
67 | $result = $db->prepare('UPDATE `auth_users` SET `verify_hash` = \'\' WHERE `id` = :userid;'); | |
68 | if (!$result->execute(array(':userid' => $user['id']))) { | |
69 | $utils->log('empty_vhash_failure', 'user: '.$user['id']); | |
70 | } | |
71 | else { | |
72 | $user['verify_hash'] = ''; | |
73 | } | |
74 | } | |
60e46184 | 75 | $utils->doRedirectIfSet($prev_session); |
d26d08a1 | 76 | } |
89975cb9 | 77 | else { |
4c6d8064 | 78 | $errors[] = _('This password is invalid or your email is not verified yet. Did you type them correctly?'); |
89975cb9 | 79 | } |
d26d08a1 | 80 | } |
4c6d8064 RK |
81 | else { |
82 | // new user: check password, create user and send verification; existing users: re-send verification or send password change instructions | |
83 | if (array_key_exists('pwd', $_POST)) { | |
84 | $errors += $utils->checkPasswordConstraints(strval($_POST['pwd']), $_POST['email']); | |
85 | } | |
86 | if (!count($errors)) { | |
87 | // Put user into the DB | |
e876642c | 88 | if (!$user['id']) { |
4c6d8064 RK |
89 | $newHash = $utils->pwdHash($_POST['pwd']); |
90 | $vcode = $utils->createVerificationCode(); | |
d42db7c5 RK |
91 | $result = $db->prepare('INSERT INTO `auth_users` (`email`, `pwdhash`, `status`, `verify_hash`) VALUES (:email, :pwdhash, :status, :vcode);'); |
92 | if (!$result->execute(array(':email' => $_POST['email'], ':pwdhash' => $newHash, ':status' => 'unchecked', ':vcode' => $vcode))) { | |
60e46184 | 93 | $utils->log('user_insert_failure', 'email: '.$_POST['email'].' - '.$result->errorInfo()[2]); |
3f24953f RK |
94 | $errors[] = _('Could not add user.').' ' |
95 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
4c6d8064 | 96 | } |
d42db7c5 RK |
97 | $user = [ |
98 | 'id' => $db->lastInsertId(), | |
99 | 'email' => $_POST['email'], | |
100 | 'pwdhash' => $newHash, | |
101 | 'status' => 'unchecked', | |
102 | 'verify_hash' => $vcode, | |
103 | 'hcheck_question' => null, | |
104 | 'hcheck_solution' => null, | |
105 | ]; | |
4c6d8064 | 106 | $utils->log('new_user', 'user: '.$user['id'].', email: '.$user['email']); |
e876642c | 107 | } |
d42db7c5 RK |
108 | $utils->log('user_log_check', 'user: '.$user['id'].', email: '.$user['email'].', status: '.$user['status']); |
109 | if ($user['status'] == 'unchecked' && !is_null($user['hcheck_question']) && array_key_exists('hcheck_solution', $_POST)) { | |
110 | if ($_POST['hcheck_solution'] == $user['hcheck_solution']) { | |
111 | $result = $db->prepare('UPDATE `auth_users` SET `status` = :status, `hcheck_question` = :hcquestion, `hcheck_solution` = :hcsolution WHERE `id` = :userid;'); | |
112 | if (!$result->execute(array(':status' => 'unverified', ':hcquestion' => null, ':hcsolution' => null, ':userid' => $user['id']))) { | |
113 | $errors[] = _('Could not update user status.').' ' | |
114 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
115 | } | |
116 | $user['status'] = 'unverified'; | |
117 | $utils->log('user_checked', 'user: '.$user['id'].', email: '.$user['email']); | |
118 | } | |
119 | else { | |
120 | $errors[] = _('Solution was not correct. Please start over.'); | |
121 | $utils->log('user_check_failed', 'user: '.$user['id'].', email: '.$user['email']); | |
122 | } | |
123 | } | |
124 | if ($user['status'] == 'unchecked') { | |
125 | // Display a humanity check. | |
126 | $pagetype = 'human_check'; | |
127 | // simple numbers, we stay within the 0 to 100 range | |
128 | $num1 = mt_rand(0, 10); | |
129 | $num2 = mt_rand($num1, 100); | |
130 | $operation = mt_rand(0, 1); // 0 is addition, 1 is subtraction | |
131 | if ($operation == 0) { | |
132 | $user['hcheck_question'] = sprintf(_('%s plus %s equals'), ($num2 - $num1), $num1); | |
133 | $user['hcheck_solution'] = $num2; | |
134 | } | |
135 | else { | |
136 | $user['hcheck_question'] = sprintf(_('%s minus %s equals'), $num2, $num1); | |
137 | $user['hcheck_solution'] = $num2 - $num1; | |
138 | } | |
139 | $result = $db->prepare('UPDATE `auth_users` SET `hcheck_question` = :hcquestion, `hcheck_solution` = :hcsolution WHERE `id` = :userid;'); | |
140 | if (!$result->execute(array(':hcquestion' => $user['hcheck_question'], ':hcsolution' => $user['hcheck_solution'], ':userid' => $user['id']))) { | |
141 | $errors[] = _('Could not generate check for being a human.').' ' | |
142 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
143 | } | |
144 | } | |
145 | elseif ($user['status'] == 'unverified') { | |
4c6d8064 RK |
146 | // Send email for verification and show message to point to it. |
147 | $mail = new email(); | |
148 | $mail->setCharset('utf-8'); | |
149 | $mail->addHeader('X-KAIRO-AUTH', 'email_verification'); | |
150 | $mail->addRecipient($user['email']); | |
3f24953f RK |
151 | $mail->setSender($utils->settings['info_from_email'], sprintf(_('%s Authentication Service'), $utils->settings['operator_name'])); |
152 | $mail->setSubject(sprintf(_('Email Verification for %s Authentication'), $utils->settings['operator_name'])); | |
4c6d8064 RK |
153 | $mail->addMailText(_('Welcome!')."\n\n"); |
154 | $mail->addMailText(sprintf(_('This email address, %s, has been used for registration on "%s".'), | |
3f24953f | 155 | $user['email'], sprintf(_('%s Authentication Service'), $utils->settings['operator_name']))."\n\n"); |
4c6d8064 | 156 | $mail->addMailText(_('Please confirm that registration by clicking the following link (or calling it up in your browser):')."\n"); |
409b55f4 | 157 | $mail->addMailText($utils->getDomainBaseURL().strstr($_SERVER['REQUEST_URI'], '?', true) |
4c6d8064 RK |
158 | .'?email='.rawurlencode($user['email']).'&verification_code='.rawurlencode($user['verify_hash'])."\n\n"); |
159 | $mail->addMailText(_('With this confirmation, you accept that we handle your data for the purpose of logging you into other websites when you request that.')."\n"); | |
160 | $mail->addMailText(_('Those websites will get to know your email address but not your password, which we store securely.')."\n"); | |
161 | $mail->addMailText(_('If you do not call this confirmation link within 72 hours, your data will be deleted from our database.')."\n\n"); | |
3f24953f | 162 | $mail->addMailText(sprintf(_('The %s team'), $utils->settings['operator_name'])); |
4c6d8064 RK |
163 | //$mail->setDebugAddress("robert@localhost"); |
164 | $mailsent = $mail->send(); | |
165 | if ($mailsent) { | |
166 | $pagetype = 'verification_sent'; | |
167 | } | |
168 | else { | |
169 | $utils->log('verify_mail_failure', 'user: '.$user['id'].', email: '.$user['email']); | |
3f24953f RK |
170 | $errors[] = _('The confirmation email could not be sent to you.').' ' |
171 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
4c6d8064 | 172 | } |
b19743bc | 173 | } |
4c6d8064 RK |
174 | else { |
175 | // Password reset requested with "Password forgotten?" function. | |
176 | $vcode = $utils->createVerificationCode(); | |
177 | $result = $db->prepare('UPDATE `auth_users` SET `verify_hash` = :vcode WHERE `id` = :userid;'); | |
178 | if (!$result->execute(array(':vcode' => $vcode, ':userid' => $user['id']))) { | |
179 | $utils->log('vhash_set_failure', 'user: '.$user['id']); | |
3f24953f RK |
180 | $errors[] = _('Could not initiate reset request.').' ' |
181 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
4c6d8064 RK |
182 | } |
183 | else { | |
184 | $utils->log('pwd_reset_request', 'user: '.$user['id'].', email: '.$user['email']); | |
185 | $resetcode = $vcode.dechex($user['id'] + $session['id']).'_'.$utils->createTimeCode($session, null, 60); | |
186 | // Send email with instructions for resetting the password. | |
187 | $mail = new email(); | |
188 | $mail->setCharset('utf-8'); | |
189 | $mail->addHeader('X-KAIRO-AUTH', 'password_reset'); | |
190 | $mail->addRecipient($user['email']); | |
3f24953f RK |
191 | $mail->setSender($utils->settings['info_from_email'], sprintf(_('%s Authentication Service'), $utils->settings['operator_name'])); |
192 | $mail->setSubject(sprintf(_('How to reset your password for %s Authentication'), $utils->settings['operator_name'])); | |
4c6d8064 RK |
193 | $mail->addMailText(_('Hi,')."\n\n"); |
194 | $mail->addMailText(sprintf(_('A request for setting a new password for this email address, %s, has been submitted on "%s".'), | |
3f24953f | 195 | $user['email'], sprintf(_('%s Authentication Service'), $utils->settings['operator_name']))."\n\n"); |
4c6d8064 | 196 | $mail->addMailText(_('You can set a new password by clicking the following link (or calling it up in your browser):')."\n"); |
409b55f4 | 197 | $mail->addMailText($utils->getDomainBaseURL().strstr($_SERVER['REQUEST_URI'], '?', true) |
4c6d8064 RK |
198 | .'?email='.rawurlencode($user['email']).'&reset_code='.rawurlencode($resetcode)."\n\n"); |
199 | $mail->addMailText(_('If you do not call this confirmation link within 1 hour, this link expires and the existing password is being kept in place.')."\n\n"); | |
3f24953f | 200 | $mail->addMailText(sprintf(_('The %s team'), $utils->settings['operator_name'])); |
4c6d8064 RK |
201 | //$mail->setDebugAddress("robert@localhost"); |
202 | $mailsent = $mail->send(); | |
203 | if ($mailsent) { | |
204 | $pagetype = 'resetmail_sent'; | |
205 | } | |
206 | else { | |
207 | $utils->log('pwd_reset_mail_failure', 'user: '.$user['id'].', email: '.$user['email']); | |
3f24953f RK |
208 | $errors[] = _('The email with password reset instructions could not be sent to you.').' ' |
209 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
89975cb9 RK |
210 | } |
211 | } | |
212 | } | |
213 | } | |
89975cb9 | 214 | } |
60e46184 RK |
215 | if (!count($errors) && ($addgroup > 0)) { |
216 | // We should add the login email to the group of that existing user. | |
217 | $result = $db->prepare('SELECT `group_id` FROM `auth_users` WHERE `id` = :userid;'); | |
218 | $result->execute(array(':userid' => $addgroup)); | |
219 | $grpuser = $result->fetch(PDO::FETCH_ASSOC); | |
220 | if (!intval($grpuser['group_id'])) { | |
221 | // If that user doesn't have a group, put him into a group with his own user ID. | |
222 | $result = $db->prepare('UPDATE `auth_users` SET `group_id` = :groupid WHERE `id` = :userid;'); | |
223 | if (!$result->execute(array(':groupid' => $addgroup, ':userid' => $addgroup))) { | |
224 | $utils->log('group_save_failure', 'user: '.$addgroup); | |
225 | } | |
226 | else { | |
227 | $utils->log('new grouping', 'user: '.$addgroup.', group: '.$addgroup); | |
228 | } | |
229 | } | |
230 | // Save grouping for the new or logged-in user. | |
231 | $result = $db->prepare('UPDATE `auth_users` SET `group_id` = :groupid WHERE `id` = :userid;'); | |
232 | if (!$result->execute(array(':groupid' => $addgroup, ':userid' => $user['id']))) { | |
233 | $utils->log('group_save_failure', 'user: '.$user['id']); | |
234 | } | |
235 | else { | |
236 | $utils->log('new grouping', 'user: '.$user['id'].', group: '.$addgroup); | |
237 | $user['group_id'] = $addgroup; | |
238 | } | |
239 | } | |
4c6d8064 RK |
240 | } |
241 | else { | |
e66b9a25 | 242 | $errors[] = _('The form you used was not valid. Possibly it has expired and you need to initiate the action again, or you have disabled cookies for this site.'); |
4c6d8064 RK |
243 | } |
244 | } | |
245 | elseif (array_key_exists('reset', $_GET)) { | |
246 | if ($session['logged_in']) { | |
fb7b39f0 | 247 | $result = $db->prepare('SELECT `id`,`email`,`group_id` FROM `auth_users` WHERE `id` = :userid;'); |
4c6d8064 RK |
248 | $result->execute(array(':userid' => $session['user'])); |
249 | $user = $result->fetch(PDO::FETCH_ASSOC); | |
250 | if (!$user['id']) { | |
251 | $utils->log('reset_user_read_failure', 'user: '.$session['user']); | |
252 | } | |
253 | $pagetype = 'resetpwd'; | |
254 | } | |
255 | else { | |
256 | // Display form for entering email. | |
257 | $pagetype = 'resetstart'; | |
258 | } | |
259 | } | |
260 | elseif (array_key_exists('verification_code', $_GET)) { | |
fb7b39f0 | 261 | $result = $db->prepare('SELECT `id`,`email`,`group_id` FROM `auth_users` WHERE `email` = :email AND `status` = \'unverified\' AND `verify_hash` = :vcode;'); |
4c6d8064 RK |
262 | $result->execute(array(':email' => @$_GET['email'], ':vcode' => $_GET['verification_code'])); |
263 | $user = $result->fetch(PDO::FETCH_ASSOC); | |
264 | if ($user['id']) { | |
265 | $result = $db->prepare('UPDATE `auth_users` SET `verify_hash` = \'\', `status` = \'ok\' WHERE `id` = :userid;'); | |
266 | if (!$result->execute(array(':userid' => $user['id']))) { | |
267 | $utils->log('verification_save_failure', 'user: '.$user['id']); | |
3f24953f RK |
268 | $errors[] = _('Could not save confirmation.').' ' |
269 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
4c6d8064 RK |
270 | } |
271 | $pagetype = 'verification_done'; | |
272 | } | |
273 | else { | |
274 | $errors[] = _('The confirmation link you called is not valid. Possibly it has expired and you need to try registering again.'); | |
275 | } | |
276 | } | |
277 | elseif (array_key_exists('reset_code', $_GET)) { | |
278 | $reset_fail = true; | |
fb7b39f0 | 279 | $result = $db->prepare('SELECT `id`,`email`,`verify_hash`,`group_id` FROM `auth_users` WHERE `email` = :email'); |
4c6d8064 RK |
280 | $result->execute(array(':email' => @$_GET['email'])); |
281 | $user = $result->fetch(PDO::FETCH_ASSOC); | |
282 | if ($user['id']) { | |
283 | // Deconstruct reset code and verify it. | |
284 | if (preg_match('/^([0-9a-f]{'.strlen($user['verify_hash']).'})([0-9a-f]+)_(\d+\.\d+)$/', $_GET['reset_code'], $regs)) { | |
285 | $tcode_sessid = hexdec($regs[2]) - $user['id']; | |
286 | $result = $db->prepare('SELECT `id`,`sesskey` FROM `auth_sessions` WHERE `id` = :sessid;'); | |
287 | $result->execute(array(':sessid' => $tcode_sessid)); | |
288 | $row = $result->fetch(PDO::FETCH_ASSOC); | |
289 | if ($row) { | |
290 | $tcode_session = $row; | |
291 | if (($regs[1] == $user['verify_hash']) && | |
292 | $utils->verifyTimeCode($regs[3], $session, 60)) { | |
293 | // Set a new verify_hash for the actual password reset. | |
294 | $user['verify_hash'] = $utils->createVerificationCode(); | |
295 | $result = $db->prepare('UPDATE `auth_users` SET `verify_hash` = :vcode WHERE `id` = :userid;'); | |
296 | if (!$result->execute(array(':vcode' => $user['verify_hash'], ':userid' => $user['id']))) { | |
297 | $utils->log('vhash_reset_failure', 'user: '.$user['id']); | |
e876642c | 298 | } |
4c6d8064 RK |
299 | $result = $db->prepare('UPDATE `auth_sessions` SET `user` = :userid WHERE `id` = :sessid;'); |
300 | if (!$result->execute(array(':userid' => $user['id'], ':sessid' => $session['id']))) { | |
301 | $utils->log('reset_session_set_user_failure', 'session: '.$session['id']); | |
e876642c | 302 | } |
4c6d8064 RK |
303 | $pagetype = 'resetpwd'; |
304 | $reset_fail = false; | |
e876642c RK |
305 | } |
306 | } | |
b19743bc | 307 | } |
d26d08a1 | 308 | } |
4c6d8064 RK |
309 | if ($reset_fail) { |
310 | $errors[] = _('The password reset link you called is not valid. Possibly it has expired and you need to call the "Password forgotten?" function again.'); | |
311 | } | |
d26d08a1 | 312 | } |
ea0452ad | 313 | elseif (array_key_exists('clients', $_GET)) { |
fb7b39f0 | 314 | $result = $db->prepare('SELECT `id`,`email`,`group_id` FROM `auth_users` WHERE `id` = :userid;'); |
ea0452ad RK |
315 | $result->execute(array(':userid' => $session['user'])); |
316 | $user = $result->fetch(PDO::FETCH_ASSOC); | |
317 | if ($session['logged_in'] && $user['id']) { | |
318 | if (array_key_exists('client_id', $_POST) && (strlen($_POST['client_id']) >= 5)) { | |
319 | $clientid = $_POST['client_id']; | |
320 | $clientsecret = $utils->createClientSecret(); | |
321 | $rediruri = strval(@$_POST['redirect_uri']); | |
322 | $scope = strval(@$_POST['scope']); | |
323 | $result = $db->prepare('INSERT INTO `oauth_clients` (`client_id`, `client_secret`, `redirect_uri`, `scope`, `user_id`) VALUES (:clientid, :secret, :rediruri, :scope, :userid);'); | |
324 | if (!$result->execute(array(':clientid' => $clientid, | |
325 | ':secret' => $clientsecret, | |
326 | ':rediruri' => $rediruri, | |
327 | ':scope' => $scope, | |
328 | ':userid' => $user['id']))) { | |
329 | $utils->log('client_save_failure', 'client: '.$clientid); | |
3f24953f RK |
330 | $errors[] = _('Unexpectedly failed to save new client information.').' ' |
331 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
ea0452ad RK |
332 | } |
333 | } | |
334 | if (!count($errors)) { | |
335 | // List clients | |
336 | $result = $db->prepare('SELECT `client_id`,`client_secret`,`redirect_uri`,`scope` FROM `oauth_clients` WHERE `user_id` = :userid;'); | |
337 | $result->execute(array(':userid' => $user['id'])); | |
338 | $clients = $result->fetchAll(PDO::FETCH_ASSOC); | |
339 | if (!$clients) { $clients = array(); } | |
340 | $pagetype = 'clientlist'; | |
341 | } | |
342 | } | |
343 | else { | |
344 | $errors[] = _('This function is only available if you are logged in.'); | |
345 | } | |
346 | } | |
4c6d8064 | 347 | elseif (intval($session['user'])) { |
60e46184 | 348 | $result = $db->prepare('SELECT `id`,`email`,`verify_hash`,`group_id` FROM `auth_users` WHERE `id` = :userid;'); |
4c6d8064 RK |
349 | $result->execute(array(':userid' => $session['user'])); |
350 | $user = $result->fetch(PDO::FETCH_ASSOC); | |
351 | if (!$user['id']) { | |
352 | $utils->log('user_read_failure', 'user: '.$session['user']); | |
d26d08a1 | 353 | } |
4c6d8064 RK |
354 | // Password reset requested. |
355 | if (array_key_exists('pwd', $_POST) && array_key_exists('reset', $_POST) && array_key_exists('tcode', $_POST)) { | |
356 | // If not logged in, a password reset needs to have the proper vcode set. | |
357 | if (!$session['logged_in'] && (!strlen(@$_POST['vcode']) || ($_POST['vcode'] != $user['verify_hash']))) { | |
358 | $errors[] = _('Password reset failed. The reset form you used was not valid. Possibly it has expired and you need to initiate the password reset again.'); | |
359 | } | |
360 | // If not logged in, a password reset also needs to have the proper email set. | |
361 | if (!$session['logged_in'] && !count($errors) && (@$_POST['email_hidden'] != $user['email'])) { | |
362 | $errors[] = _('Password reset failed. The reset form you used was not valid. Possibly it has expired and you need to initiate the password reset again.'); | |
363 | } | |
364 | // Check validity of time code. | |
365 | if (!count($errors) && !$utils->verifyTimeCode($_POST['tcode'], $session)) { | |
366 | $errors[] = _('Password reset failed. The reset form you used was not valid. Possibly it has expired and you need to initiate the password reset again.'); | |
367 | } | |
368 | $errors += $utils->checkPasswordConstraints(strval($_POST['pwd']), $user['email']); | |
369 | if (!count($errors)) { | |
370 | $newHash = $utils->pwdHash($_POST['pwd']); | |
371 | $result = $db->prepare('UPDATE `auth_users` SET `pwdhash` = :pwdhash, `verify_hash` = \'\' WHERE `id` = :userid;'); | |
372 | if (!$result->execute(array(':pwdhash' => $newHash, ':userid' => $session['user']))) { | |
373 | $utils->log('pwd_reset_failure', 'user: '.$session['user']); | |
3f24953f RK |
374 | $errors[] = _('Password reset failed.').' ' |
375 | .sprintf(_('Please <a href="%s">contact %s</a> and tell the team about this.'), $utils->settings['operator_contact_url'], $utils->settings['operator_name']); | |
4c6d8064 RK |
376 | } |
377 | else { | |
378 | $pagetype = 'reset_done'; | |
379 | } | |
380 | } | |
b19743bc | 381 | } |
60e46184 RK |
382 | else { |
383 | $utils->doRedirectIfSet($session); | |
384 | } | |
d26d08a1 RK |
385 | } |
386 | } | |
387 | ||
388 | if (!count($errors)) { | |
d42db7c5 RK |
389 | if ($pagetype == 'human_check') { |
390 | $para = $body->appendElement('p', _('This is a new registration, please verify that you are a human by solving the calculation below.')); | |
391 | $para->setAttribute('class', 'humancheckinfo'); | |
392 | $form = $body->appendForm('./', 'POST', 'humancheckform'); | |
393 | $form->setAttribute('id', 'humancheckform'); | |
394 | $ulist = $form->appendElement('ul'); | |
395 | $ulist->setAttribute('class', 'flat humancheck'); | |
396 | $litem = $ulist->appendElement('li'); | |
397 | $litem->setAttribute('class', 'donotshow'); | |
398 | $inptxt = $litem->appendInputEmail('email', 30, 20, 'login_email', $user['email']); | |
399 | $inptxt->setAttribute('autocomplete', 'email'); | |
400 | $inptxt->setAttribute('placeholder', _('Email')); | |
401 | $litem = $ulist->appendElement('li'); | |
402 | $litem->appendText($user['hcheck_question'].' '); | |
403 | $inptxt = $litem->appendInputText('hcheck_solution', 20, 10, 'hcheck_solution'); | |
404 | $litem = $ulist->appendElement('li'); | |
405 | $litem->appendInputHidden('tcode', $utils->createTimeCode($session)); | |
406 | $submit = $litem->appendInputSubmit(_('Continue Registration')); | |
407 | $para = $form->appendElement('p'); | |
408 | $para->setAttribute('class', 'toplink small'); | |
409 | $link = $para->appendLink('./', _('Cancel')); | |
410 | } | |
411 | elseif ($pagetype == 'verification_sent') { | |
b19743bc RK |
412 | $para = $body->appendElement('p', sprintf(_('An email for confirmation has been sent to %s. Please follow the link provided there to complete the process.'), $user['email'])); |
413 | $para->setAttribute('class', 'verifyinfo pending'); | |
409b55f4 RK |
414 | $para = $body->appendElement('p', _('Reload this page after you confirm to continue.')); |
415 | $para->setAttribute('class', 'verifyinfo pending'); | |
e66b9a25 RK |
416 | $para = $body->appendElement('p'); |
417 | $para->setAttribute('class', 'verifyinfo pending'); | |
418 | $link = $para->appendLink('./', _('Reload')); | |
b19743bc | 419 | } |
89975cb9 RK |
420 | elseif ($pagetype == 'resetmail_sent') { |
421 | $para = $body->appendElement('p', | |
422 | _('An email has been sent to the requested account with further information. If you do not receive an email then please confirm you have entered the same email address used during account registration.')); | |
423 | $para->setAttribute('class', 'resetinfo pending'); | |
e66b9a25 RK |
424 | $para = $body->appendElement('p'); |
425 | $para->setAttribute('class', 'resetinfo pending small'); | |
426 | $link = $para->appendLink('./', _('Back to top')); | |
89975cb9 | 427 | } |
b19743bc RK |
428 | elseif ($pagetype == 'resetstart') { |
429 | $para = $body->appendElement('p', _('If you forgot your password or didn\'t receive the registration confirmation, please enter your email here.')); | |
430 | $para->setAttribute('class', ''); | |
77f0f9ff | 431 | $form = $body->appendForm('./?reset', 'POST', 'resetform'); |
b19743bc RK |
432 | $form->setAttribute('id', 'loginform'); |
433 | $form->setAttribute('class', 'loginarea hidden'); | |
434 | $ulist = $form->appendElement('ul'); | |
435 | $ulist->setAttribute('class', 'flat login'); | |
436 | $litem = $ulist->appendElement('li'); | |
437 | $inptxt = $litem->appendInputEmail('email', 30, 20, 'login_email'); | |
438 | $inptxt->setAttribute('autocomplete', 'email'); | |
439 | $inptxt->setAttribute('required', ''); | |
440 | $inptxt->setAttribute('placeholder', _('Email')); | |
441 | $litem = $ulist->appendElement('li'); | |
ac442755 | 442 | $litem->appendInputHidden('tcode', $utils->createTimeCode($session)); |
b19743bc | 443 | $submit = $litem->appendInputSubmit(_('Send instructions to email')); |
e66b9a25 RK |
444 | $para = $form->appendElement('p'); |
445 | $para->setAttribute('class', 'toplink small'); | |
446 | $link = $para->appendLink('./', _('Cancel')); | |
b19743bc RK |
447 | } |
448 | elseif ($pagetype == 'resetpwd') { | |
89975cb9 | 449 | $para = $body->appendElement('p', sprintf(_('You can set a new password for %s here.'), $user['email'])); |
e66b9a25 | 450 | $para->setAttribute('class', 'newpwdinfo'); |
77f0f9ff | 451 | $form = $body->appendForm('./', 'POST', 'newpwdform'); |
b19743bc RK |
452 | $form->setAttribute('id', 'loginform'); |
453 | $form->setAttribute('class', 'loginarea hidden'); | |
454 | $ulist = $form->appendElement('ul'); | |
455 | $ulist->setAttribute('class', 'flat login'); | |
456 | $litem = $ulist->appendElement('li'); | |
e876642c RK |
457 | $litem->setAttribute('class', 'donotshow'); |
458 | $inptxt = $litem->appendInputEmail('email_hidden', 30, 20, 'login_email', $user['email']); | |
459 | $inptxt->setAttribute('autocomplete', 'email'); | |
460 | $inptxt->setAttribute('placeholder', _('Email')); | |
461 | $litem = $ulist->appendElement('li'); | |
b19743bc RK |
462 | $inptxt = $litem->appendInputPassword('pwd', 20, 20, 'login_pwd', ''); |
463 | $inptxt->setAttribute('required', ''); | |
464 | $inptxt->setAttribute('placeholder', _('Password')); | |
465 | $inptxt->setAttribute('class', 'login'); | |
466 | $litem = $ulist->appendElement('li'); | |
e876642c | 467 | $litem->appendInputHidden('reset', ''); |
ac442755 | 468 | $litem->appendInputHidden('tcode', $utils->createTimeCode($session)); |
89975cb9 RK |
469 | if (!$session['logged_in'] && strlen(@$user['verify_hash'])) { |
470 | $litem->appendInputHidden('vcode', $user['verify_hash']); | |
471 | } | |
b19743bc | 472 | $submit = $litem->appendInputSubmit(_('Save password')); |
e66b9a25 RK |
473 | $para = $form->appendElement('p'); |
474 | $para->setAttribute('class', 'toplink small'); | |
475 | $link = $para->appendLink('./', _('Cancel')); | |
b19743bc | 476 | } |
ea0452ad RK |
477 | elseif ($pagetype == 'clientlist') { |
478 | $scopes = array('clientreg', 'email'); | |
479 | $form = $body->appendForm('?clients', 'POST', 'newclientform'); | |
480 | $form->setAttribute('id', 'clientform'); | |
481 | $tbl = $form->appendElement('table'); | |
482 | $tbl->setAttribute('class', 'clientlist border'); | |
483 | $thead = $tbl->appendElement('thead'); | |
484 | $trow = $thead->appendElement('tr'); | |
485 | $trow->appendElement('th', _('Client ID')); | |
486 | $trow->appendElement('th', _('Client Secrect')); | |
487 | $trow->appendElement('th', _('Redirect URI')); | |
488 | $trow->appendElement('th', _('Scope')); | |
489 | $trow->appendElement('th'); | |
490 | $tbody = $tbl->appendElement('tbody'); | |
491 | foreach ($clients as $client) { | |
492 | $trow = $tbody->appendElement('tr'); | |
493 | $trow->appendElement('td', $client['client_id']); | |
494 | $trow->appendElement('td', $client['client_secret']); | |
495 | $trow->appendElement('td', $client['redirect_uri']); | |
496 | $trow->appendElement('td', $client['scope']); | |
497 | $trow->appendElement('td'); // Future: Delete link? | |
498 | } | |
499 | // Form fields for adding a new one. | |
500 | $tfoot = $tbl->appendElement('tfoot'); | |
501 | $trow = $tfoot->appendElement('tr'); | |
502 | $cell = $trow->appendElement('td'); | |
503 | $inptxt = $cell->appendInputText('client_id', 80, 25, 'client_id'); | |
504 | $cell = $trow->appendElement('td'); // Empty, as secret will be generated. | |
505 | $cell = $trow->appendElement('td'); | |
506 | $inptxt = $cell->appendInputText('redirect_uri', 500, 50, 'redirect_uri'); | |
507 | $cell = $trow->appendElement('td'); | |
508 | $select = $cell->appendElementSelect('scope'); | |
509 | foreach ($scopes as $scope) { | |
510 | $select->appendElementOption($scope, $scope); | |
511 | } | |
512 | //$inptxt = $cell->appendInputText('scope', 100, 20, 'scope'); | |
513 | $cell = $trow->appendElement('td'); | |
514 | $submit = $cell->appendInputSubmit(_('Create')); | |
e66b9a25 RK |
515 | $para = $form->appendElement('p'); |
516 | $para->setAttribute('class', 'toplink'); | |
517 | $link = $para->appendLink('./', _('Back to top')); | |
ea0452ad | 518 | } |
60e46184 | 519 | elseif ($session['logged_in'] && (!array_key_exists('addemail', $_GET))) { |
e876642c RK |
520 | if ($pagetype == 'reset_done') { |
521 | $para = $body->appendElement('p', _('Your password has successfully been reset.')); | |
522 | $para->setAttribute('class', 'resetinfo done'); | |
523 | } | |
d26d08a1 RK |
524 | $div = $body->appendElement('div', $user['email']); |
525 | $div->setAttribute('class', 'loginheader'); | |
60e46184 RK |
526 | $groupmails = $utils->getGroupedEmails($user['group_id'], $user['email']); |
527 | if (count($groupmails)) { | |
528 | $para = $div->appendElement('p', _('Grouped with: ').implode(', ', $groupmails)); | |
529 | $para->setAttribute('class', 'small groupmails'); | |
530 | } | |
d26d08a1 RK |
531 | $div = $body->appendElement('div'); |
532 | $div->setAttribute('class', 'loginlinks'); | |
b19743bc RK |
533 | $ulist = $div->appendElement('ul'); |
534 | $ulist->setAttribute('class', 'flat'); | |
535 | $litem = $ulist->appendElement('li'); | |
77f0f9ff | 536 | $link = $litem->appendLink('./?logout', _('Log out')); |
60e46184 RK |
537 | $litem = $ulist->appendElement('li'); |
538 | $link = $litem->appendLink('./?addemail', _('Add another email address')); | |
3875e0fb | 539 | if (($utils->client_reg_email_whitelist === false) || (in_array($user['email'], $utils->client_reg_email_whitelist))) { |
ea0452ad RK |
540 | $litem = $ulist->appendElement('li'); |
541 | $link = $litem->appendLink('./?clients', _('Manage OAuth2 clients')); | |
542 | } | |
b19743bc | 543 | $litem = $ulist->appendElement('li'); |
77f0f9ff | 544 | $litem->appendLink('./?reset', _('Set new password')); |
d26d08a1 RK |
545 | } |
546 | else { // not logged in | |
60e46184 | 547 | $addfields = array(); |
b19743bc RK |
548 | if ($pagetype == 'verification_done') { |
549 | $para = $body->appendElement('p', _('Hooray! Your email was successfully confirmed! You can log in now.')); | |
550 | $para->setAttribute('class', 'verifyinfo done'); | |
551 | } | |
e876642c RK |
552 | elseif ($pagetype == 'reset_done') { |
553 | $para = $body->appendElement('p', _('Your password has successfully been reset. You can log in now with the new password.')); | |
554 | $para->setAttribute('class', 'resetinfo done'); | |
555 | } | |
60e46184 RK |
556 | elseif (array_key_exists('addemail', $_GET)) { |
557 | $para = $body->appendElement('p', sprintf(_('Add another email grouped with %s by either logging in with it or specifying the email and a new password to use.'), $user['email'])); | |
558 | $para->setAttribute('class', 'addemailinfo'); | |
559 | $addfields['grouptoexisting'] = '1'; | |
560 | } | |
561 | $utils->appendLoginForm($body, $session, $user, $addfields); | |
d26d08a1 RK |
562 | } |
563 | } | |
564 | ||
565 | if (count($errors)) { | |
566 | $body->appendElement('p', ((count($errors) <= 1) | |
567 | ?_('The following error was detected') | |
568 | :_('The following errors were detected')).':'); | |
569 | $list = $body->appendElement('ul'); | |
570 | $list->setAttribute('class', 'flat warn'); | |
571 | foreach ($errors as $msg) { | |
9b32cdeb RK |
572 | $item = $list->appendElement('li'); |
573 | $item->appendHTMLMarkup($msg); | |
d26d08a1 | 574 | } |
b19743bc | 575 | $body->appendButton(_('Back'), 'history.back();'); |
133aecbe RK |
576 | } |
577 | ||
578 | // Send HTML to client. | |
579 | print($document->saveHTML()); | |
580 | ?> |