Назад | Перейти на главную страницу

Восстановление учетной записи, заблокированной из-за бездействия

Учетные записи для входа имеют таймер бездействия, установленный на 35 дней. То есть в /etc/pam.d/passwd-auth есть строка

auth        required      pam_lastlog.so inactive=35

Я получаю такие строки, как

sshd[29629]: pam_unix(sshd:account): account weaverw has expired (failed to change password)
sshd[29629]: pam_lastlog(sshd:account): user weaverw inactive for 71 days - denied

Вопрос: как лучше всего повторно активировать эти учетные записи? SA выполняет переход к учетной записи, а затем завершает ее работу, поэтому в последнем журнале будет запись, но это кажется неэлегантным.

Чтобы исправить pam_unix срок действия пароля, изменить /etc/shadow. Он имеет формат [поля, разделенные двоеточиями]:

username:passwd:number_of_days_since_pw_changed:...

и обнулить третье поле.


Чтобы исправить pam_lastlog это немного уродливее. Контрольный файл /var/log/lastlog. Это файл сжатого и / или двоичного формата.

Может быть просмотрено с lastlog утилита. Но [AFAICT] утилита не предоставляет механизма для изменения отдельной записи.

Похоже, что рекомендуемый метод - обнулить файл. Хотя это меняет его для всех пользователей, это менее серьезно, чем изменение срока действия пароля. cp /dev/null /var/log/lastlog сделает это, не беспокоя selinux разрешения.

В usermod утилита воля сбросить информацию для не замужем пользователь, но только при использовании -u возможность изменить uid пользователя. Возможно, используется совместно с -o:

usermod -o -u <current_uid_of_user> <username>

В худшем случае, сделайте это двумя командами, сначала установив для uid новый уникальный uid, а затем вернув его к старому. Например, если uid пользователя был 5001 и был нет uid 5500 в использовании, выполните:

usermod -u 5500 fred
usermod -u 5001 fred

если ты действительно хочу сохранить большую часть информации в /var/log/lastlog и вышеуказанное не работает, shadow-utils в исходном пакете есть способ сделать это ...

Вот фрагмент исходного кода от useradd:

static void lastlog_reset (uid_t uid)
{
    struct lastlog ll;
    int fd;
    off_t offset_uid = (off_t) (sizeof ll) * uid;

    if (access (LASTLOG_FILE, F_OK) != 0) {
        return;
    }

    memzero (&ll, sizeof (ll));

    fd = open (LASTLOG_FILE, O_RDWR);
    if (   (-1 == fd)
        || (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
        || (write (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll))
        || (fsync (fd) != 0)
        || (close (fd) != 0)) {
        fprintf (stderr,
                 _("%s: failed to reset the lastlog entry of UID %lu: %s\n"),
                 Prog, (unsigned long) uid, strerror (errno));
        SYSLOG ((LOG_WARN, "failed to reset the lastlog entry of UID %lu", (unsigned long) uid));
        /* continue */
    }
}

Вот отрывок из usermod:

/*
 * update_lastlog - update the lastlog file
 *
 * Relocate the "lastlog" entries for the user. The old entry is
 * left alone in case the UID was shared. It doesn't hurt anything
 * to just leave it be.
 */
static void update_lastlog (void)
{
    struct lastlog ll;
    int fd;
    off_t off_uid = (off_t) user_id * sizeof ll;
    off_t off_newuid = (off_t) user_newid * sizeof ll;

    if (access (LASTLOG_FILE, F_OK) != 0) {
        return;
    }

    fd = open (LASTLOG_FILE, O_RDWR);

    if (-1 == fd) {
        fprintf (stderr,
                 _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
                 Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno));
        return;
    }

    if (   (lseek (fd, off_uid, SEEK_SET) == off_uid)
        && (read (fd, &ll, sizeof ll) == (ssize_t) sizeof ll)) {
        /* Copy the old entry to its new location */
        if (   (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
            || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
            || (fsync (fd) != 0)
            || (close (fd) != 0)) {
            fprintf (stderr,
                     _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
                     Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno));
        }
    } else {
        /* Assume lseek or read failed because there is
         * no entry for the old UID */

        /* Check if the new UID already has an entry */
        if (   (lseek (fd, off_newuid, SEEK_SET) == off_newuid)
            && (read (fd, &ll, sizeof ll) == (ssize_t) sizeof ll)) {
            /* Reset the new uid's lastlog entry */
            memzero (&ll, sizeof (ll));
            if (   (lseek (fd, off_newuid, SEEK_SET) != off_newuid)
                || (write (fd, &ll, sizeof ll) != (ssize_t) sizeof ll)
                || (fsync (fd) != 0)
                || (close (fd) != 0)) {
                fprintf (stderr,
                         _("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
                         Prog, (unsigned long) user_id, (unsigned long) user_newid, strerror (errno));
            }
        } else {
            (void) close (fd);
        }
    }
}

Определение для struct lastlog происходит от #include <lastlog.h> и будет выглядеть так:

/* The structure describing an entry in the database of
   previous logins.  */
struct lastlog
  {
#ifdef __WORDSIZE_TIME64_COMPAT32
    int32_t ll_time;
#else
    __time_t ll_time;
#endif
    char ll_line[UT_LINESIZE];
    char ll_host[UT_HOSTSIZE];
  };

Если вы можете попасть на сервер как другой пользователь, вы можете 'su - пользователь', чтобы сбросить время входа в систему.