Пример #1
0
function authenticated_via_ldap_cache($username, $password, &$ldap_displayname)
{
    global $LDAP_options, $auto_tags;
    // Destroy the cache each time config changes.
    if (sha1(serialize($LDAP_options)) != loadScript('LDAPConfigHash')) {
        discardLDAPCache();
        saveScript('LDAPConfigHash', sha1(serialize($LDAP_options)));
    }
    $oldinfo = acquireLDAPCache($username, sha1($password), $LDAP_options['cache_expiry']);
    if ($oldinfo === NULL) {
        // On cache miss execute complete procedure and return the result. In case
        // of successful authentication put a record into cache.
        $newinfo = queryLDAPServer($username, $password);
        if ($newinfo['result'] == 'ACK') {
            $ldap_displayname = $newinfo['displayed_name'];
            foreach ($newinfo['memberof'] as $autotag) {
                $auto_tags[] = array('tag' => $autotag);
            }
            replaceLDAPCacheRecord($username, sha1($password), $newinfo['displayed_name'], $newinfo['memberof']);
            releaseLDAPCache();
            discardLDAPCache($LDAP_options['cache_expiry']);
            return TRUE;
        }
        releaseLDAPCache();
        return FALSE;
    }
    // cache HIT
    // There are two confidence levels of cache hits: "certain" and "uncertain". In either case
    // expect authentication success, unless it's well-timed to perform a retry,
    // which may sometimes bring a NAK decision.
    if ($oldinfo['success_age'] < $LDAP_options['cache_refresh'] or $oldinfo['retry_age'] < $LDAP_options['cache_retry']) {
        releaseLDAPCache();
        $ldap_displayname = $oldinfo['displayed_name'];
        foreach ($oldinfo['memberof'] as $autotag) {
            $auto_tags[] = array('tag' => $autotag);
        }
        return TRUE;
    }
    // Either refresh threshold or retry threshold reached.
    $newinfo = queryLDAPServer($username, $password);
    switch ($newinfo['result']) {
        case 'ACK':
            // refresh existing record
            $ldap_displayname = $newinfo['displayed_name'];
            foreach ($newinfo['memberof'] as $autotag) {
                $auto_tags[] = array('tag' => $autotag);
            }
            replaceLDAPCacheRecord($username, sha1($password), $newinfo['displayed_name'], $newinfo['memberof']);
            releaseLDAPCache();
            discardLDAPCache($LDAP_options['cache_expiry']);
            return TRUE;
        case 'NAK':
            // The record isn't valid any more.
            deleteLDAPCacheRecord($username);
            releaseLDAPCache();
            discardLDAPCache($LDAP_options['cache_expiry']);
            return FALSE;
        case 'CAN':
            // retry failed, do nothing, use old value till next retry
            $ldap_displayname = $oldinfo['displayed_name'];
            foreach ($oldinfo['memberof'] as $autotag) {
                $auto_tags[] = array('tag' => $autotag);
            }
            touchLDAPCacheRecord($username);
            releaseLDAPCache();
            discardLDAPCache($LDAP_options['cache_expiry']);
            return TRUE;
        default:
            throw new RackTablesError('structure error', RackTablesError::INTERNAL);
    }
    // This is never reached.
    return FALSE;
}
Пример #2
0
function replaceLDAPCacheRecord($form_username, $password_hash, $dname, $memberof)
{
    // FIXME: This sequence is able to trigger a deadlock, namely, when executed
    // in parallel from multiple working copies of the same user, which for some
    // reason has no valid record in LDAPCache. Perhaps, using REPLACE INTO can
    // lower the chances of this.
    deleteLDAPCacheRecord($form_username);
    usePreparedInsertBlade('LDAPCache', array('presented_username' => $form_username, 'successful_hash' => $password_hash, 'displayed_name' => $dname, 'memberof' => base64_encode(serialize($memberof))));
}
Пример #3
0
function authenticated_via_ldap_cache($username, $password, &$ldap_displayname)
{
    global $LDAP_options, $auto_tags;
    $user_data = array();
    // fill auto_tags and ldap_displayname from this array
    $password_hash = sha1($password);
    // first try to get cache row without locking it (quick way)
    $cache_row = fetchLDAPCacheRow($username);
    if (isLDAPCacheValid($cache_row, $password_hash, TRUE)) {
        $user_data = $cache_row;
    } else {
        // cache miss or expired. Try to lock LDAPCache for $username
        $cache_row = acquireLDAPCache($username);
        if (isLDAPCacheValid($cache_row, $password_hash, TRUE)) {
            $user_data = $cache_row;
        } else {
            $ldap_answer = queryLDAPServer($username, $password);
            switch ($ldap_answer['result']) {
                case 'ACK':
                    replaceLDAPCacheRecord($username, $password_hash, $ldap_answer['displayed_name'], $ldap_answer['memberof']);
                    $user_data = $ldap_answer;
                    break;
                case 'NAK':
                    // The record isn't valid any more.
                    // TODO: negative result caching
                    deleteLDAPCacheRecord($username);
                    break;
                case 'CAN':
                    // LDAP query failed, use old value till next retry
                    if (isLDAPCacheValid($cache_row, $password_hash, FALSE)) {
                        touchLDAPCacheRecord($username);
                        $user_data = $cache_row;
                    } else {
                        deleteLDAPCacheRecord($username);
                    }
                    break;
                default:
                    throw new RackTablesError('structure error', RackTablesError::INTERNAL);
            }
        }
        releaseLDAPCache();
        discardLDAPCache($LDAP_options['cache_expiry']);
        // clear expired rows of other users
    }
    if ($user_data) {
        $ldap_displayname = $user_data['displayed_name'];
        foreach ($user_data['memberof'] as $autotag) {
            $auto_tags[] = array('tag' => $autotag);
        }
        return TRUE;
    }
    return FALSE;
}