Dotclear

source: admin/auth.php @ 3627:9bccfc2257ad

Revision 3627:9bccfc2257ad, 13.1 KB checked in by franck <carnet.franck.paul@…>, 5 years ago (diff)

Use PHP 5.5+ new password functions, closes #2182

Warnings:

  • $core->auth->crypt($pwd) doesn't return twice the same result for a single $pwd, so if you need this old behaviour use the $core->auth->cryptLegacy($pwd) instead.
  • $core->auth->checkPassword($pwd) must be used with an uncrypted password string as argument.
  • if you need a unique UID/key, use http::browserUID(DC_MASTER_KEY.$core->auth->userID().$core->auth->cryptLegacy($core->auth->userID())). (may be refined in future)
Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12
13require dirname(__FILE__).'/../inc/admin/prepend.php';
14
15# If we have a session cookie, go to index.php
16if (isset($_SESSION['sess_user_id']))
17{
18     $core->adminurl->redirect('admin.home');
19}
20
21# Loading locales for detected language
22# That's a tricky hack but it works ;)
23$dlang = http::getAcceptLanguage();
24$dlang = ($dlang == '' ? 'en' : $dlang);
25if ($dlang != 'en' && preg_match('/^[a-z]{2}(-[a-z]{2})?$/',$dlang))
26{
27     l10n::lang($dlang);
28     l10n::set(dirname(__FILE__).'/../locales/'.$dlang.'/main');
29}
30
31if (defined('DC_ADMIN_URL')) {
32     $page_url = DC_ADMIN_URL.$core->adminurl->get('admin.auth');
33} else {
34     $page_url = http::getHost().$_SERVER['REQUEST_URI'];
35}
36
37$change_pwd = $core->auth->allowPassChange() && isset($_POST['new_pwd']) && isset($_POST['new_pwd_c']) && isset($_POST['login_data']);
38$login_data = !empty($_POST['login_data']) ? html::escapeHTML($_POST['login_data']) : null;
39$recover = $core->auth->allowPassChange() && !empty($_REQUEST['recover']);
40$safe_mode = !empty($_REQUEST['safe_mode']);
41$akey = $core->auth->allowPassChange() && !empty($_GET['akey']) ? $_GET['akey'] : null;
42$user_id = $user_pwd = $user_key = $user_email = null;
43$err = $msg = null;
44
45# Auto upgrade
46if (empty($_GET) && empty($_POST)) {
47     require dirname(__FILE__).'/../inc/dbschema/upgrade.php';
48     try {
49          if (($changes = dcUpgrade::dotclearUpgrade($core)) !== false) {
50               $msg = __('Dotclear has been upgraded.').'<!-- '.$changes.' -->';
51          }
52     } catch (Exception $e) {
53          $err = $e->getMessage();
54     }
55}
56
57# If we have POST login informations, go throug auth process
58if (!empty($_POST['user_id']) && !empty($_POST['user_pwd']))
59{
60     $user_id = !empty($_POST['user_id']) ? $_POST['user_id'] : null;
61     $user_pwd = !empty($_POST['user_pwd']) ? $_POST['user_pwd'] : null;
62}
63# If we have COOKIE login informations, go throug auth process
64elseif (isset($_COOKIE['dc_admin']) && strlen($_COOKIE['dc_admin']) == 104)
65{
66     # If we have a remember cookie, go through auth process with user_key
67     $user_id = substr($_COOKIE['dc_admin'],40);
68     $user_id = @unpack('a32',@pack('H*',$user_id));
69     if (is_array($user_id))
70     {
71          $user_id = trim($user_id[1]);
72          $user_key = substr($_COOKIE['dc_admin'],0,40);
73          $user_pwd = null;
74     }
75     else
76     {
77          $user_id = null;
78     }
79}
80
81# Recover password
82if ($recover && !empty($_POST['user_id']) && !empty($_POST['user_email']))
83{
84     $user_id = !empty($_POST['user_id']) ? $_POST['user_id'] : null;
85     $user_email = !empty($_POST['user_email']) ? $_POST['user_email'] : '';
86     try
87     {
88          $recover_key = $core->auth->setRecoverKey($user_id,$user_email);
89
90          $subject = mail::B64Header('Dotclear '.__('Password reset'));
91          $message =
92          __('Someone has requested to reset the password for the following site and username.')."\n\n".
93          $page_url."\n".__('Username:').' '.$user_id."\n\n".
94          __('To reset your password visit the following address, otherwise just ignore this email and nothing will happen.')."\n".
95          $page_url.'?akey='.$recover_key;
96
97          $headers[] = 'From: '.(defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local');
98          $headers[] = 'Content-Type: text/plain; charset=UTF-8;';
99
100          mail::sendMail($user_email,$subject,$message,$headers);
101          $msg = sprintf(__('The e-mail was sent successfully to %s.'),$user_email);
102     }
103     catch (Exception $e)
104     {
105          $err = $e->getMessage();
106     }
107}
108# Send new password
109elseif ($akey)
110{
111     try
112     {
113          $recover_res = $core->auth->recoverUserPassword($akey);
114
115          $subject = mb_encode_mimeheader('Dotclear '.__('Your new password'),'UTF-8','B');
116          $message =
117          __('Username:').' '.$recover_res['user_id']."\n".
118          __('Password:').' '.$recover_res['new_pass']."\n\n".
119          preg_replace('/\?(.*)$/','',$page_url);
120
121          $headers[] = 'From: '.(defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local');
122          $headers[] = 'Content-Type: text/plain; charset=UTF-8;';
123
124          mail::sendMail($recover_res['user_email'],$subject,$message,$headers);
125          $msg = __('Your new password is in your mailbox.');
126     }
127     catch (Exception $e)
128     {
129          $err = $e->getMessage();
130     }
131}
132# Change password and retry to log
133elseif ($change_pwd)
134{
135     try
136     {
137          $tmp_data = explode('/',$_POST['login_data']);
138          if (count($tmp_data) != 3) {
139               throw new Exception();
140          }
141          $data = array(
142               'user_id'=>base64_decode($tmp_data[0]),
143               'cookie_admin'=>$tmp_data[1],
144               'user_remember'=>$tmp_data[2]=='1'
145          );
146          if ($data['user_id'] === false) {
147               throw new Exception();
148          }
149
150          # Check login informations
151          $check_user = false;
152          if (isset($data['cookie_admin']) && strlen($data['cookie_admin']) == 104)
153          {
154               $user_id = substr($data['cookie_admin'],40);
155               $user_id = @unpack('a32',@pack('H*',$user_id));
156               if (is_array($user_id)) {
157                    $user_id = trim($data['user_id']);
158                    $user_key = substr($data['cookie_admin'],0,40);
159                    $check_user = $core->auth->checkUser($user_id,null,$user_key) === true;
160               } else {
161                    $user_id = trim($user_id);
162               }
163          }
164
165          if (!$core->auth->allowPassChange() || !$check_user) {
166               $change_pwd = false;
167               throw new Exception();
168          }
169
170          if ($_POST['new_pwd'] != $_POST['new_pwd_c']) {
171               throw new Exception(__("Passwords don't match"));
172          }
173
174          if ($core->auth->checkUser($user_id,$_POST['new_pwd']) === true) {
175               throw new Exception(__("You didn't change your password."));
176          }
177
178          $cur = $core->con->openCursor($core->prefix.'user');
179          $cur->user_change_pwd = 0;
180          $cur->user_pwd = $_POST['new_pwd'];
181          $core->updUser($core->auth->userID(),$cur);
182
183          $core->session->start();
184          $_SESSION['sess_user_id'] = $user_id;
185          $_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY);
186
187          if ($data['user_remember'])
188          {
189               setcookie('dc_admin',$data['cookie_admin'],strtotime('+15 days'),'','',DC_ADMIN_SSL);
190          }
191
192          $core->adminurl->redirect('admin.home');
193     }
194     catch (Exception $e)
195     {
196          $err = $e->getMessage();
197     }
198}
199# Try to log
200elseif ($user_id !== null && ($user_pwd !== null || $user_key !== null))
201{
202     # We check the user
203     $check_user = $core->auth->checkUser($user_id,$user_pwd,$user_key,false) === true;
204     if ($check_user) {
205          $check_perms = $core->auth->findUserBlog() !== false;
206     } else {
207          $check_perms = false;
208     }
209
210     $cookie_admin = http::browserUID(DC_MASTER_KEY.$user_id.
211          $core->auth->cryptLegacy($user_id)).bin2hex(pack('a32',$user_id));
212
213     if ($check_perms && $core->auth->mustChangePassword())
214     {
215          $login_data = join('/',array(
216               base64_encode($user_id),
217               $cookie_admin,
218               empty($_POST['user_remember'])?'0':'1'
219          ));
220
221          if (!$core->auth->allowPassChange()) {
222               $err = __('You have to change your password before you can login.');
223          } else {
224               $err = __('In order to login, you have to change your password now.');
225               $change_pwd = true;
226          }
227     }
228     elseif ($check_perms && !empty($_POST['safe_mode']) && !$core->auth->isSuperAdmin())
229     {
230          $err = __('Safe Mode can only be used for super administrators.');
231     }
232     elseif ($check_perms)
233     {
234          $core->session->start();
235          $_SESSION['sess_user_id'] = $user_id;
236          $_SESSION['sess_browser_uid'] = http::browserUID(DC_MASTER_KEY);
237
238          if (!empty($_POST['blog'])) {
239               $_SESSION['sess_blog_id'] = $_POST['blog'];
240          }
241
242          if (!empty($_POST['safe_mode']) && $core->auth->isSuperAdmin()) {
243               $_SESSION['sess_safe_mode'] = true;
244          }
245
246          if (!empty($_POST['user_remember'])) {
247               setcookie('dc_admin',$cookie_admin,strtotime('+15 days'),'','',DC_ADMIN_SSL);
248          }
249
250          $core->adminurl->redirect('admin.home');
251     }
252     else
253     {
254          if (isset($_COOKIE['dc_admin'])) {
255               unset($_COOKIE['dc_admin']);
256               setcookie('dc_admin',false,-600,'','',DC_ADMIN_SSL);
257          }
258          if ($check_user) {
259               $err = __('Insufficient permissions');
260          } else {
261               $err = __('Wrong username or password');
262          }
263     }
264}
265
266if (isset($_GET['user'])) {
267     $user_id = $_GET['user'];
268}
269
270header('Content-Type: text/html; charset=UTF-8');
271
272// Prevents Clickjacking as far as possible
273header('X-Frame-Options: SAMEORIGIN'); // FF 3.6.9+ Chrome 4.1+ IE 8+ Safari 4+ Opera 10.5+
274
275?>
276<!DOCTYPE html>
277<html lang="<?php echo $dlang; ?>">
278<head>
279  <meta charset="UTF-8" />
280  <meta http-equiv="Content-Script-Type" content="text/javascript" />
281  <meta http-equiv="Content-Style-Type" content="text/css" />
282  <meta http-equiv="Content-Language" content="<?php echo $dlang; ?>" />
283  <meta name="ROBOTS" content="NOARCHIVE,NOINDEX,NOFOLLOW" />
284  <meta name="GOOGLEBOT" content="NOSNIPPET" />
285  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
286  <title><?php echo html::escapeHTML(DC_VENDOR_NAME); ?></title>
287  <link rel="icon" type="image/png" href="images/favicon96-logout.png" />
288  <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
289
290
291<?php
292echo dcPage::jsCommon();
293?>
294
295     <link rel="stylesheet" href="style/default.css" type="text/css" media="screen" />
296
297<?php
298# --BEHAVIOR-- loginPageHTMLHead
299$core->callBehavior('loginPageHTMLHead');
300?>
301
302     <script type="text/javascript">
303          $(window).load(function() {
304               var uid = $('input[name=user_id]');
305               var upw = $('input[name=user_pwd]');
306               uid.focus();
307
308               if (upw.length == 0) { return; }
309
310               uid.keypress(processKey);
311
312               function processKey(evt) {
313                    if (evt.which == 13 && upw.val() == '') {
314                         upw.focus();
315                         return false;
316                    }
317                    return true;
318               };
319               $.cookie('dc_admin_test_cookie',true);
320               if ($.cookie('dc_admin_test_cookie')) {
321                    $('#cookie_help').hide();
322                    $.cookie('dc_admin_test_cookie', '', {'expires': -1});
323               } else {
324                    $('#cookie_help').show();
325               }
326               $('#issue #more').toggleWithLegend($('#issue').children().not('#more'));
327          });
328     </script>
329</head>
330
331<body id="dotclear-admin" class="auth">
332
333<form action="<?php echo $core->adminurl->get('admin.auth'); ?>" method="post" id="login-screen">
334<h1 role="banner"><?php echo html::escapeHTML(DC_VENDOR_NAME); ?></h1>
335
336<?php
337if ($err) {
338     echo '<div class="error" role="alert">'.$err.'</div>';
339}
340if ($msg) {
341     echo '<p class="success" role="alert">'.$msg.'</p>';
342}
343
344if ($akey)
345{
346     echo '<p><a href="'.$core->adminurl->get('admin.auth').'">'.__('Back to login screen').'</a></p>';
347}
348elseif ($recover)
349{
350     echo
351     '<div class="fieldset" role="main"><h2>'.__('Request a new password').'</h2>'.
352     '<p><label for="user_id">'.__('Username:').'</label> '.
353     form::field(array('user_id','user_id'),20,32,html::escapeHTML($user_id)).'</p>'.
354
355     '<p><label for="user_email">'.__('Email:').'</label> '.
356     form::field(array('user_email','user_email'),20,255,html::escapeHTML($user_email)).'</p>'.
357
358     '<p><input type="submit" value="'.__('recover').'" />'.
359     form::hidden(array('recover'),1).'</p>'.
360     '</div>'.
361
362     '<div id="issue">'.
363     '<p><a href="'.$core->adminurl->get('admin.auth').'">'.__('Back to login screen').'</a></p>'.
364     '</div>';
365}
366elseif ($change_pwd)
367{
368     echo
369     '<div class="fieldset"><h2>'.__('Change your password').'</h2>'.
370     '<p><label for="new_pwd">'.__('New password:').'</label> '.
371     form::password(array('new_pwd','new_pwd'),20,255).'</p>'.
372
373     '<p><label for="new_pwd_c">'.__('Confirm password:').'</label> '.
374     form::password(array('new_pwd_c','new_pwd_c'),20,255).'</p>'.
375     '</div>'.
376
377     '<p><input type="submit" value="'.__('change').'" />'.
378     form::hidden('login_data',$login_data).'</p>';
379}
380else
381{
382     if (is_callable(array($core->auth,'authForm')))
383     {
384          echo $core->auth->authForm($user_id);
385     }
386     else
387     {
388          if ($safe_mode) {
389               echo '<div class="fieldset" role="main">';
390               echo '<h2>'.__('Safe mode login').'</h2>';
391               echo
392                    '<p class="form-note">'.
393                    __('This mode allows you to login without activating any of your plugins. This may be useful to solve compatibility problems').'&nbsp;</p>'.
394                    '<p class="form-note">'.__('Disable or delete any plugin suspected to cause trouble, then log out and log back in normally.').
395                    '</p>';
396          }
397          else {
398               echo '<div class="fieldset" role="main">';
399          }
400
401          echo
402          '<p><label for="user_id">'.__('Username:').'</label> '.
403          form::field(array('user_id','user_id'),20,32,html::escapeHTML($user_id)).'</p>'.
404
405          '<p><label for="user_pwd">'.__('Password:').'</label> '.
406          form::password(array('user_pwd','user_pwd'),20,255).'</p>'.
407
408          '<p>'.
409          form::checkbox(array('user_remember','user_remember'),1).
410          '<label for="user_remember" class="classic">'.
411          __('Remember my ID on this device').'</label></p>'.
412
413          '<p><input type="submit" value="'.__('log in').'" class="login" /></p>';
414
415          if (!empty($_REQUEST['blog'])) {
416               echo form::hidden('blog',html::escapeHTML($_REQUEST['blog']));
417          }
418          if($safe_mode) {
419               echo
420               form::hidden('safe_mode',1).
421               '</div>';
422          }
423          else {
424               echo '</div>';
425          }
426          echo
427          '<p id="cookie_help" class="error">'.__('You must accept cookies in order to use the private area.').'</p>';
428
429          echo '<div id="issue">';
430
431          if ($safe_mode) {
432               echo
433               '<p><a href="'.$core->adminurl->get('admin.auth').'" id="normal_mode_link">'.__('Get back to normal authentication').'</a></p>';
434          } else {
435               echo '<p id="more"><strong>'.__('Connection issue?').'</strong></p>';
436               if ($core->auth->allowPassChange()) {
437                    echo '<p><a href="'.$core->adminurl->get('admin.auth',array('recover' => 1)).'">'.__('I forgot my password').'</a></p>';
438               }
439               echo '<p><a href="'.$core->adminurl->get('admin.auth',array('safe_mode' => 1)).'" id="safe_mode_link">'.__('I want to log in in safe mode').'</a></p>';
440          }
441
442          echo '</div>';
443     }
444}
445?>
446</form>
447</body>
448</html>
Note: See TracBrowser for help on using the repository browser.

Sites map