Учетные записи для входа имеют таймер бездействия, установленный на 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 - пользователь', чтобы сбросить время входа в систему.