]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
dsdb: Prepare to handle smartcard password rollover
authorAndrew Bartlett <abartlet@samba.org>
Mon, 20 May 2024 01:51:23 +0000 (13:51 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 10 Jun 2024 04:27:30 +0000 (04:27 +0000)
We do this by allowing the password change control to indicate
that the password is to be randomised, bypassing the quality
checks (as true random passwords often fail these) and
re-randomising with the same code as is used for the KDC.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Jo Sutton <josutton@catalyst.net.nz>
source4/dsdb/common/util.c
source4/dsdb/samdb/ldb_modules/password_hash.c
source4/dsdb/samdb/samdb.h
source4/libcli/ldap/ldap_controls.c
source4/setup/schema_samba4.ldif

index 38cd30c47dca4cd35679c4f1b0041df3e6c7a2de..689fbd22a38c4af505aa5b34f5f1519c96d3b1ff 100644 (file)
@@ -2540,6 +2540,16 @@ static NTSTATUS samdb_set_password_request(struct ldb_context *ldb, TALLOC_CTX *
                        talloc_free(req);
                        return NT_STATUS_NO_MEMORY;
                }
+
+       /* a KDC-triggered smart card password rollover (ResetSmartCardAccountPassword) */
+       } else if (old_password_checked == DSDB_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD) {
+               ret = ldb_request_add_control(req,
+                                             DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD,
+                                             true, NULL);
+               if (ret != LDB_SUCCESS) {
+                       talloc_free(req);
+                       return NT_STATUS_NO_MEMORY;
+               }
        }
        if (hash_values) {
                ret = ldb_request_add_control(req,
index bcdf68a221429f8b80e7ad32f11c2d0c45be8252..1d1267624e2c02f6746ce39484e5e93b72c75833 100644 (file)
@@ -135,6 +135,7 @@ struct ph_context {
        bool pwd_last_set_bypass;
        bool pwd_last_set_default;
        bool smartcard_reset;
+       bool kdc_reset_smartcard_account_password;
        const char **userPassword_schemes;
 };
 
@@ -2622,6 +2623,8 @@ static int setup_given_passwords(struct setup_password_fields_io *io,
 static int setup_password_fields(struct setup_password_fields_io *io)
 {
        struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
+       bool prepare_random;
+
        int ret;
 
        ret = setup_last_set_field(io);
@@ -2649,12 +2652,16 @@ static int setup_password_fields(struct setup_password_fields_io *io)
                }
        }
 
+       prepare_random = io->u.is_krbtgt || io->ac->smartcard_reset ||
+                        io->ac->kdc_reset_smartcard_account_password;
+
        /*
-        * Both krbtgt and smartcard reset (on addition of
-        * UF_SMARTCARD_REQUIRED) need random passwords for all
-        * supported keys
+        * krbtgt, smartcard reset (on addition of
+        * UF_SMARTCARD_REQUIRED) and KDC-triggered rollover (for
+        * ResetSmartCardAccountPassword) need random passwords for
+        * all supported keys
         */
-       if (io->u.is_krbtgt || io->ac->smartcard_reset) {
+       if (prepare_random) {
                size_t min = 196;
                size_t max = 255;
                size_t diff = max - min;
@@ -2749,7 +2756,7 @@ static int setup_smartcard_reset(struct setup_password_fields_io *io)
         * to declare this a password update so that the change is
         * made (this ensures that the other rules about updates are
         * skipped in case, which is the setting of
-        * UF_SMARTCARD_REQUIRED on an account
+        * UF_SMARTCARD_REQUIRED on an account)
         */
 
        io->ac->update_password = true;
@@ -2927,6 +2934,11 @@ static int check_password_restrictions(struct setup_password_fields_io *io, WERR
                return ret;
        }
 
+       /* Do not apply restrictions on a KDC-issued rollover (eg ResetSmartCardAccountPassword) */
+       if (io->ac->kdc_reset_smartcard_account_password) {
+               return LDB_SUCCESS;
+       }
+
        /*
         * First check the old password is correct, for password
         * changes when this hasn't already been checked by a
@@ -4189,6 +4201,17 @@ static void ph_apply_controls(struct ph_context *ac)
                /* Mark the "smartcard required" control as uncritical (done) */
                ctrl->critical = false;
        }
+
+       ac->kdc_reset_smartcard_account_password = false;
+       ctrl = ldb_request_get_control(ac->req,
+                               DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD);
+       if (ctrl != NULL) {
+               ac->kdc_reset_smartcard_account_password = true;
+
+               /* Mark KDC running ResetSmartCardAccountPassword control as uncritical (done) */
+               ctrl->critical = false;
+       }
+
 }
 
 static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
index 64135ef704f0247a50de363a8ef7fc5a423923a7..3b62b60c52fa8e6f05c5592f680c69a9debf31ba 100644 (file)
@@ -39,7 +39,15 @@ struct KeyEnvelope;
 enum dsdb_password_checked {
        DSDB_PASSWORD_NOT_CHECKED = 0, /* unused */
        DSDB_PASSWORD_RESET,
-       DSDB_PASSWORD_CHECKED_AND_CORRECT
+       DSDB_PASSWORD_CHECKED_AND_CORRECT,
+       /*
+        * This disables the password rules for this new random
+        * password for ResetSmartCardAccountPassword handling.  This
+        * produces a
+        * DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD
+        * control.
+        */
+       DSDB_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD
 };
 
 #include "lib/util/data_blob.h"
@@ -263,6 +271,11 @@ struct dsdb_control_calculated_default_sd {
 #define DSDB_CONTROL_GMSA_UPDATE_OID "1.3.6.1.4.1.7165.4.3.38"
 /* struct gmsa_update */
 
+/*
+ * KDC is running ResetSmartCardAccountPassword behaviour, the password needs to be made random
+ */
+#define DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD "1.3.6.1.4.1.7165.4.3.39"
+
 #define DSDB_EXTENDED_REPLICATED_OBJECTS_OID "1.3.6.1.4.1.7165.4.4.1"
 struct dsdb_extended_replicated_object {
        struct ldb_message *msg;
index ec0094f6bc0257c4c7a396feab0c9e261f7e9d1e..8d3a40f602e31b3f0bd0ebebaf6dcc152b29dd53 100644 (file)
@@ -1296,6 +1296,7 @@ static const struct ldap_control_handler ldap_known_controls[] = {
        { DSDB_CONTROL_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE_OID, NULL, NULL },
        { DSDB_CONTROL_ACL_READ_OID, NULL, NULL },
        { DSDB_CONTROL_GMSA_UPDATE_OID, NULL, NULL },
+       { DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD, NULL, NULL },
        { DSDB_EXTENDED_SCHEMA_UPGRADE_IN_PROGRESS_OID, NULL, NULL },
        { DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID, NULL, NULL},
        { DSDB_CONTROL_CALCULATED_DEFAULT_SD_OID, NULL, NULL },
index 86907fac1ece1c50e65857c5986d2a3407c66382..ed775af59a8feb40e9847d76fca70a7133123a05 100644 (file)
 #Allocated: DSDB_CONTROL_CALCULATED_DEFAULT_SD_OID 1.3.6.1.4.1.7165.4.3.36
 #Allocated: DSDB_CONTROL_ACL_READ_OID 1.3.6.1.4.1.7165.4.3.37
 #Allocated: DSDB_CONTROL_GMSA_UPDATE_OID 1.3.6.1.4.1.7165.4.3.38
-
+#Allocated: DSDB_CONTROL_PASSWORD_KDC_RESET_SMARTCARD_ACCOUNT_PASSWORD 1.3.6.1.4.1.7165.4.3.39
 
 # Extended 1.3.6.1.4.1.7165.4.4.x
 #Allocated: DSDB_EXTENDED_REPLICATED_OBJECTS_OID 1.3.6.1.4.1.7165.4.4.1