From 6f9281b028ca6a8f392a1c0fff02ba9af5c0072f Mon Sep 17 00:00:00 2001 From: Jo Sutton Date: Fri, 5 Apr 2024 13:23:18 +1300 Subject: [PATCH] s4:dsdb: Set up passwords and password IDs of new gMSAs Signed-off-by: Jo Sutton Reviewed-by: Andrew Bartlett --- selftest/knownfail.d/gmsa | 7 -- .../samba-tool-user-get-kerberos-ticket | 3 - source4/dsdb/samdb/ldb_modules/samldb.c | 98 ++++++++++++++++++++++ 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/selftest/knownfail.d/gmsa b/selftest/knownfail.d/gmsa index 0eabead5a16..31b0c869db7 100644 --- a/selftest/knownfail.d/gmsa +++ b/selftest/knownfail.d/gmsa @@ -1,14 +1,7 @@ ^samba.tests.dckeytab.samba.tests.dckeytab.DCKeytabTests.test_export_keytab_gmsa ^samba.tests.blackbox.gmsa.samba.tests.blackbox.gmsa.GMSABlackboxTest.test_gmsa_password_access -^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_authenticate_to_ldap_with_kerberos\(ad_dc:local\)$ -^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_authenticate_to_ldap_without_kerberos\(ad_dc:local\)$ -^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_perform_as_req_with_aes256\(ad_dc:local\)$ -^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_perform_as_req_with_rc4\(ad_dc:local\)$ -^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_perform_gensec_logon\(ad_dc:local\)$ -^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_perform_netlogon\(ad_dc:local\)$ ^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_retrieved_password\(ad_dc:local\)$ ^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_retrieved_password_allowed\(ad_dc:local\)$ -^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_retrieved_password_denied\(ad_dc:local\)$ ^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_retrieved_password_during_clock_skew_window_when_current_key_is_expired\(ad_dc:local\)$ ^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_retrieved_password_during_clock_skew_window_when_current_key_is_valid\(ad_dc:local\)$ ^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_retrieved_password_during_clock_skew_window_when_next_key_is_expired\(ad_dc:local\)$ diff --git a/selftest/knownfail.d/samba-tool-user-get-kerberos-ticket b/selftest/knownfail.d/samba-tool-user-get-kerberos-ticket index 1be23ead50b..9005d1782fd 100644 --- a/selftest/knownfail.d/samba-tool-user-get-kerberos-ticket +++ b/selftest/knownfail.d/samba-tool-user-get-kerberos-ticket @@ -1,5 +1,2 @@ -# These tests will pass once gMSA support appears -^samba.tests.samba_tool.user_get_kerberos_ticket.samba.tests.samba_tool.user_get_kerberos_ticket.GetKerberosTicketTest.test_gmsa_ticket.ad_dc:local -^samba.tests.samba_tool.user_get_kerberos_ticket.samba.tests.samba_tool.user_get_kerberos_ticket.GetKerberosTicketTest.test_gmsa_ticket.ad_dc_no_ntlm:local # This test could be fixed by reading the AES keys in supplementalCredentials, not just the unicodePwd ^samba.tests.samba_tool.user_get_kerberos_ticket.samba.tests.samba_tool.user_get_kerberos_ticket.GetKerberosTicketTest.test_user_ticket.ad_dc_no_ntlm:local diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 4288cfff446..30f4fddc098 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -32,20 +32,27 @@ */ #include "includes.h" +#include "ldb.h" +#include "ldb_errors.h" #include "libcli/ldap/ldap_ndr.h" #include "ldb_module.h" #include "auth/auth.h" +#include "dsdb/gmsa/util.h" #include "dsdb/samdb/samdb.h" #include "dsdb/samdb/ldb_modules/util.h" #include "dsdb/samdb/ldb_modules/ridalloc.h" #include "libcli/security/security.h" +#include "librpc/gen_ndr/security.h" #include "librpc/gen_ndr/ndr_security.h" #include "ldb_wrap.h" #include "param/param.h" #include "libds/common/flag_mapping.h" #include "system/network.h" #include "librpc/gen_ndr/irpc.h" +#include "lib/crypto/gmsa.h" +#include "lib/util/data_blob.h" #include "lib/util/smb_strtox.h" +#include "lib/util/time.h" #undef strcasecmp @@ -84,6 +91,9 @@ struct samldb_ctx { /* used in "samldb_find_for_defaultObjectCategory" */ struct ldb_dn *dn, *res_dn; + /* the SID to be assigned to the resulting account */ + const struct dom_sid *sid; + /* all the async steps necessary to complete the operation */ struct samldb_step *steps; struct samldb_step *curstep; @@ -1041,6 +1051,8 @@ static int samldb_allocate_sid(struct samldb_ctx *ac) return ldb_operr(ldb); } + ac->sid = sid; + return samldb_next_step(ac); } @@ -1137,6 +1149,85 @@ found: return samldb_next_step(ac); } +static int samldb_gmsa_add(struct samldb_ctx *ac) +{ + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + int ret = LDB_SUCCESS; + NTTIME current_time = 0; + const bool userPassword = dsdb_user_password_support(ac->module, + ac->msg, + ac->req); + bool ok; + + ok = dsdb_gmsa_current_time(ldb, ¤t_time); + if (!ok) { + ret = ldb_operr(ldb); + goto out; + } + + /* Remove any user‐specified passwords. */ + dsdb_remove_password_related_attrs(ac->msg, userPassword); + + /* Remove any user‐specified password IDs. */ + ldb_msg_remove_attr(ac->msg, "msDS-ManagedPasswordId"); + ldb_msg_remove_attr(ac->msg, "msDS-ManagedPasswordPreviousId"); + + { + DATA_BLOB pwd_id_blob = {}; + DATA_BLOB password_blob = {}; + struct gmsa_null_terminated_password *password = NULL; + + /* + * The account must have a SID allocated for us to be able to + * derive its password. + */ + if (ac->sid == NULL) { + ret = ldb_operr(ldb); + goto out; + } + + /* Calculate the password and ID blobs. */ + ret = gmsa_generate_blobs(ldb, + ac->msg, + current_time, + ac->sid, + &pwd_id_blob, + &password); + if (ret) { + goto out; + } + + password_blob = (DATA_BLOB){.data = password->buf, + .length = GMSA_PASSWORD_LEN}; + + /* Add the new password blob. */ + ret = ldb_msg_append_steal_value(ac->msg, + "clearTextPassword", + &password_blob, + 0); + if (ret) { + goto out; + } + + /* Add the new password ID blob. */ + ret = ldb_msg_append_steal_value(ac->msg, + "msDS-ManagedPasswordId", + &pwd_id_blob, + 0); + if (ret) { + goto out; + } + } + + ret = samldb_next_step(ac); + if (ret) { + goto out; + } + +out: + return ret; +} + static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac) { struct ldb_context *ldb = ldb_module_get_ctx(ac->module); @@ -1418,6 +1509,13 @@ static int samldb_fill_object(struct samldb_ctx *ac) if (ret != LDB_SUCCESS) return ret; } + if (dsdb_account_is_gmsa(ldb, ac->msg)) { + ret = samldb_add_step(ac, samldb_gmsa_add); + if (ret != LDB_SUCCESS) { + return ret; + } + } + /* check if we have a valid sAMAccountName */ ret = samldb_add_step(ac, samldb_check_sAMAccountName); if (ret != LDB_SUCCESS) return ret; -- 2.11.4.GIT