Merge pull request #8 from radiocontrolled/0004872
[atutor.git] / login.php
1 <?php
2 /***********************************************************************/
3 /* ATutor                                                                                                                          */
4 /***********************************************************************/
5 /* Copyright (c) 2002-2010                                             */
6 /* Inclusive Design Institute                                          */
7 /* http://atutor.ca                                                                                                        */
8 /*                                                                                                                                         */
9 /* This program is free software. You can redistribute it and/or           */
10 /* modify it under the terms of the GNU General Public License             */
11 /* as published by the Free Software Foundation.                                           */
12 /***********************************************************************/
13 // $Id$
14
15 $_user_location = 'public';
16 define('AT_INCLUDE_PATH', 'include/');
17 require (AT_INCLUDE_PATH.'vitals.inc.php');
18
19 // For security reasons the token has to be generated anew before each login attempt.
20 // The entropy of SHA-1 input should be comparable to that of its output; in other words, the more randomness you feed it the better.
21
22 /***
23 * Remove comments below to enable a remote login form.
24 */
25 if (isset($_POST['token']))
26 {
27         $_SESSION['token'] = $_POST['token'];
28 }
29 else
30 {
31         if (!isset($_SESSION['token']))
32                 $_SESSION['token'] = sha1(mt_rand() . microtime(TRUE));
33 }
34
35 /***
36 * Add comments 2 lines below to enable a remote login form.
37 */
38 //if (!isset($_SESSION['token']))
39 //      $_SESSION['token'] = sha1(mt_rand() . microtime(TRUE));
40
41 if (isset($_GET['course'])) {
42         $_GET['course'] = intval($_GET['course']);
43 } else {
44         $_GET['course'] = 0;
45 }
46
47 // check if we have a cookie
48 if (!$msg->containsFeedbacks()) {
49         if (isset($_COOKIE['ATLogin'])) {
50                 $cookie_login = $_COOKIE['ATLogin'];
51         }
52         if (isset($_COOKIE['ATPass'])) {
53                 $cookie_pass  = $_COOKIE['ATPass'];
54         }
55 }
56
57 //garbage collect for maximum login attempts table
58 if (rand(1, 100) == 1){
59         $sql = 'DELETE FROM '.TABLE_PREFIX.'member_login_attempt WHERE expiry < '. time();
60         mysql_query($sql, $db);
61 }
62
63 if (isset($cookie_login, $cookie_pass) && !isset($_POST['submit'])) {
64         /* auto login */
65         $this_login             = $cookie_login;
66         $this_password  = $cookie_pass;
67         $auto_login             = 1;
68         $used_cookie    = true;
69 } else if (isset($_POST['submit'])) {
70         /* form post login */
71         $this_password = $_POST['form_password_hidden'];
72         $this_login             = $_POST['form_login'];
73         $auto_login             = isset($_POST['auto']) ? intval($_POST['auto']) : 0;
74         $used_cookie    = false;
75 }
76
77 if (isset($this_login, $this_password)) {
78         if (version_compare(PHP_VERSION, '5.1.0', '>=')) {
79                 session_regenerate_id(TRUE);
80         }
81
82
83         if ($_GET['course']) {
84                 $_POST['form_course_id'] = intval($_GET['course']);
85         } else {
86                 $_POST['form_course_id'] = intval($_POST['form_course_id']);
87         }
88         $this_login    = $addslashes($this_login);
89         $this_password = $addslashes($this_password);
90
91         //Check if this account has exceeded maximum attempts
92 //      $sql = 'SELECT a.login, b.attempt, b.expiry FROM (SELECT login FROM '.TABLE_PREFIX.'members UNION SELECT login FROM '.TABLE_PREFIX.'admins) AS a LEFT JOIN '.TABLE_PREFIX."member_login_attempt b ON a.login=b.login WHERE a.login='$this_login'";
93         $sql = 'SELECT login, attempt, expiry FROM '.TABLE_PREFIX."member_login_attempt WHERE login='$this_login'";
94
95         $result = mysql_query($sql, $db);
96         if ($result && mysql_numrows($result) > 0){
97                 list($attempt_login_name, $attempt_login, $attempt_expiry) = mysql_fetch_array($result);
98         } else {
99                 $attempt_login_name = '';
100                 $attempt_login = 0;
101                 $attempt_expiry = 0;
102         }
103         if($attempt_expiry > 0 && $attempt_expiry < time()){
104                 //clear entry if it has expired
105                 $sql = 'DELETE FROM '.TABLE_PREFIX."member_login_attempt WHERE login='$this_login'";
106                 mysql_query($sql, $db);
107                 $attempt_login = 0;     
108                 $attempt_expiry = 0;
109         } 
110         
111         if ($used_cookie) {
112             #4775: password now store with salt
113             $sql = "SELECT password, last_login FROM " . TABLE_PREFIX . "members WHERE login='$this_login'";
114             $result = mysql_query($sql, $db);
115             $cookieRow = mysql_fetch_assoc($result);
116             $saltedPassword = hash('sha512', $cookieRow['password'] . hash('sha512', $cookieRow['last_login']));
117                 $sql = "SELECT member_id, login, first_name, second_name, last_name, preferences,password AS pass, language, status, last_login FROM ".TABLE_PREFIX."members WHERE login='$this_login' AND '$saltedPassword'='$this_password'";
118         } else {
119                 $sql = "SELECT member_id, login, first_name, second_name, last_name, preferences, language, status, password AS pass, last_login FROM ".TABLE_PREFIX."members WHERE (login='$this_login' OR email='$this_login') AND SHA1(CONCAT(password, '$_SESSION[token]'))='$this_password'";
120         }
121         $result = mysql_query($sql, $db);
122
123         if($_config['max_login'] > 0 && $attempt_login >= $_config['max_login']){
124                 $msg->addError('MAX_LOGIN_ATTEMPT');
125         } else if (($row = mysql_fetch_assoc($result)) && ($row['status'] == AT_STATUS_UNCONFIRMED)) {
126                 $msg->addError('NOT_CONFIRMED');
127         } else if ($row && $row['status'] == AT_STATUS_DISABLED) {
128                 $msg->addError('ACCOUNT_DISABLED');
129         } else if ($row) {
130                 $_SESSION['valid_user'] = true;
131                 $_SESSION['member_id']  = intval($row['member_id']);
132                 $_SESSION['login']              = $row['login'];
133                 if ($row['preferences'] == "")
134                         assign_session_prefs(unserialize(stripslashes($_config["pref_defaults"])), 1);
135                 else
136                         assign_session_prefs(unserialize(stripslashes($row['preferences'])), 1);
137                 $_SESSION['is_guest']   = 0;
138                 $_SESSION['lang']               = $row['language'];
139                 $_SESSION['course_id']  = 0;
140                 $now = date('Y-m-d H:i:s');
141
142                 if ($auto_login == 1) {
143                         $parts = parse_url($_base_href);
144                         // update the cookie.. increment to another 2 days
145                         $cookie_expire = time()+172800;
146                         // #4775, also look at pref_tab_functions.inc.php setAutoLoginCookie(). Same technique.
147                         $saltedPassword = hash('sha512', $row['pass'] . hash('sha512', $now));
148                         ATutor.setcookie('ATLogin', $this_login, $cookie_expire, $parts['path']);
149                         ATutor.setcookie('ATPass',  $saltedPassword,  $cookie_expire, $parts['path']);
150                 }
151                 
152                 $_SESSION['first_login'] = false;
153                 if ($row['last_login'] == null || $row['last_login'] == '' || $row['last_login'] == '0000-00-00 00:00:00' 
154             || $_SESSION['prefs']['PREF_MODIFIED']!==1) {
155                     $_SESSION['first_login'] = true;
156                 }
157
158                 $sql = "UPDATE ".TABLE_PREFIX."members SET creation_date=creation_date, last_login='$now' WHERE member_id=$_SESSION[member_id]";
159                 mysql_query($sql, $db);
160
161                 //clear login attempt on successful login
162                 $sql = 'DELETE FROM '.TABLE_PREFIX."member_login_attempt WHERE login='$this_login'";
163                 mysql_query($sql, $db);
164
165                 //if page variable is set, bring them there.
166                 if (isset($_POST['p']) && $_POST['p']!=''){
167                         header ('Location: '.urldecode($_POST['p']));
168                         exit;
169                 }
170                 
171                 $msg->addFeedback('LOGIN_SUCCESS');
172         header('Location: bounce.php?course='.$_POST['form_course_id']);
173                 exit;
174         } else {
175                 // check if it's an admin login.
176                 $sql = "SELECT login, `privileges`, language FROM ".TABLE_PREFIX."admins WHERE login='$this_login' AND SHA1(CONCAT(password, '$_SESSION[token]'))='$this_password' AND `privileges`>0";
177                 $result = mysql_query($sql, $db);
178
179                 if ($row = mysql_fetch_assoc($result)) {
180                         $sql = "UPDATE ".TABLE_PREFIX."admins SET last_login=NOW() WHERE login='$this_login'";
181                         mysql_query($sql, $db);
182
183                         $_SESSION['login']              = $row['login'];
184                         $_SESSION['valid_user'] = true;
185                         $_SESSION['course_id']  = -1;
186                         $_SESSION['privileges'] = intval($row['privileges']);
187                         $_SESSION['lang'] = $row['language'];
188
189                         write_to_log(AT_ADMIN_LOG_UPDATE, 'admins', mysql_affected_rows($db), $sql);
190                         //clear login attempt on successful login
191                         $sql = 'DELETE FROM '.TABLE_PREFIX."member_login_attempt WHERE login='$this_login'";
192                         mysql_query($sql, $db);
193
194                         $msg->addFeedback('LOGIN_SUCCESS');
195
196                         header('Location: admin/index.php');
197                         exit;
198
199                 } else {
200                         //Only if the user exist in our database
201 //                      if ($attempt_login_name!=''){
202                                 $expiry_stmt = '';
203                                 $attempt_login++;
204                                 if ($attempt_expiry==0){
205                                         $expiry_stmt = ', expiry='.(time() + LOGIN_ATTEMPT_LOCKED_TIME * 60);   //an hour from now
206                                 } else {
207                                         $expiry_stmt = ', expiry='.$attempt_expiry;     
208                                 }
209                                 $sql = 'REPLACE INTO '.TABLE_PREFIX.'member_login_attempt SET attempt='.$attempt_login . $expiry_stmt .", login='$this_login'";
210                                 mysql_query($sql, $db);                         
211 //                      }
212                 }
213                 //Different error messages depend on the number of login failure.
214                 if ($_config['max_login'] > 0 && ($_config['max_login']-$attempt_login)==2){
215                         $msg->addError('MAX_LOGIN_ATTEMPT_2');
216                 } elseif ($_config['max_login'] > 0 && ($_config['max_login']-$attempt_login)==1){
217                         $msg->addError('MAX_LOGIN_ATTEMPT_1');
218                 } elseif ($_config['max_login'] > 0 && ($_config['max_login']-$attempt_login)==0){
219                         $msg->addError('MAX_LOGIN_ATTEMPT');
220                 } else {
221                         $msg->addError('INVALID_LOGIN');
222                 } 
223         }
224 }
225
226 if (isset($_SESSION['member_id'])) {
227         $sql = "DELETE FROM ".TABLE_PREFIX."users_online WHERE member_id=$_SESSION[member_id]";
228         $result = @mysql_query($sql, $db);
229 }
230
231 unset($_SESSION['login']);
232 unset($_SESSION['valid_user']);
233 unset($_SESSION['member_id']);
234 unset($_SESSION['is_admin']);
235 unset($_SESSION['course_id']);
236 unset($_SESSION['is_super_admin']);
237 unset($_SESSION['dd_question_ids']);
238
239 $_SESSION['prefs']['PREF_FORM_FOCUS'] = 1;
240
241 /*****************************/
242 /* template starts down here */
243
244 $onload = 'document.form.form_login.focus();';
245
246 $savant->assign('form_course_id', $_GET['course']);
247
248 if (isset($_GET['course']) && $_GET['course']) {
249         $savant->assign('title',  ' '._AT('to1').' '.$system_courses[$_GET['course']]['title']);
250 } else {
251         $savant->assign('title',  ' ');
252 }
253
254 header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
255 $savant->display('login.tmpl.php');
256 ?>