]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3/rpc_server/samr: fix CID 1509008 - time_t truncation
authorXavi Hernandez <xhernandez@gmail.com>
Thu, 25 Sep 2025 08:42:30 +0000 (10:42 +0200)
committerDouglas Bagnall <dbagnall@samba.org>
Fri, 26 Sep 2025 05:23:30 +0000 (05:23 +0000)
The call to get_time_t_max() doesn't work as expected when time_t is a
64-bits type and the returned value is stored into a 32-bits unsigned
integer. Truncating a 64-bits constant to a 32-bits number won't return,
in general, the same value we would get if time_t were a 32-bits type.
It's unsafe and could even return small numbers very far from the
intended maximum.

This patch completely avoids the need to use get_time_t_max() by
assuming that when pwd_max_age is 0 or -1, it means no maximum age is
defined, so the password never expires and we don't need to do any
comparison.

A small adjustment has also been made to avoid calling
pdb_get_account_policy() if it's not necessary.

Signed-off-by: Xavi Hernandez <xhernandez@gmail.com>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Autobuild-User(master): Douglas Bagnall <dbagnall@samba.org>
Autobuild-Date(master): Fri Sep 26 05:23:30 UTC 2025 on atb-devel-224

source3/rpc_server/samr/srv_samr_util.c

index fa35ce6a5de708895944273d845a855ac0df0022..ebf8b3127bce4f41d9237bad8aab5f738d3f15aa 100644 (file)
@@ -639,24 +639,28 @@ void copy_id21_to_sam_passwd(const char *log_prefix,
                           for example, to clear an autolocked acct.
                           We must check to see if it's expired first. jmcd */
 
-                       uint32_t pwd_max_age = 0;
                        time_t now = time(NULL);
-
-                       pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &pwd_max_age);
-
-                       if (pwd_max_age == (uint32_t)-1 || pwd_max_age == 0) {
-                               pwd_max_age = get_time_t_max();
-                       }
-
-                       stored_time = pdb_get_pass_last_set_time(to);
+                       bool expired = true;
 
                        /* we will only *set* a pwdlastset date when
                           a) the last pwdlastset time was 0 (user was forced to
                              change password).
                           b) the users password has not expired. gd. */
 
-                       if ((stored_time == 0) ||
-                           ((now - stored_time) > pwd_max_age)) {
+                       stored_time = pdb_get_pass_last_set_time(to);
+                       if (stored_time != 0) {
+                               uint32_t pwd_max_age = 0;
+
+                               pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE,
+                                                      &pwd_max_age);
+                               if ((pwd_max_age == (uint32_t)-1) ||
+                                   (pwd_max_age == 0) ||
+                                   (now <= (stored_time + pwd_max_age))) {
+                                       expired = false;
+                               }
+                       }
+
+                       if (expired) {
                                pdb_set_pass_last_set_time(to, now, PDB_CHANGED);
                        }
                }