Proyectos de Subversion Moodle

Rev

Rev 1391 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
1441 ariadna 3
// This file is part of Moodle - http://moodle.org/
1 efrain 4
//
1441 ariadna 5
// Moodle is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
1 efrain 9
//
1441 ariadna 10
// Moodle is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
1 efrain 14
//
1441 ariadna 15
// You should have received a copy of the GNU General Public License
16
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
1 efrain 17
 
18
/**
1441 ariadna 19
 * Main login page.
1 efrain 20
 *
21
 * @package    core
22
 * @subpackage auth
23
 * @copyright  1999 onwards Martin Dougiamas  http://dougiamas.com
24
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
26
 
27
require('../config.php');
28
require_once('lib.php');
29
 
30
redirect_if_major_upgrade_required();
31
 
1441 ariadna 32
$testsession = optional_param('testsession', 0, PARAM_INT); // test session works properly
33
$anchor      = optional_param('anchor', '', PARAM_RAW);     // Used to restore hash anchor to wantsurl.
34
$loginredirect = optional_param('loginredirect', 1, PARAM_BOOL);   // Used to bypass alternateloginurl.
1 efrain 35
 
1441 ariadna 36
$resendconfirmemail = optional_param('resendconfirmemail', false, PARAM_BOOL);
1 efrain 37
 
1441 ariadna 38
// It might be safe to do this for non-Behat sites, or there might
39
// be a security risk. For now we only allow it on Behat sites.
40
// If you wants to do the analysis, you may be able to remove the
41
// if (BEHAT_SITE_RUNNING).
1 efrain 42
if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) {
1441 ariadna 43
    $wantsurl    = optional_param('wantsurl', '', PARAM_LOCALURL);   // Overrides $SESSION->wantsurl if given.
1 efrain 44
    if ($wantsurl !== '') {
45
        $SESSION->wantsurl = (new moodle_url($wantsurl))->out(false);
46
    }
47
}
48
 
49
$context = context_system::instance();
50
$PAGE->set_url("$CFG->wwwroot/login/index.php");
51
$PAGE->set_context($context);
52
$PAGE->set_pagelayout('login');
1441 ariadna 53
$PAGE->set_cacheable(false);
1 efrain 54
 
1441 ariadna 55
/// Initialize variables
56
$errormsg = '';
57
$infomsg = '';
58
$errorcode = 0;
1 efrain 59
 
1441 ariadna 60
// login page requested session test
1 efrain 61
if ($testsession) {
62
    if ($testsession == $USER->id) {
63
        if (isset($SESSION->wantsurl)) {
64
            $urltogo = $SESSION->wantsurl;
65
        } else {
1441 ariadna 66
            $urltogo = $CFG->wwwroot.'/';
1 efrain 67
        }
68
        unset($SESSION->wantsurl);
69
        redirect($urltogo);
70
    } else {
1441 ariadna 71
        // TODO: try to find out what is the exact reason why sessions do not work
1 efrain 72
        $errormsg = get_string("cookiesnotenabled");
73
        $errorcode = 1;
74
    }
75
}
76
 
1441 ariadna 77
/// Check for timed out sessions
1 efrain 78
if (!empty($SESSION->has_timed_out)) {
79
    $session_has_timed_out = true;
80
    unset($SESSION->has_timed_out);
81
} else {
82
    $session_has_timed_out = false;
83
}
84
 
1441 ariadna 85
$frm  = false;
1 efrain 86
$user = false;
87
 
1441 ariadna 88
$authsequence = get_enabled_auth_plugins(); // Auths, in sequence.
89
foreach($authsequence as $authname) {
1 efrain 90
    $authplugin = get_auth_plugin($authname);
1441 ariadna 91
    // The auth plugin's loginpage_hook() can eventually set $frm and/or $user.
1 efrain 92
    $authplugin->loginpage_hook();
93
}
94
 
95
 
1441 ariadna 96
/// Define variables used in page
1 efrain 97
$site = get_site();
98
 
1441 ariadna 99
// Ignore any active pages in the navigation/settings.
100
// We do this because there won't be an active page there, and by ignoring the active pages the
101
// navigation and settings won't be initialised unless something else needs them.
1 efrain 102
$PAGE->navbar->ignore_active();
103
$loginsite = get_string("loginsite");
104
$PAGE->navbar->add($loginsite);
105
 
1441 ariadna 106
if ($user !== false or $frm !== false or $errormsg !== '') {
107
    // some auth plugin already supplied full user, fake form data or prevented user login with error message
1391 ariadna 108
 
1441 ariadna 109
} else if (!empty($SESSION->wantsurl) && file_exists($CFG->dirroot.'/login/weblinkauth.php')) {
110
    // Handles the case of another Moodle site linking into a page on this site
111
    //TODO: move weblink into own auth plugin
112
    include($CFG->dirroot.'/login/weblinkauth.php');
1 efrain 113
    if (function_exists('weblink_auth')) {
114
        $user = weblink_auth($SESSION->wantsurl);
115
    }
116
    if ($user) {
117
        $frm->username = $user->username;
118
    } else {
119
        $frm = data_submitted();
120
    }
1441 ariadna 121
 
1 efrain 122
} else {
123
    $frm = data_submitted();
124
}
125
 
1441 ariadna 126
// Restore the #anchor to the original wantsurl. Note that this
127
// will only work for internal auth plugins, SSO plugins such as
128
// SAML / CAS / OIDC will have to handle this correctly directly.
1 efrain 129
if ($anchor && isset($SESSION->wantsurl) && strpos($SESSION->wantsurl, '#') === false) {
130
    $wantsurl = new moodle_url($SESSION->wantsurl);
131
    $wantsurl->set_anchor(substr($anchor, 1));
132
    $SESSION->wantsurl = $wantsurl->out();
133
}
134
 
1441 ariadna 135
/// Check if the user has actually submitted login data to us
1 efrain 136
 
1441 ariadna 137
if ($frm and isset($frm->username)) {                             // Login WITH cookies
138
 
1 efrain 139
    $frm->username = trim(core_text::strtolower($frm->username));
140
 
1441 ariadna 141
    if (is_enabled_auth('none') ) {
1 efrain 142
        if ($frm->username !== core_user::clean_field($frm->username, 'username')) {
1441 ariadna 143
            $errormsg = get_string('username').': '.get_string("invalidusername");
1 efrain 144
            $errorcode = 2;
145
            $user = null;
146
        }
147
    }
148
 
149
    if ($user) {
1441 ariadna 150
        // The auth plugin has already provided the user via the loginpage_hook() called above.
1 efrain 151
    } else if (($frm->username == 'guest') and empty($CFG->guestloginbutton)) {
1441 ariadna 152
        $user = false;    /// Can't log in as guest if guest button is disabled
1 efrain 153
        $frm = false;
154
    } else {
155
        if (empty($errormsg)) {
156
            $logintoken = isset($frm->logintoken) ? $frm->logintoken : '';
157
            $loginrecaptcha = login_captcha_enabled() ? $frm->{'g-recaptcha-response'} ?? '' : false;
158
            $user = authenticate_user_login($frm->username, $frm->password, false, $errorcode, $logintoken, $loginrecaptcha);
159
        }
160
    }
161
 
1441 ariadna 162
    // Intercept 'restored' users to provide them with info & reset password
1 efrain 163
    if (!$user and $frm and is_restored_user($frm->username)) {
164
        $PAGE->set_title(get_string('restoredaccount'));
165
        $PAGE->set_heading($site->fullname);
166
        echo $OUTPUT->header();
167
        echo $OUTPUT->heading(get_string('restoredaccount'));
168
        echo $OUTPUT->box(get_string('restoredaccountinfo'), 'generalbox boxaligncenter');
1441 ariadna 169
        require_once('restored_password_form.php'); // Use our "supplanter" login_forgot_password_form. MDL-20846
1 efrain 170
        $form = new login_forgot_password_form('forgot_password.php', array('username' => $frm->username));
171
        $form->display();
172
        echo $OUTPUT->footer();
173
        die;
174
    }
175
 
1441 ariadna 176
    if ($user) {
1391 ariadna 177
 
1441 ariadna 178
        // language setup
1 efrain 179
        if (isguestuser($user)) {
1441 ariadna 180
            // no predefined language for guests - use existing session or default site lang
1 efrain 181
            unset($user->lang);
1441 ariadna 182
 
1 efrain 183
        } else if (!empty($user->lang)) {
1441 ariadna 184
            // unset previous session language - use user preference instead
1 efrain 185
            unset($SESSION->lang);
186
        }
187
 
1441 ariadna 188
        if (empty($user->confirmed)) {       // This account was never confirmed
1 efrain 189
            $PAGE->set_title(get_string("mustconfirm"));
190
            $PAGE->set_heading($site->fullname);
191
            echo $OUTPUT->header();
192
            echo $OUTPUT->heading(get_string("mustconfirm"));
193
            if ($resendconfirmemail) {
194
                if (!send_confirmation_email($user)) {
195
                    echo $OUTPUT->notification(get_string('emailconfirmsentfailure'), \core\output\notification::NOTIFY_ERROR);
196
                } else {
197
                    echo $OUTPUT->notification(get_string('emailconfirmsentsuccess'), \core\output\notification::NOTIFY_SUCCESS);
198
                }
199
            }
200
            echo $OUTPUT->box(get_string("emailconfirmsent", "", s($user->email)), "generalbox boxaligncenter");
1441 ariadna 201
            $resendconfirmurl = new moodle_url('/login/index.php',
1 efrain 202
                [
203
                    'username' => $frm->username,
204
                    'password' => $frm->password,
205
                    'resendconfirmemail' => true,
206
                    'logintoken' => \core\session\manager::get_login_token()
207
                ]
208
            );
209
            echo $OUTPUT->single_button($resendconfirmurl, get_string('emailconfirmationresend'));
210
            echo $OUTPUT->footer();
211
            die;
212
        }
213
 
1441 ariadna 214
    /// Let's get them all set up.
1 efrain 215
        complete_user_login($user);
216
 
217
        \core\session\manager::apply_concurrent_login_limit($user->id, session_id());
218
 
1441 ariadna 219
        // sets the username cookie
1 efrain 220
        if (!empty($CFG->nolastloggedin)) {
1441 ariadna 221
            // do not store last logged in user in cookie
222
            // auth plugins can temporarily override this from loginpage_hook()
223
            // do not save $CFG->nolastloggedin in database!
224
 
1 efrain 225
        } else if (empty($CFG->rememberusername)) {
1441 ariadna 226
            // no permanent cookies, delete old one if exists
1 efrain 227
            set_moodle_cookie('');
1441 ariadna 228
 
1 efrain 229
        } else {
230
            set_moodle_cookie($USER->username);
231
        }
232
 
233
        $urltogo = core_login_get_return_url();
234
 
1441 ariadna 235
    /// check if user password has expired
236
    /// Currently supported only for ldap-authentication module
1 efrain 237
        $userauth = get_auth_plugin($USER->auth);
238
        if (!isguestuser() and !empty($userauth->config->expiration) and $userauth->config->expiration == 1) {
239
            $externalchangepassword = false;
240
            if ($userauth->can_change_password()) {
241
                $passwordchangeurl = $userauth->change_password_url();
242
                if (!$passwordchangeurl) {
1441 ariadna 243
                    $passwordchangeurl = $CFG->wwwroot.'/login/change_password.php';
1 efrain 244
                } else {
245
                    $externalchangepassword = true;
246
                }
247
            } else {
1441 ariadna 248
                $passwordchangeurl = $CFG->wwwroot.'/login/change_password.php';
1 efrain 249
            }
250
            $days2expire = $userauth->password_expire($USER->username);
251
            $PAGE->set_title($loginsite);
252
            $PAGE->set_heading("$site->fullname");
253
            if (intval($days2expire) > 0 && intval($days2expire) < intval($userauth->config->expiration_warning)) {
254
                echo $OUTPUT->header();
255
                echo $OUTPUT->confirm(get_string('auth_passwordwillexpire', 'auth', $days2expire), $passwordchangeurl, $urltogo);
256
                echo $OUTPUT->footer();
257
                exit;
1441 ariadna 258
            } elseif (intval($days2expire) < 0 ) {
1 efrain 259
                if ($externalchangepassword) {
1441 ariadna 260
                    // We end the session if the change password form is external. This prevents access to the site
261
                    // until the password is correctly changed.
1 efrain 262
                    require_logout();
263
                } else {
1441 ariadna 264
                    // If we use the standard change password form, this user preference will be reset when the password
265
                    // is changed. Until then it will prevent access to the site.
1 efrain 266
                    set_user_preference('auth_forcepasswordchange', 1, $USER);
267
                }
268
                echo $OUTPUT->header();
269
                echo $OUTPUT->confirm(get_string('auth_passwordisexpired', 'auth'), $passwordchangeurl, $urltogo);
270
                echo $OUTPUT->footer();
271
                exit;
272
            }
273
        }
274
 
1441 ariadna 275
        // Discard any errors before the last redirect.
1 efrain 276
        unset($SESSION->loginerrormsg);
277
        unset($SESSION->logininfomsg);
278
 
1441 ariadna 279
        // Discard loginredirect if we are redirecting away.
1 efrain 280
        unset($SESSION->loginredirect);
281
 
1441 ariadna 282
        // test the session actually works by redirecting to self
1 efrain 283
        $SESSION->wantsurl = $urltogo;
1441 ariadna 284
        redirect(new moodle_url(get_login_url(), array('testsession'=>$USER->id)));
285
 
1 efrain 286
    } else {
287
        if (empty($errormsg)) {
288
            if ($errorcode == AUTH_LOGIN_UNAUTHORISED) {
289
                $errormsg = get_string("unauthorisedlogin", "", $frm->username);
290
            } else if ($errorcode == AUTH_LOGIN_FAILED_RECAPTCHA) {
291
                $errormsg = get_string('missingrecaptchachallengefield');
292
            } else {
293
                $errormsg = get_string("invalidlogin");
294
                $errorcode = 3;
295
            }
296
        }
297
    }
298
}
299
 
1441 ariadna 300
/// Detect problems with timedout sessions
1 efrain 301
if ($session_has_timed_out and !data_submitted()) {
302
    $errormsg = get_string('sessionerroruser', 'error');
303
    $errorcode = 4;
304
}
305
 
1441 ariadna 306
/// First, let's remember where the user was trying to get to before they got here
1 efrain 307
 
308
if (empty($SESSION->wantsurl)) {
309
    $SESSION->wantsurl = null;
310
    $referer = get_local_referer(false);
1441 ariadna 311
    if ($referer &&
312
            $referer != $CFG->wwwroot &&
313
            $referer != $CFG->wwwroot . '/' &&
314
            $referer != $CFG->wwwroot . '/login/' &&
315
            strpos($referer, $CFG->wwwroot . '/login/?') !== 0 &&
316
            strpos($referer, $CFG->wwwroot . '/login/index.php') !== 0) { // There might be some extra params such as ?lang=.
1 efrain 317
        $SESSION->wantsurl = $referer;
318
    }
319
}
320
 
1441 ariadna 321
// Check if loginredirect is set in the SESSION.
1 efrain 322
if ($errorcode && isset($SESSION->loginredirect)) {
323
    $loginredirect = $SESSION->loginredirect;
324
}
325
$SESSION->loginredirect = $loginredirect;
326
 
1441 ariadna 327
/// Redirect to alternative login URL if needed
1 efrain 328
if (!empty($CFG->alternateloginurl) && $loginredirect) {
329
    $loginurl = new moodle_url($CFG->alternateloginurl);
1441 ariadna 330
 
1 efrain 331
    $loginurlstr = $loginurl->out(false);
332
 
333
    if ($SESSION->wantsurl != '' && strpos($SESSION->wantsurl, $loginurlstr) === 0) {
1441 ariadna 334
        // We do not want to return to alternate url.
1 efrain 335
        $SESSION->wantsurl = null;
336
    }
337
 
1441 ariadna 338
    // If error code then add that to url.
1 efrain 339
    if ($errorcode) {
340
        $loginurl->param('errorcode', $errorcode);
341
    }
342
 
343
    redirect($loginurl->out(false));
344
}
345
 
1441 ariadna 346
/// Generate the login page with forms
1 efrain 347
 
348
if (!isset($frm) or !is_object($frm)) {
349
    $frm = new stdClass();
350
}
351
 
1441 ariadna 352
if (empty($frm->username) && $authsequence[0] != 'shibboleth') {  // See bug 5184
1 efrain 353
    if (!empty($_GET["username"])) {
1441 ariadna 354
        // we do not want data from _POST here
355
        $frm->username = clean_param($_GET["username"], PARAM_RAW); // we do not want data from _POST here
1 efrain 356
    } else {
357
        $frm->username = get_moodle_cookie();
358
    }
1441 ariadna 359
 
1 efrain 360
    $frm->password = "";
361
}
362
 
363
if (!empty($SESSION->loginerrormsg) || !empty($SESSION->logininfomsg)) {
1441 ariadna 364
    // We had some messages before redirect, show them now.
1 efrain 365
    $errormsg = $SESSION->loginerrormsg ?? '';
366
    $infomsg = $SESSION->logininfomsg ?? '';
367
    unset($SESSION->loginerrormsg);
368
    unset($SESSION->logininfomsg);
1441 ariadna 369
 
1 efrain 370
} else if ($testsession) {
1441 ariadna 371
    // No need to redirect here.
1 efrain 372
    unset($SESSION->loginerrormsg);
373
    unset($SESSION->logininfomsg);
1441 ariadna 374
 
1 efrain 375
} else if ($errormsg or !empty($frm->password)) {
1441 ariadna 376
    // We must redirect after every password submission.
1 efrain 377
    if ($errormsg) {
378
        $SESSION->loginerrormsg = $errormsg;
379
    }
1441 ariadna 380
 
381
    // Add redirect param to url.
1 efrain 382
    $loginurl = new moodle_url('/login/index.php');
383
    $loginurl->param('loginredirect', $SESSION->loginredirect);
1441 ariadna 384
 
1 efrain 385
    redirect($loginurl->out(false));
386
}
387
 
388
$PAGE->set_title($loginsite);
389
$PAGE->set_heading("$site->fullname");
390
 
391
echo $OUTPUT->header();
392
 
393
if (isloggedin() and !isguestuser()) {
1441 ariadna 394
    // prevent logging when already logged in, we do not want them to relogin by accident because sesskey would be changed
1 efrain 395
    echo $OUTPUT->box_start();
1441 ariadna 396
    $logout = new single_button(new moodle_url('/login/logout.php', array('sesskey'=>sesskey(),'loginpage'=>1)), get_string('logout'), 'post');
1 efrain 397
    $continue = new single_button(new moodle_url('/'), get_string('cancel'), 'get');
398
    echo $OUTPUT->confirm(get_string('alreadyloggedin', 'error', fullname($USER)), $logout, $continue);
399
    echo $OUTPUT->box_end();
400
} else {
401
    $loginform = new \core_auth\output\login($authsequence, $frm->username);
402
    $loginform->set_error($errormsg);
403
    $loginform->set_info($infomsg);
404
    echo $OUTPUT->render($loginform);
405
}
406
 
407
echo $OUTPUT->footer();