1
0
mirror of https://github.com/systemd/systemd synced 2025-12-27 03:14:46 +01:00

Compare commits

...

6 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
a5d815bb7f
Merge pull request #16938 from poettering/homed-rtc-wrong
homed: don't refuse logins when RTC is wrong
2020-09-22 20:51:39 +02:00
Lennart Poettering
a512e330ce homed: in images that lack mkfs.btrfs automatically fall back to ext4
It's better to tweak suboptimal defaults than to just fail with
compiled-in defaults.
2020-09-21 18:02:35 +02:00
Lennart Poettering
f2ba663ea5 homed: show actual file system in messages about file systems 2020-09-21 18:02:35 +02:00
Lennart Poettering
3e0b54867e user-record: don't refuse login when last pw change time is in the future
The RTC is like just off, it's a weird system state, let's continue
without requiring pw change.
2020-09-21 18:02:35 +02:00
Lennart Poettering
61a29a020c homed: ignore ratelimiting counters when timestamp is from future
This likely indicates that the system clock is simply wrong, hence allow
access in this case.

Fixes: #15917
2020-09-21 18:02:35 +02:00
Lennart Poettering
51a95db6dc homed: don't block logins into accounts with future change time
This might happen if the system clock is wrong, and we should allow
access in this case (though certainly log about it).
2020-09-21 18:02:31 +02:00
6 changed files with 65 additions and 20 deletions

View File

@ -1574,7 +1574,7 @@ static int home_may_change_password(
assert(h);
r = user_record_test_password_change_required(h->record);
if (IN_SET(r, -EKEYREVOKED, -EOWNERDEAD, -EKEYEXPIRED))
if (IN_SET(r, -EKEYREVOKED, -EOWNERDEAD, -EKEYEXPIRED, -ESTALE))
return 0; /* expired in some form, but changing is allowed */
if (IN_SET(r, -EKEYREJECTED, -EROFS))
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Expiration settings of account %s do not allow changing of password.", h->user_name);

View File

@ -1885,7 +1885,24 @@ int home_create_luks(
fstype = user_record_file_system_type(h);
if (!supported_fstype(fstype))
return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "Unsupported file system type: %s", h->file_system_type);
return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "Unsupported file system type: %s", fstype);
r = mkfs_exists(fstype);
if (r < 0)
return log_error_errno(r, "Failed to check if mkfs binary for %s exists: %m", fstype);
if (r == 0) {
if (h->file_system_type || streq(fstype, "ext4") || !supported_fstype("ext4"))
return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkfs binary for file system type %s does not exist.", fstype);
/* If the record does not explicitly declare a file system to use, and the compiled-in
* default does not actually exist, than do an automatic fallback onto ext4, as the baseline
* fs of Linux. We won't search for a working fs type here beyond ext4, i.e. nothing fancier
* than a single, conservative fallback to baseline. This should be useful in minimal
* environments where mkfs.btrfs or so are not made available, but mkfs.ext4 as Linux' most
* boring, most basic fs is. */
log_info("Formatting tool for compiled-in default file system %s not available, falling back to ext4 instead.", fstype);
fstype = "ext4";
}
if (sd_id128_is_null(h->partition_uuid)) {
r = sd_id128_randomize(&partition_uuid);
@ -1964,7 +1981,8 @@ int home_create_luks(
host_size = DISK_SIZE_ROUND_DOWN(h->disk_size);
if (!supported_fs_size(fstype, host_size))
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Selected file system size too small for %s.", h->file_system_type);
return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
"Selected file system size too small for %s.", fstype);
/* After creation we should reference this partition by its UUID instead of the block
* device. That's preferable since the user might have specified a device node such as
@ -1997,7 +2015,7 @@ int home_create_luks(
return r;
if (!supported_fs_size(fstype, host_size))
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Selected file system size too small for %s.", h->file_system_type);
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Selected file system size too small for %s.", fstype);
r = tempfn_random(ip, "homework", &temporary_image_path);
if (r < 0)

View File

@ -846,8 +846,8 @@ _public_ PAM_EXTERN int pam_sm_acct_mgmt(
switch (r) {
case -ESTALE:
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "User record is newer than current system time, prohibiting access.");
return PAM_ACCT_EXPIRED;
pam_syslog(handle, LOG_WARNING, "User record for '%s' is newer than current system time, assuming incorrect system clock, allowing access.", ur->user_name);
break;
case -ENOLCK:
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "User record is blocked, prohibiting access.");
@ -904,6 +904,11 @@ _public_ PAM_EXTERN int pam_sm_acct_mgmt(
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Password will expire soon, please change.");
break;
case -ESTALE:
/* If the system clock is wrong, let's log but continue */
pam_syslog(handle, LOG_WARNING, "Couldn't check if password change is required, last change is in the future, system clock likely wrong.");
break;
case -EROFS:
/* All good, just means the password if we wanted to change we couldn't, but we don't need to */
break;

View File

@ -1295,10 +1295,12 @@ int user_record_ratelimit(UserRecord *h) {
usec = now(CLOCK_REALTIME);
if (h->ratelimit_begin_usec != UINT64_MAX && h->ratelimit_begin_usec > usec)
/* Hmm, time is running backwards? Say no! */
return 0;
else if (h->ratelimit_begin_usec == UINT64_MAX ||
if (h->ratelimit_begin_usec != UINT64_MAX && h->ratelimit_begin_usec > usec) {
/* Hmm, start-time is after the current time? If so, the RTC most likely doesn't work. */
new_ratelimit_begin_usec = usec;
new_ratelimit_count = 1;
log_debug("Rate limit timestamp is in the future, assuming incorrect system clock, resetting limit.");
} else if (h->ratelimit_begin_usec == UINT64_MAX ||
usec_add(h->ratelimit_begin_usec, user_record_ratelimit_interval_usec(h)) <= usec) {
/* Fresh start */
new_ratelimit_begin_usec = usec;

View File

@ -45,6 +45,10 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
if (hr->last_change_usec != USEC_INFINITY) {
char buf[FORMAT_TIMESTAMP_MAX];
printf(" Last Change: %s\n", format_timestamp(buf, sizeof(buf), hr->last_change_usec));
if (hr->last_change_usec > now(CLOCK_REALTIME))
printf(" %sModification time lies in the future, system clock wrong?%s\n",
ansi_highlight_yellow(), ansi_normal());
}
if (hr->last_password_change_usec != USEC_INFINITY &&
@ -56,10 +60,6 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
r = user_record_test_blocked(hr);
switch (r) {
case -ESTALE:
printf(" Login OK: %sno%s (last change time is in the future)\n", ansi_highlight_red(), ansi_normal());
break;
case -ENOLCK:
printf(" Login OK: %sno%s (record is locked)\n", ansi_highlight_red(), ansi_normal());
break;
@ -72,10 +72,11 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
printf(" Login OK: %sno%s (record not valid anymore))\n", ansi_highlight_red(), ansi_normal());
break;
case -ESTALE:
default: {
usec_t y;
if (r < 0) {
if (r < 0 && r != -ESTALE) {
errno = -r;
printf(" Login OK: %sno%s (%m)\n", ansi_highlight_red(), ansi_normal());
break;
@ -123,6 +124,10 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
printf(" Password OK: %schange not permitted%s\n", ansi_highlight_yellow(), ansi_normal());
break;
case -ESTALE:
printf(" Password OK: %slast password change in future%s\n", ansi_highlight_yellow(), ansi_normal());
break;
default:
if (r < 0) {
errno = -r;

View File

@ -1919,6 +1919,11 @@ uint64_t user_record_ratelimit_next_try(UserRecord *h) {
h->ratelimit_count == UINT64_MAX)
return UINT64_MAX;
if (h->ratelimit_begin_usec > now(CLOCK_REALTIME)) /* If the ratelimit time is in the future, then
* the local clock is probably incorrect. Let's
* not refuse login then. */
return UINT64_MAX;
if (h->ratelimit_count < user_record_ratelimit_burst(h))
return 0;
@ -2025,19 +2030,20 @@ int user_record_test_blocked(UserRecord *h) {
assert(h);
n = now(CLOCK_REALTIME);
if (h->last_change_usec != UINT64_MAX &&
h->last_change_usec > n) /* Don't allow log ins when the record is from the future */
return -ESTALE;
if (h->locked > 0)
return -ENOLCK;
n = now(CLOCK_REALTIME);
if (h->not_before_usec != UINT64_MAX && n < h->not_before_usec)
return -EL2HLT;
if (h->not_after_usec != UINT64_MAX && n > h->not_after_usec)
return -EL3HLT;
if (h->last_change_usec != UINT64_MAX &&
h->last_change_usec > n) /* Complain during log-ins when the record is from the future */
return -ESTALE;
return 0;
}
@ -2055,6 +2061,7 @@ int user_record_test_password_change_required(UserRecord *h) {
-EKEYEXPIRED: Password is about to expire, warn user
-ENETDOWN: Record has expiration info but no password change timestamp
-EROFS: No password change required nor permitted
-ESTALE: RTC likely incorrect, last password change is in the future
0: No password change required, but permitted
*/
@ -2064,6 +2071,14 @@ int user_record_test_password_change_required(UserRecord *h) {
n = now(CLOCK_REALTIME);
/* Password change in the future? Then our RTC is likely incorrect */
if (h->last_password_change_usec != UINT64_MAX &&
h->last_password_change_usec > n &&
(h->password_change_min_usec != UINT64_MAX ||
h->password_change_max_usec != UINT64_MAX ||
h->password_change_inactive_usec != UINT64_MAX))
return -ESTALE;
/* Then, let's check if password changing is currently allowed at all */
if (h->password_change_min_usec != UINT64_MAX) {