Ejemplo n.º 1
0
/**
 * Called from set/unset_user_preferences, so that the prefs can be correctly reloaded in different sessions.
 *
 * NOTE: internal function, do not call from other code.
 *
 * @package core
 * @access private
 * @param integer $userid the user whose prefs were changed.
 */
function mark_user_preferences_changed($userid)
{
    global $CFG;
    if (empty($userid) or isguestuser($userid)) {
        // No cache flags for guest and not-logged-in users.
        return;
    }
    set_cache_flag('userpreferenceschanged', $userid, 1, time() + $CFG->sessiontimeout);
}
Ejemplo n.º 2
0
 public function test_set_user_preference()
 {
     global $DB, $USER;
     $this->resetAfterTest();
     $this->setAdminUser();
     $otheruser = $this->getDataGenerator()->create_user();
     $otheruserid = $otheruser->id;
     $DB->delete_records('user_preferences', array('userid' => $otheruserid));
     set_cache_flag('userpreferenceschanged', $otheruserid, null);
     $user = new stdClass();
     $user->id = $otheruserid;
     set_user_preference('aaa', 'bbb', $otheruserid);
     $this->assertSame('bbb', $DB->get_field('user_preferences', 'value', array('userid' => $otheruserid, 'name' => 'aaa')));
     $this->assertSame('bbb', get_user_preferences('aaa', null, $otheruserid));
     set_user_preference('xxx', 'yyy', $user);
     $this->assertSame('yyy', $DB->get_field('user_preferences', 'value', array('userid' => $otheruserid, 'name' => 'xxx')));
     $this->assertSame('yyy', get_user_preferences('xxx', null, $otheruserid));
     $this->assertTrue(is_array($user->preference));
     $this->assertSame('bbb', $user->preference['aaa']);
     $this->assertSame('yyy', $user->preference['xxx']);
     set_user_preference('xxx', null, $user);
     $this->assertFalse($DB->get_field('user_preferences', 'value', array('userid' => $otheruserid, 'name' => 'xxx')));
     $this->assertNull(get_user_preferences('xxx', null, $otheruserid));
     set_user_preference('ooo', true, $user);
     $prefs = get_user_preferences(null, null, $otheruserid);
     $this->assertSame($user->preference['aaa'], $prefs['aaa']);
     $this->assertSame($user->preference['ooo'], $prefs['ooo']);
     $this->assertSame('1', $prefs['ooo']);
     set_user_preference('null', 0, $user);
     $this->assertSame('0', get_user_preferences('null', null, $otheruserid));
     $this->assertSame('lala', get_user_preferences('undefined', 'lala', $otheruserid));
     $DB->delete_records('user_preferences', array('userid' => $otheruserid));
     set_cache_flag('userpreferenceschanged', $otheruserid, null);
     // Test $USER default.
     set_user_preference('_test_user_preferences_pref', 'ok');
     $this->assertSame('ok', $USER->preference['_test_user_preferences_pref']);
     unset_user_preference('_test_user_preferences_pref');
     $this->assertTrue(!isset($USER->preference['_test_user_preferences_pref']));
     // Test 1333 char values (no need for unicode, there are already tests for that in DB tests).
     $longvalue = str_repeat('a', 1333);
     set_user_preference('_test_long_user_preference', $longvalue);
     $this->assertEquals($longvalue, get_user_preferences('_test_long_user_preference'));
     $this->assertEquals($longvalue, $DB->get_field('user_preferences', 'value', array('userid' => $USER->id, 'name' => '_test_long_user_preference')));
     // Test > 1333 char values, coding_exception expected.
     $longvalue = str_repeat('a', 1334);
     try {
         set_user_preference('_test_long_user_preference', $longvalue);
         $this->fail('Exception expected - longer than 1333 chars not allowed as preference value');
     } catch (moodle_exception $ex) {
         $this->assertInstanceOf('coding_exception', $ex);
     }
     // Test invalid params.
     try {
         set_user_preference('_test_user_preferences_pref', array());
         $this->fail('Exception expected - array not valid preference value');
     } catch (moodle_exception $ex) {
         $this->assertInstanceOf('coding_exception', $ex);
     }
     try {
         set_user_preference('_test_user_preferences_pref', new stdClass());
         $this->fail('Exception expected - class not valid preference value');
     } catch (moodle_exception $ex) {
         $this->assertInstanceOf('coding_exception', $ex);
     }
     try {
         set_user_preference('_test_user_preferences_pref', 1, array('xx' => 1));
         $this->fail('Exception expected - user instance expected');
     } catch (moodle_exception $ex) {
         $this->assertInstanceOf('coding_exception', $ex);
     }
     try {
         set_user_preference('_test_user_preferences_pref', 1, 'abc');
         $this->fail('Exception expected - user instance expected');
     } catch (moodle_exception $ex) {
         $this->assertInstanceOf('coding_exception', $ex);
     }
     try {
         set_user_preference('', 1);
         $this->fail('Exception expected - invalid name accepted');
     } catch (moodle_exception $ex) {
         $this->assertInstanceOf('coding_exception', $ex);
     }
     try {
         set_user_preference('1', 1);
         $this->fail('Exception expected - invalid name accepted');
     } catch (moodle_exception $ex) {
         $this->assertInstanceOf('coding_exception', $ex);
     }
 }
Ejemplo n.º 3
0
/**
 * Mark a context as dirty (with timestamp) so as to force reloading of the context.
 *
 * @deprecated since 2.2, use $context->mark_dirty() instead
 * @see context::mark_dirty()
 * @param string $path context path
 */
function mark_context_dirty($path)
{
    global $CFG, $USER, $ACCESSLIB_PRIVATE;
    debugging('mark_context_dirty() is deprecated, please use $context->mark_dirty() instead.', DEBUG_DEVELOPER);
    if (during_initial_install()) {
        return;
    }
    // only if it is a non-empty string
    if (is_string($path) && $path !== '') {
        set_cache_flag('accesslib/dirtycontexts', $path, 1, time() + $CFG->sessiontimeout);
        if (isset($ACCESSLIB_PRIVATE->dirtycontexts)) {
            $ACCESSLIB_PRIVATE->dirtycontexts[$path] = 1;
        } else {
            if (CLI_SCRIPT) {
                $ACCESSLIB_PRIVATE->dirtycontexts = array($path => 1);
            } else {
                if (isset($USER->access['time'])) {
                    $ACCESSLIB_PRIVATE->dirtycontexts = get_cache_flags('accesslib/dirtycontexts', $USER->access['time'] - 2);
                } else {
                    $ACCESSLIB_PRIVATE->dirtycontexts = array($path => 1);
                }
                // flags not loaded yet, it will be done later in $context->reload_if_dirty()
            }
        }
    }
}
Ejemplo n.º 4
0
 /**
  * To be called from a page running under NTLM's
  * "Integrated Windows Authentication".
  *
  * If successful, it will set a special "cookie" (not an HTTP cookie!)
  * in cache_flags under the $this->pluginconfig/ntlmsess "plugin" and return true.
  * The "cookie" will be picked up by ntlmsso_finish() to complete the
  * process.
  *
  * On failure it will return false for the caller to display an appropriate
  * error message (probably saying that Integrated Windows Auth isn't enabled!)
  *
  * NOTE that this code will execute under the OS user credentials,
  * so we MUST avoid dealing with files -- such as session files.
  * (The caller should define('NO_MOODLE_COOKIES', true) before including config.php)
  *
  */
 function ntlmsso_magic($sesskey)
 {
     if (isset($_SERVER['REMOTE_USER']) && !empty($_SERVER['REMOTE_USER'])) {
         // HTTP __headers__ seem to be sent in ISO-8859-1 encoding
         // (according to my reading of RFC-1945, RFC-2616 and RFC-2617 and
         // my local tests), so we need to convert the REMOTE_USER value
         // (i.e., what we got from the HTTP WWW-Authenticate header) into UTF-8
         $username = core_text::convert($_SERVER['REMOTE_USER'], 'iso-8859-1', 'utf-8');
         switch ($this->config->ntlmsso_type) {
             case 'ntlm':
                 // The format is now configurable, so try to extract the username
                 $username = $this->get_ntlm_remote_user($username);
                 if (empty($username)) {
                     return false;
                 }
                 break;
             case 'kerberos':
                 // Format is username@DOMAIN
                 $username = substr($username, 0, strpos($username, '@'));
                 break;
             default:
                 error_log($this->errorlogtag . get_string('ntlmsso_unknowntype', 'auth_ldap'));
                 return false;
                 // Should never happen!
         }
         $username = core_text::strtolower($username);
         // Compatibility hack
         set_cache_flag($this->pluginconfig . '/ntlmsess', $sesskey, $username, AUTH_NTLMTIMEOUT);
         return true;
     }
     return false;
 }
Ejemplo n.º 5
0
/**
 * Mark a context as dirty (with timestamp)
 * so as to force reloading of the context.
 * @param string $path context path
 */
function mark_context_dirty($path)
{
    global $CFG, $ACCESSLIB_PRIVATE;
    if (empty($CFG->rolesactive)) {
        return;
    }
    // only if it is a non-empty string
    if (is_string($path) && $path !== '') {
        set_cache_flag('accesslib/dirtycontexts', $path, 1, time() + $CFG->sessiontimeout);
        if (isset($ACCESSLIB_PRIVATE->dirtycontexts)) {
            $ACCESSLIB_PRIVATE->dirtycontexts[$path] = 1;
        }
    }
}
Ejemplo n.º 6
0
/**
 * Notify admin users or admin user of any failed logins (since last notification).
 *
 * Note that this function must be only executed from the cron script
 * It uses the cache_flags system to store temporary records, deleting them
 * by name before finishing
 *
 * @uses $CFG
 * @uses $db
 * @uses HOURSECS
 */
function notify_login_failures()
{
    global $CFG, $db;
    switch ($CFG->notifyloginfailures) {
        case 'mainadmin':
            $recip = array(get_admin());
            break;
        case 'alladmins':
            $recip = get_admins();
            break;
    }
    if (empty($CFG->lastnotifyfailure)) {
        $CFG->lastnotifyfailure = 0;
    }
    // we need to deal with the threshold stuff first.
    if (empty($CFG->notifyloginthreshold)) {
        $CFG->notifyloginthreshold = 10;
        // default to something sensible.
    }
    /// Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure
    /// and insert them into the cache_flags temp table
    $iprs = get_recordset_sql("SELECT ip, count(*)\n                                 FROM {$CFG->prefix}log\n                                WHERE module = 'login'\n                                  AND action = 'error'\n                                  AND time > {$CFG->lastnotifyfailure}\n                             GROUP BY ip\n                               HAVING count(*) >= {$CFG->notifyloginthreshold}");
    while ($iprec = rs_fetch_next_record($iprs)) {
        if (!empty($iprec->ip)) {
            set_cache_flag('login_failure_by_ip', $iprec->ip, '1', 0);
        }
    }
    rs_close($iprs);
    /// Get all the INFOs with more than notifyloginthreshold failures since lastnotifyfailure
    /// and insert them into the cache_flags temp table
    $infors = get_recordset_sql("SELECT info, count(*)\n                                   FROM {$CFG->prefix}log\n                                  WHERE module = 'login'\n                                    AND action = 'error'\n                                    AND time > {$CFG->lastnotifyfailure}\n                               GROUP BY info\n                                 HAVING count(*) >= {$CFG->notifyloginthreshold}");
    while ($inforec = rs_fetch_next_record($infors)) {
        if (!empty($inforec->info)) {
            set_cache_flag('login_failure_by_info', $inforec->info, '1', 0);
        }
    }
    rs_close($infors);
    /// Now, select all the login error logged records belonging to the ips and infos
    /// since lastnotifyfailure, that we have stored in the cache_flags table
    $logsrs = get_recordset_sql("SELECT l.*, u.firstname, u.lastname\n                                   FROM {$CFG->prefix}log l\n                                   JOIN {$CFG->prefix}cache_flags cf ON (l.ip = cf.name)\n                              LEFT JOIN {$CFG->prefix}user u ON (l.userid = u.id)\n                                  WHERE l.module = 'login'\n                                    AND l.action = 'error'\n                                    AND l.time > {$CFG->lastnotifyfailure}\n                                    AND cf.flagtype = 'login_failure_by_ip'\n                             UNION ALL\n                                 SELECT l.*, u.firstname, u.lastname\n                                   FROM {$CFG->prefix}log l\n                                   JOIN {$CFG->prefix}cache_flags cf ON (l.info = cf.name)\n                              LEFT JOIN {$CFG->prefix}user u ON (l.userid = u.id)\n                                  WHERE l.module = 'login'\n                                    AND l.action = 'error'\n                                    AND l.time > {$CFG->lastnotifyfailure}\n                                    AND cf.flagtype = 'login_failure_by_info'\n                             ORDER BY time DESC");
    /// Init some variables
    $count = 0;
    $messages = '';
    /// Iterate over the logs recordset
    while ($log = rs_fetch_next_record($logsrs)) {
        $log->time = userdate($log->time);
        $messages .= get_string('notifyloginfailuresmessage', '', $log) . "\n";
        $count++;
    }
    rs_close($logsrs);
    /// If we haven't run in the last hour and
    /// we have something useful to report and we
    /// are actually supposed to be reporting to somebody
    if (time() - HOURSECS > $CFG->lastnotifyfailure && $count > 0 && is_array($recip) && count($recip) > 0) {
        $site = get_site();
        $subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname));
        /// Calculate the complete body of notification (start + messages + end)
        $body = get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot) . ($CFG->lastnotifyfailure != 0 ? '(' . userdate($CFG->lastnotifyfailure) . ')' : '') . "\n\n" . $messages . "\n\n" . get_string('notifyloginfailuresmessageend', '', $CFG->wwwroot) . "\n\n";
        /// For each destination, send mail
        mtrace('Emailing admins about ' . $count . ' failed login attempts');
        foreach ($recip as $admin) {
            email_to_user($admin, get_admin(), $subject, $body);
        }
        /// Update lastnotifyfailure with current time
        set_config('lastnotifyfailure', time());
    }
    /// Finally, delete all the temp records we have created in cache_flags
    delete_records_select('cache_flags', "flagtype IN ('login_failure_by_ip', 'login_failure_by_info')");
}
Ejemplo n.º 7
0
 public function test_set_user_preference()
 {
     global $DB, $USER;
     if (!($otheruserid = $this->get_fake_preference_test_userid())) {
         $this->fail('Can not find unused user id for the preferences test');
         return;
     }
     $DB->delete_records('user_preferences', array('userid' => $otheruserid));
     set_cache_flag('userpreferenceschanged', $otheruserid, null);
     $user = new stdClass();
     $user->id = $otheruserid;
     set_user_preference('aaa', 'bbb', $otheruserid);
     $this->assertEqual('bbb', $DB->get_field('user_preferences', 'value', array('userid' => $otheruserid, 'name' => 'aaa')));
     $this->assertEqual('bbb', get_user_preferences('aaa', null, $otheruserid));
     set_user_preference('xxx', 'yyy', $user);
     $this->assertEqual('yyy', $DB->get_field('user_preferences', 'value', array('userid' => $otheruserid, 'name' => 'xxx')));
     $this->assertEqual('yyy', get_user_preferences('xxx', null, $otheruserid));
     $this->assertTrue(is_array($user->preference));
     $this->assertEqual($user->preference['aaa'], 'bbb');
     $this->assertEqual($user->preference['xxx'], 'yyy');
     set_user_preference('xxx', NULL, $user);
     $this->assertIdentical(false, $DB->get_field('user_preferences', 'value', array('userid' => $otheruserid, 'name' => 'xxx')));
     $this->assertIdentical(null, get_user_preferences('xxx', null, $otheruserid));
     set_user_preference('ooo', true, $user);
     $prefs = get_user_preferences(null, null, $otheruserid);
     $this->assertIdentical($prefs['aaa'], $user->preference['aaa']);
     $this->assertIdentical($prefs['ooo'], $user->preference['ooo']);
     $this->assertIdentical($prefs['ooo'], '1');
     set_user_preference('null', 0, $user);
     $this->assertIdentical('0', get_user_preferences('null', null, $otheruserid));
     $this->assertIdentical('lala', get_user_preferences('undefined', 'lala', $otheruserid));
     $DB->delete_records('user_preferences', array('userid' => $otheruserid));
     set_cache_flag('userpreferenceschanged', $otheruserid, null);
     // test $USER default
     set_user_preference('_test_user_preferences_pref', 'ok');
     $this->assertIdentical('ok', $USER->preference['_test_user_preferences_pref']);
     unset_user_preference('_test_user_preferences_pref');
     $this->assertTrue(!isset($USER->preference['_test_user_preferences_pref']));
     //test invalid params
     try {
         set_user_preference('_test_user_preferences_pref', array());
         $this->assertFail('Exception expected - array not valid preference value');
     } catch (Exception $ex) {
         $this->assertTrue(true);
     }
     try {
         set_user_preference('_test_user_preferences_pref', new stdClass());
         $this->assertFail('Exception expected - class not valid preference value');
     } catch (Exception $ex) {
         $this->assertTrue(true);
     }
     try {
         set_user_preference('_test_user_preferences_pref', 1, array('xx' => 1));
         $this->assertFail('Exception expected - user instance expected');
     } catch (Exception $ex) {
         $this->assertTrue(true);
     }
     try {
         set_user_preference('_test_user_preferences_pref', 1, 'abc');
         $this->assertFail('Exception expected - user instance expected');
     } catch (Exception $ex) {
         $this->assertTrue(true);
     }
     try {
         set_user_preference('', 1);
         $this->assertFail('Exception expected - invalid name accepted');
     } catch (Exception $ex) {
         $this->assertTrue(true);
     }
     try {
         set_user_preference('1', 1);
         $this->assertFail('Exception expected - invalid name accepted');
     } catch (Exception $ex) {
         $this->assertTrue(true);
     }
 }
Ejemplo n.º 8
0
 /**
  * To be called from a page running under NTLM's
  * "Integrated Windows Authentication". 
  *
  * If successful, it will set a special "cookie" (not an HTTP cookie!) 
  * in cache_flags under the "auth/ldap/ntlmsess" "plugin" and return true.
  * The "cookie" will be picked up by ntlmsso_finish() to complete the
  * process.
  *
  * On failure it will return false for the caller to display an appropriate
  * error message (probably saying that Integrated Windows Auth isn't enabled!)
  *
  * NOTE that this code will execute under the OS user credentials, 
  * so we MUST avoid dealing with files -- such as session files.
  * (The caller should set $nomoodlecookie before including config.php)
  *
  */
 function ntlmsso_magic($sesskey)
 {
     if (isset($_SERVER['REMOTE_USER']) && !empty($_SERVER['REMOTE_USER'])) {
         $username = $_SERVER['REMOTE_USER'];
         $username = substr(strrchr($username, '\\'), 1);
         //strip domain info
         $username = moodle_strtolower($username);
         //compatibility hack
         set_cache_flag('auth/ldap/ntlmsess', $sesskey, $username, AUTH_NTLMTIMEOUT);
         return true;
     }
     return false;
 }
Ejemplo n.º 9
0
    public function test_set_user_preference() {
        global $DB, $USER;
        $this->resetAfterTest(true);

        $olduser = $USER;
        $USER = $DB->get_record('user', array('id'=>2)); //admin

        if (!$otheruserid = $this->get_fake_preference_test_userid()) {
            $this->fail('Can not find unused user id for the preferences test');
            return;
        }

        $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
        set_cache_flag('userpreferenceschanged', $otheruserid, null);

        $user = new stdClass();
        $user->id = $otheruserid;

        set_user_preference('aaa', 'bbb', $otheruserid);
        $this->assertEquals('bbb', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'aaa')));
        $this->assertEquals('bbb', get_user_preferences('aaa', null, $otheruserid));

        set_user_preference('xxx', 'yyy', $user);
        $this->assertEquals('yyy', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx')));
        $this->assertEquals('yyy', get_user_preferences('xxx', null, $otheruserid));
        $this->assertTrue(is_array($user->preference));
        $this->assertEquals($user->preference['aaa'], 'bbb');
        $this->assertEquals($user->preference['xxx'], 'yyy');

        set_user_preference('xxx', NULL, $user);
        $this->assertSame(false, $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx')));
        $this->assertSame(null, get_user_preferences('xxx', null, $otheruserid));

        set_user_preference('ooo', true, $user);
        $prefs = get_user_preferences(null, null, $otheruserid);
        $this->assertSame($prefs['aaa'], $user->preference['aaa']);
        $this->assertSame($prefs['ooo'], $user->preference['ooo']);
        $this->assertSame($prefs['ooo'], '1');

        set_user_preference('null', 0, $user);
        $this->assertSame('0', get_user_preferences('null', null, $otheruserid));

        $this->assertSame('lala', get_user_preferences('undefined', 'lala', $otheruserid));

        $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
        set_cache_flag('userpreferenceschanged', $otheruserid, null);

        // test $USER default
        set_user_preference('_test_user_preferences_pref', 'ok');
        $this->assertSame('ok', $USER->preference['_test_user_preferences_pref']);
        unset_user_preference('_test_user_preferences_pref');
        $this->assertTrue(!isset($USER->preference['_test_user_preferences_pref']));

        // Test 1333 char values (no need for unicode, there are already tests for that in DB tests)
        $longvalue = str_repeat('a', 1333);
        set_user_preference('_test_long_user_preference', $longvalue);
        $this->assertEquals($longvalue, get_user_preferences('_test_long_user_preference'));
        $this->assertEquals($longvalue,
            $DB->get_field('user_preferences', 'value', array('userid' => $USER->id, 'name' => '_test_long_user_preference')));

        // Test > 1333 char values, coding_exception expected
        $longvalue = str_repeat('a', 1334);
        try {
            set_user_preference('_test_long_user_preference', $longvalue);
            $this->assertFail('Exception expected - longer than 1333 chars not allowed as preference value');
        } catch (Exception $e) {
            $this->assertTrue($e instanceof coding_exception);
        }

        //test invalid params
        try {
            set_user_preference('_test_user_preferences_pref', array());
            $this->assertFail('Exception expected - array not valid preference value');
        } catch (Exception $ex) {
            $this->assertTrue(true);
        }
        try {
            set_user_preference('_test_user_preferences_pref', new stdClass);
            $this->assertFail('Exception expected - class not valid preference value');
        } catch (Exception $ex) {
            $this->assertTrue(true);
        }
        try {
            set_user_preference('_test_user_preferences_pref', 1, array('xx'=>1));
            $this->assertFail('Exception expected - user instance expected');
        } catch (Exception $ex) {
            $this->assertTrue(true);
        }
        try {
            set_user_preference('_test_user_preferences_pref', 1, 'abc');
            $this->assertFail('Exception expected - user instance expected');
        } catch (Exception $ex) {
            $this->assertTrue(true);
        }
        try {
            set_user_preference('', 1);
            $this->assertFail('Exception expected - invalid name accepted');
        } catch (Exception $ex) {
            $this->assertTrue(true);
        }
        try {
            set_user_preference('1', 1);
            $this->assertFail('Exception expected - invalid name accepted');
        } catch (Exception $ex) {
            $this->assertTrue(true);
        }

        $USER = $olduser;
    }
Ejemplo n.º 10
0
/**
 * Mark a context as dirty (with timestamp)
 * so as to force reloading of the context.
 * @param string $path context path
 */
function mark_context_dirty($path)
{
    global $CFG, $DIRTYCONTEXTS;
    // only if it is a non-empty string
    if (is_string($path) && $path !== '') {
        set_cache_flag('accesslib/dirtycontexts', $path, 1, time() + $CFG->sessiontimeout);
        if (isset($DIRTYCONTEXTS)) {
            $DIRTYCONTEXTS[$path] = 1;
        }
    }
}
 /**
  * Do the job.
  * Throw exceptions on errors (the job will be retried).
  */
 public function execute()
 {
     global $CFG, $DB;
     if (empty($CFG->notifyloginfailures)) {
         return;
     }
     $recip = get_users_from_config($CFG->notifyloginfailures, 'moodle/site:config');
     if (empty($CFG->lastnotifyfailure)) {
         $CFG->lastnotifyfailure = 0;
     }
     // If it has been less than an hour, or if there are no recipients, don't execute.
     if (time() - HOURSECS < $CFG->lastnotifyfailure || !is_array($recip) || count($recip) <= 0) {
         return;
     }
     // We need to deal with the threshold stuff first.
     if (empty($CFG->notifyloginthreshold)) {
         $CFG->notifyloginthreshold = 10;
         // Default to something sensible.
     }
     // Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure
     // and insert them into the cache_flags temp table.
     $logmang = get_log_manager();
     $readers = $logmang->get_readers('\\core\\log\\sql_internal_reader');
     $reader = reset($readers);
     $readername = key($readers);
     if (empty($reader) || empty($readername)) {
         // No readers, no processing.
         return true;
     }
     $logtable = $reader->get_internal_log_table_name();
     $sql = "SELECT ip, COUNT(*)\n                  FROM {" . $logtable . "}\n                 WHERE eventname = ?\n                       AND timecreated > ?\n               GROUP BY ip\n                 HAVING COUNT(*) >= ?";
     $params = array('\\core\\event\\user_login_failed', $CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $iprec) {
         if (!empty($iprec->ip)) {
             set_cache_flag('login_failure_by_ip', $iprec->ip, '1', 0);
         }
     }
     $rs->close();
     // Get all the INFOs with more than notifyloginthreshold failures since lastnotifyfailure
     // and insert them into the cache_flags temp table.
     $sql = "SELECT userid, count(*)\n                  FROM {" . $logtable . "}\n                 WHERE eventname = ?\n                       AND timecreated > ?\n              GROUP BY userid\n                HAVING count(*) >= ?";
     $params = array('\\core\\event\\user_login_failed', $CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $inforec) {
         if (!empty($inforec->info)) {
             set_cache_flag('login_failure_by_id', $inforec->userid, '1', 0);
         }
     }
     $rs->close();
     // Now, select all the login error logged records belonging to the ips and infos
     // since lastnotifyfailure, that we have stored in the cache_flags table.
     $sql = "SELECT * FROM (\n                        SELECT l.*, u.username\n                          FROM {" . $logtable . "} l\n                          JOIN {cache_flags} cf ON l.ip = cf.name\n                     LEFT JOIN {user} u         ON l.userid = u.id\n                         WHERE l.eventname = ?\n                               AND l.timecreated > ?\n                               AND cf.flagtype = 'login_failure_by_ip'\n                    UNION ALL\n                        SELECT l.*, u.username\n                          FROM {" . $logtable . "} l\n                          JOIN {cache_flags} cf ON l.userid = " . $DB->sql_cast_char2int('cf.name') . "\n                     LEFT JOIN {user} u         ON l.userid = u.id\n                         WHERE l.eventname = ?\n                               AND l.timecreated > ?\n                               AND cf.flagtype = 'login_failure_by_info') t\n             ORDER BY t.timecreated DESC";
     $params = array('\\core\\event\\user_login_failed', $CFG->lastnotifyfailure, '\\core\\event\\user_login_failed', $CFG->lastnotifyfailure);
     // Init some variables.
     $count = 0;
     $messages = '';
     // Iterate over the logs recordset.
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $log) {
         $a = new \stdClass();
         $a->time = userdate($log->timecreated);
         if (empty($log->username)) {
             // Entries with no valid username. We get attempted username from the event's other field.
             $other = unserialize($log->other);
             $a->info = empty($other['username']) ? '' : $other['username'];
         } else {
             $a->info = $log->username;
         }
         $a->ip = $log->ip;
         $messages .= get_string('notifyloginfailuresmessage', '', $a) . "\n";
         $count++;
     }
     $rs->close();
     // If we have something useful to report.
     if ($count > 0) {
         $site = get_site();
         $subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname));
         // Calculate the complete body of notification (start + messages + end).
         $params = array('id' => 0, 'modid' => 'site_errors', 'chooselog' => '1', 'logreader' => $readername);
         $url = new \moodle_url('/report/log/index.php', $params);
         $body = get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot) . ($CFG->lastnotifyfailure != 0 ? '(' . userdate($CFG->lastnotifyfailure) . ')' : '') . "\n\n" . $messages . "\n\n" . get_string('notifyloginfailuresmessageend', '', $url->out(false) . ' ') . "\n\n";
         // For each destination, send mail.
         mtrace('Emailing admins about ' . $count . ' failed login attempts');
         foreach ($recip as $admin) {
             // Emailing the admins directly rather than putting these through the messaging system.
             email_to_user($admin, \core_user::get_support_user(), $subject, $body);
         }
     }
     // Update lastnotifyfailure with current time.
     set_config('lastnotifyfailure', time());
     // Finally, delete all the temp records we have created in cache_flags.
     $DB->delete_records_select('cache_flags', "flagtype IN ('login_failure_by_ip', 'login_failure_by_info')");
 }
Ejemplo n.º 12
0
 /**
  * To be called from a page running under NTLM's
  * "Integrated Windows Authentication". 
  *
  * If successful, it will set a special "cookie" (not an HTTP cookie!) 
  * in cache_flags under the "auth/ldap/ntlmsess" "plugin" and return true.
  * The "cookie" will be picked up by ntlmsso_finish() to complete the
  * process.
  *
  * On failure it will return false for the caller to display an appropriate
  * error message (probably saying that Integrated Windows Auth isn't enabled!)
  *
  * NOTE that this code will execute under the OS user credentials, 
  * so we MUST avoid dealing with files -- such as session files.
  * (The caller should set $nomoodlecookie before including config.php)
  *
  */
 function ntlmsso_magic($sesskey)
 {
     if (isset($_SERVER['REMOTE_USER']) && !empty($_SERVER['REMOTE_USER'])) {
         // HTTP __headers__ seem to be sent in ISO-8859-1 encoding
         // (according to my reading of RFC-1945, RFC-2616 and RFC-2617 and
         // my local tests), so we need to convert the REMOTE_USER value
         // (i.e., what we got from the HTTP WWW-Authenticate header) into UTF-8
         $textlib = textlib_get_instance();
         $username = $textlib->convert($_SERVER['REMOTE_USER'], 'iso-8859-1', 'utf-8');
         $username = substr(strrchr($username, '\\'), 1);
         //strip domain info
         $username = moodle_strtolower($username);
         //compatibility hack
         set_cache_flag('auth/ldap/ntlmsess', $sesskey, $username, AUTH_NTLMTIMEOUT);
         return true;
     }
     return false;
 }
Ejemplo n.º 13
0
function mark_context_dirty($path)
{
    global $CFG;
    // only if it is a non-empty string
    if (is_string($path) && $path !== '') {
        set_cache_flag('accesslib/dirtycontexts', $path, 1, time() + $CFG->sessiontimeout);
    }
}
Ejemplo n.º 14
0
/**
 * Notify admin users or admin user of any failed logins (since last notification).
 *
 * Note that this function must be only executed from the cron script
 * It uses the cache_flags system to store temporary records, deleting them
 * by name before finishing
 *
 * @return bool True if executed, false if not
 */
function notify_login_failures()
{
    global $CFG, $DB, $OUTPUT;
    if (empty($CFG->notifyloginfailures)) {
        return false;
    }
    $recip = get_users_from_config($CFG->notifyloginfailures, 'moodle/site:config');
    if (empty($CFG->lastnotifyfailure)) {
        $CFG->lastnotifyfailure = 0;
    }
    // If it has been less than an hour, or if there are no recipients, don't execute.
    if (time() - HOURSECS < $CFG->lastnotifyfailure || !is_array($recip) || count($recip) <= 0) {
        return false;
    }
    // we need to deal with the threshold stuff first.
    if (empty($CFG->notifyloginthreshold)) {
        $CFG->notifyloginthreshold = 10;
        // default to something sensible.
    }
    // Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure
    // and insert them into the cache_flags temp table
    $sql = "SELECT ip, COUNT(*)\n              FROM {log}\n             WHERE module = 'login' AND action = 'error'\n                   AND time > ?\n          GROUP BY ip\n            HAVING COUNT(*) >= ?";
    $params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
    $rs = $DB->get_recordset_sql($sql, $params);
    foreach ($rs as $iprec) {
        if (!empty($iprec->ip)) {
            set_cache_flag('login_failure_by_ip', $iprec->ip, '1', 0);
        }
    }
    $rs->close();
    // Get all the INFOs with more than notifyloginthreshold failures since lastnotifyfailure
    // and insert them into the cache_flags temp table
    $sql = "SELECT info, count(*)\n              FROM {log}\n             WHERE module = 'login' AND action = 'error'\n                   AND time > ?\n          GROUP BY info\n            HAVING count(*) >= ?";
    $params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
    $rs = $DB->get_recordset_sql($sql, $params);
    foreach ($rs as $inforec) {
        if (!empty($inforec->info)) {
            set_cache_flag('login_failure_by_info', $inforec->info, '1', 0);
        }
    }
    $rs->close();
    // Now, select all the login error logged records belonging to the ips and infos
    // since lastnotifyfailure, that we have stored in the cache_flags table
    $sql = "SELECT * FROM (\n        SELECT l.*, u.firstname, u.lastname\n              FROM {log} l\n              JOIN {cache_flags} cf ON l.ip = cf.name\n         LEFT JOIN {user} u         ON l.userid = u.id\n             WHERE l.module = 'login' AND l.action = 'error'\n                   AND l.time > ?\n                   AND cf.flagtype = 'login_failure_by_ip'\n        UNION ALL\n            SELECT l.*, u.firstname, u.lastname\n              FROM {log} l\n              JOIN {cache_flags} cf ON l.info = cf.name\n         LEFT JOIN {user} u         ON l.userid = u.id\n             WHERE l.module = 'login' AND l.action = 'error'\n                   AND l.time > ?\n                   AND cf.flagtype = 'login_failure_by_info') t\n        ORDER BY t.time DESC";
    $params = array($CFG->lastnotifyfailure, $CFG->lastnotifyfailure);
    // Init some variables
    $count = 0;
    $messages = '';
    // Iterate over the logs recordset
    $rs = $DB->get_recordset_sql($sql, $params);
    foreach ($rs as $log) {
        $log->time = userdate($log->time);
        $messages .= get_string('notifyloginfailuresmessage', '', $log) . "\n";
        $count++;
    }
    $rs->close();
    // If we have something useful to report.
    if ($count > 0) {
        $site = get_site();
        $subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname));
        // Calculate the complete body of notification (start + messages + end)
        $body = get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot) . ($CFG->lastnotifyfailure != 0 ? '(' . userdate($CFG->lastnotifyfailure) . ')' : '') . "\n\n" . $messages . "\n\n" . get_string('notifyloginfailuresmessageend', '', $CFG->wwwroot) . "\n\n";
        // For each destination, send mail
        mtrace('Emailing admins about ' . $count . ' failed login attempts');
        foreach ($recip as $admin) {
            //emailing the admins directly rather than putting these through the messaging system
            email_to_user($admin, core_user::get_support_user(), $subject, $body);
        }
    }
    // Update lastnotifyfailure with current time
    set_config('lastnotifyfailure', time());
    // Finally, delete all the temp records we have created in cache_flags
    $DB->delete_records_select('cache_flags', "flagtype IN ('login_failure_by_ip', 'login_failure_by_info')");
    return true;
}
Ejemplo n.º 15
0
 /**
  * Test logging in via LDAP calls a user_loggedin event.
  */
 public function test_ldap_user_loggedin_event()
 {
     global $CFG, $DB, $USER;
     require_once $CFG->dirroot . '/auth/ldap/auth.php';
     $this->resetAfterTest();
     $this->assertFalse(isloggedin());
     $user = $DB->get_record('user', array('username' => 'admin'));
     // Note: we are just going to trigger the function that calls the event,
     // not actually perform a LDAP login, for the sake of sanity.
     $ldap = new auth_plugin_ldap();
     // Set the key for the cache flag we want to set which is used by LDAP.
     set_cache_flag($ldap->pluginconfig . '/ntlmsess', sesskey(), $user->username, AUTH_NTLMTIMEOUT);
     // We are going to need to set the sesskey as the user's password in order for the LDAP log in to work.
     update_internal_user_password($user, sesskey());
     // The function ntlmsso_finish is responsible for triggering the event, so call it directly and catch the event.
     $sink = $this->redirectEvents();
     // We need to supress this function call, or else we will get the message "session_regenerate_id(): Cannot
     // regenerate session id - headers already sent" as the ntlmsso_finish function calls complete_user_login
     @$ldap->ntlmsso_finish();
     $events = $sink->get_events();
     $sink->close();
     // Check that the event is valid.
     $this->assertCount(1, $events);
     $event = reset($events);
     $this->assertInstanceOf('\\core\\event\\user_loggedin', $event);
     $this->assertEquals('user', $event->objecttable);
     $this->assertEquals('2', $event->objectid);
     $this->assertEquals(context_system::instance()->id, $event->contextid);
     $expectedlog = array(SITEID, 'user', 'login', 'view.php?id=' . $USER->id . '&course=' . SITEID, $user->id, 0, $user->id);
     $this->assertEventLegacyLogData($expectedlog, $event);
 }
Ejemplo n.º 16
0
 /**
  * Mark a context as dirty (with timestamp) so as to force reloading of the context.
  */
 public function mark_dirty()
 {
     global $CFG, $USER, $ACCESSLIB_PRIVATE;
     if (during_initial_install()) {
         return;
     }
     // only if it is a non-empty string
     if (is_string($this->_path) && $this->_path !== '') {
         set_cache_flag('accesslib/dirtycontexts', $this->_path, 1, time() + $CFG->sessiontimeout);
         if (isset($ACCESSLIB_PRIVATE->dirtycontexts)) {
             $ACCESSLIB_PRIVATE->dirtycontexts[$this->_path] = 1;
         } else {
             if (CLI_SCRIPT) {
                 $ACCESSLIB_PRIVATE->dirtycontexts = array($this->_path => 1);
             } else {
                 if (isset($USER->access['time'])) {
                     $ACCESSLIB_PRIVATE->dirtycontexts = get_cache_flags('accesslib/dirtycontexts', $USER->access['time'] - 2);
                 } else {
                     $ACCESSLIB_PRIVATE->dirtycontexts = array($this->_path => 1);
                 }
                 // flags not loaded yet, it will be done later in $context->reload_if_dirty()
             }
         }
     }
 }
Ejemplo n.º 17
0
/**
 * Add the trainer info
 */
function add_trainer_info(&$sessions) {
    global $CFG, $DB;

    $moduleid = $DB->get_field('modules', 'id', array('name' => 'facetoface'));
    $alltrainers = array(); // all possible trainers for filter dropdown
    // find role id for trainer
    $trainerroleid = $DB->get_field('role', 'id', array('shortname' => 'facilitator'));

    foreach ($sessions as $session) {
        // individual session trainers
        $sessiontrainers = array();

        // get trainers for this session from session_roles table
        // set to null if trainer role id not found
        $sess_trainers = (isset($trainerroleid)) ? $DB->get_records_select('facetoface_session_roles', "sessionid = ? AND roleid = ?", array($session->sessionid, $trainerroleid)) : null;

        // check if the module instance has already had trainer info added
        if (!array_key_exists($session->cmid, $alltrainers)) {
            $context = context_module::instance($session->cmid);

            if ($sess_trainers && is_array($sess_trainers)) {
                foreach ($sess_trainers as $sess_trainer) {
                    $user = $DB->get_record('user', array('id' => $sess_trainer->userid));
                    $fullname = fullname($user);
                    if (!array_key_exists($fullname, $sessiontrainers)) {
                        $sessiontrainers[$fullname] = $fullname;
                    }
                }
                if (!empty($sessiontrainers)) {
                    asort($sessiontrainers);
                    $session->trainers = $sessiontrainers;
                    $alltrainers[$session->cmid] = $sessiontrainers;
                } else {
                    $session->trainers = '';
                    $alltrainers[$session->cmid] = '';
                }
            }
        } else {
            if (!empty($alltrainers[$session->cmid])) {
                $session->trainers = $alltrainers[$session->cmid];
            } else {
                $session->trainers = '';
            }
        }
    }

    // cache the trainerlist with an expiry of 15 minutes to help speed up the db load
    $cachevalue = serialize($alltrainers);
    $expiry = time() + TRAINER_CACHE_TIMEOUT * 60;
    set_cache_flag('blocks/facetoface', 'trainers', $cachevalue, $expiry);
}