From 7a81ad4b6bf8b986b50edd788d597f77673e9be6 Mon Sep 17 00:00:00 2001 From: dongshengyuan <545258830@qq.com> Date: Thu, 16 Jul 2026 14:44:08 +0800 Subject: [PATCH] creds: reject empty validity intervals Reject credentials whose not-after timestamp is equal to the timestamp at each encryption entry point. Reproducer: systemd-creds --timestamp=TS --not-after=TS encrypt in out Before: encryption succeeded, but decrypt refused the credential as not in order. Follow-up: 21bc0b6fa1de44b520353b935bf14160f9f70591 --- src/creds/creds.c | 6 +++--- src/shared/creds-util.c | 4 ++-- test/units/TEST-54-CREDS.sh | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/creds/creds.c b/src/creds/creds.c index 765185dbe75..d863ed83868 100644 --- a/src/creds/creds.c +++ b/src/creds/creds.c @@ -599,8 +599,8 @@ static int verb_encrypt(int argc, char *argv[], uintptr_t _data, void *userdata) timestamp = arg_timestamp != USEC_INFINITY ? arg_timestamp : now(CLOCK_REALTIME); - if (arg_not_after != USEC_INFINITY && arg_not_after < timestamp) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential is invalidated before it is valid."); + if (arg_not_after != USEC_INFINITY && arg_not_after <= timestamp) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential is invalidated before or when it becomes valid."); if (geteuid() != 0 && !sd_id128_equal(arg_with_key, CRED_AES256_GCM_BY_NULL)) { (void) polkit_agent_open_if_enabled(BUS_TRANSPORT_LOCAL, arg_ask_password); @@ -1257,7 +1257,7 @@ static int vl_method_encrypt(sd_varlink *link, sd_json_variant *parameters, sd_v timestamp_fresh = true; } else timestamp_fresh = timestamp_is_fresh(p.timestamp); - if (p.not_after != UINT64_MAX && p.not_after < p.timestamp) + if (p.not_after != UINT64_MAX && p.not_after <= p.timestamp) return sd_varlink_error_invalid_parameter_name(link, "notAfter"); r = settle_scope(link, &p.scope, &p.uid, &cflags, /* any_scope_after_polkit= */ NULL); diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 09bbf6bca89..bbba1c3eae6 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -900,8 +900,8 @@ int encrypt_credential_and_warn( if (name && !credential_name_valid(name)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid credential name: %s", name); - if (not_after != USEC_INFINITY && timestamp != USEC_INFINITY && not_after < timestamp) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential is invalidated before it is valid (" USEC_FMT " < " USEC_FMT ").", not_after, timestamp); + if (not_after != USEC_INFINITY && timestamp != USEC_INFINITY && not_after <= timestamp) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential is invalidated before or when it becomes valid (" USEC_FMT " <= " USEC_FMT ").", not_after, timestamp); if (DEBUG_LOGGING) { char buf[FORMAT_TIMESTAMP_MAX]; diff --git a/test/units/TEST-54-CREDS.sh b/test/units/TEST-54-CREDS.sh index 7c2774fa103..75d1c41253d 100755 --- a/test/units/TEST-54-CREDS.sh +++ b/test/units/TEST-54-CREDS.sh @@ -167,6 +167,8 @@ systemd-creds --not-after="+1d" encrypt /tmp/cred.orig /tmp/cred.enc systemd-creds decrypt /tmp/cred.enc /tmp/cred.dec diff /tmp/cred.orig /tmp/cred.dec rm -f /tmp/cred.{enc,dec} +ts="$(date -u '+%Y-%m-%d %H:%M:%S UTC')" +(! systemd-creds --with-key=null --timestamp="$ts" --not-after="$ts" encrypt /tmp/cred.orig /tmp/cred.enc) # Null-key credentials and the systemd.credentials_boot_policy= setting. # -- 2.47.3