auth/credentials: Dynamically calculate the salt principal (unless speccified)
authorAndrew Bartlett <abartlet@samba.org>
Wed, 20 Dec 2023 23:00:46 +0000 (12:00 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 14 Mar 2024 22:06:39 +0000 (22:06 +0000)
This helps pull the salt principal calculation into a single spot.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Jo Sutton <josutton@catalyst.net.nz>
auth/credentials/credentials.h
auth/credentials/credentials_krb5.c
auth/credentials/pycredentials.c
source3/winbindd/winbindd_util.c

index 9c11bbd9bcad6daa4167b61749bfcfcab698b759..0464d7a08c856db2761bc2f5e28f5cab69569461 100644 (file)
@@ -262,7 +262,7 @@ void cli_credentials_set_impersonate_principal(struct cli_credentials *cred,
                                               const char *principal,
                                               const char *self_service);
 void cli_credentials_set_target_service(struct cli_credentials *cred, const char *principal);
-const char *cli_credentials_get_salt_principal(struct cli_credentials *cred);
+char *cli_credentials_get_salt_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx);
 const char *cli_credentials_get_impersonate_principal(struct cli_credentials *cred);
 const char *cli_credentials_get_self_service(struct cli_credentials *cred);
 const char *cli_credentials_get_target_service(struct cli_credentials *cred);
index 4e7a1a3b265626672c4a8eda0753b0ace8406da2..3e8d4651b447b1bb4581084458676e0d0de89f26 100644 (file)
@@ -1174,10 +1174,8 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
        krb5_keytab keytab;
        TALLOC_CTX *mem_ctx;
        const char *username = cli_credentials_get_username(cred);
-       const char *upn = NULL;
        const char *realm = cli_credentials_get_realm(cred);
        char *salt_principal = NULL;
-       uint32_t uac_flags = 0;
 
        if (cred->keytab_obtained >= (MAX(cred->principal_obtained,
                                          cred->username_obtained))) {
@@ -1200,37 +1198,10 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
                return ENOMEM;
        }
 
-       switch (cred->secure_channel_type) {
-       case SEC_CHAN_WKSTA:
-       case SEC_CHAN_RODC:
-               uac_flags = UF_WORKSTATION_TRUST_ACCOUNT;
-               break;
-       case SEC_CHAN_BDC:
-               uac_flags = UF_SERVER_TRUST_ACCOUNT;
-               break;
-       case SEC_CHAN_DOMAIN:
-       case SEC_CHAN_DNS_DOMAIN:
-               uac_flags = UF_INTERDOMAIN_TRUST_ACCOUNT;
-               break;
-       default:
-               upn = cli_credentials_get_principal(cred, mem_ctx);
-               if (upn == NULL) {
-                       TALLOC_FREE(mem_ctx);
-                       return ENOMEM;
-               }
-               uac_flags = UF_NORMAL_ACCOUNT;
-               break;
-       }
-
-       ret = smb_krb5_salt_principal_str(realm,
-                                         username, /* sAMAccountName */
-                                         upn, /* userPrincipalName */
-                                         uac_flags,
-                                         mem_ctx,
-                                         &salt_principal);
-       if (ret) {
+       salt_principal = cli_credentials_get_salt_principal(cred, mem_ctx);
+       if (salt_principal == NULL) {
                talloc_free(mem_ctx);
-               return ret;
+               return ENOMEM;
        }
 
        ret = smb_krb5_create_memory_keytab(mem_ctx,
@@ -1412,9 +1383,61 @@ _PUBLIC_ int cli_credentials_get_kvno(struct cli_credentials *cred)
 }
 
 
-const char *cli_credentials_get_salt_principal(struct cli_credentials *cred)
+char *cli_credentials_get_salt_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
 {
-       return cred->salt_principal;
+       TALLOC_CTX *frame = NULL;
+       const char *realm = NULL;
+       const char *username = NULL;
+       uint32_t uac_flags = 0;
+       char *salt_principal = NULL;
+       const char *upn = NULL;
+       int ret;
+
+       /* If specified, use the specified value */
+       if (cred->salt_principal != NULL) {
+               return talloc_strdup(mem_ctx, cred->salt_principal);
+       }
+
+       frame = talloc_stackframe();
+
+       switch (cred->secure_channel_type) {
+       case SEC_CHAN_WKSTA:
+       case SEC_CHAN_RODC:
+               uac_flags = UF_WORKSTATION_TRUST_ACCOUNT;
+               break;
+       case SEC_CHAN_BDC:
+               uac_flags = UF_SERVER_TRUST_ACCOUNT;
+               break;
+       case SEC_CHAN_DOMAIN:
+       case SEC_CHAN_DNS_DOMAIN:
+               uac_flags = UF_INTERDOMAIN_TRUST_ACCOUNT;
+               break;
+       default:
+               upn = cli_credentials_get_principal(cred, frame);
+               if (upn == NULL) {
+                       TALLOC_FREE(frame);
+                       return NULL;
+               }
+               uac_flags = UF_NORMAL_ACCOUNT;
+               break;
+       }
+
+       realm = cli_credentials_get_realm(cred);
+       username = cli_credentials_get_username(cred);
+
+       ret = smb_krb5_salt_principal_str(realm,
+                                         username, /* sAMAccountName */
+                                         upn, /* userPrincipalName */
+                                         uac_flags,
+                                         mem_ctx,
+                                         &salt_principal);
+       if (ret) {
+               TALLOC_FREE(frame);
+               return NULL;
+       }
+
+       TALLOC_FREE(frame);
+       return salt_principal;
 }
 
 _PUBLIC_ void cli_credentials_set_salt_principal(struct cli_credentials *cred, const char *principal)
@@ -1497,18 +1520,23 @@ _PUBLIC_ int cli_credentials_get_aes256_key(struct cli_credentials *cred,
        };
        krb5_keyblock key;
 
+       TALLOC_CTX *frame = talloc_stackframe();
+
        if (cred->password_will_be_nt_hash) {
                DEBUG(1,("cli_credentials_get_aes256_key: cannot generate AES256 key using NT hash\n"));
+               TALLOC_FREE(frame);
                return EINVAL;
        }
 
-       salt = cli_credentials_get_salt_principal(cred);
+       salt = cli_credentials_get_salt_principal(cred, frame);
        if (salt == NULL) {
+               TALLOC_FREE(frame);
                return EINVAL;
        }
 
        password = cli_credentials_get_password(cred);
        if (password == NULL) {
+               TALLOC_FREE(frame);
                return EINVAL;
        }
 
@@ -1518,6 +1546,7 @@ _PUBLIC_ int cli_credentials_get_aes256_key(struct cli_credentials *cred,
        ret = cli_credentials_get_krb5_context(cred, lp_ctx,
                                               &smb_krb5_context);
        if (ret != 0) {
+               TALLOC_FREE(frame);
                return ret;
        }
 
@@ -1539,6 +1568,7 @@ _PUBLIC_ int cli_credentials_get_aes256_key(struct cli_credentials *cred,
                         "generation of a aes256-cts-hmac-sha1-96 key failed: %s\n",
                         smb_get_krb5_error_message(smb_krb5_context->krb5_context,
                                                    krb5_ret, mem_ctx)));
+               TALLOC_FREE(frame);
                return EINVAL;
        }
        *aes_256 = data_blob_talloc(mem_ctx,
@@ -1546,10 +1576,12 @@ _PUBLIC_ int cli_credentials_get_aes256_key(struct cli_credentials *cred,
                                    KRB5_KEY_LENGTH(&key));
        krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &key);
        if (aes_256->data == NULL) {
+               TALLOC_FREE(frame);
                return ENOMEM;
        }
        talloc_keep_secret(aes_256->data);
 
+       TALLOC_FREE(frame);
        return 0;
 }
 
index 6d73a0a2c32de8eafe450e9c29565fd3da178d3e..75cd2909a4cade1a29c8f1a7cffd7ef9446a606c 100644 (file)
@@ -994,12 +994,24 @@ static PyObject *py_creds_set_kerberos_salt_principal(PyObject *self, PyObject *
 
 static PyObject *py_creds_get_kerberos_salt_principal(PyObject *self, PyObject *unused)
 {
+       TALLOC_CTX *mem_ctx;
+       PyObject *ret = NULL;
        struct cli_credentials *creds = PyCredentials_AsCliCredentials(self);
        if (creds == NULL) {
                PyErr_Format(PyExc_TypeError, "Credentials expected");
                return NULL;
        }
-       return PyString_FromStringOrNULL(cli_credentials_get_salt_principal(creds));
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       ret = PyString_FromStringOrNULL(cli_credentials_get_salt_principal(creds, mem_ctx));
+
+       TALLOC_FREE(mem_ctx);
+
+       return ret;
 }
 
 static PyObject *py_creds_get_aes256_key(PyObject *self, PyObject *args)
index 7527a78b30e7e6be756828f4523cff6d0234d186..2234efeed542ec82258b7ccaaf0da0d18c9cd267 100644 (file)
@@ -835,7 +835,7 @@ static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
                   NULL /* oldpass */,
                   cli_credentials_get_domain(creds),
                   cli_credentials_get_realm(creds),
-                  cli_credentials_get_salt_principal(creds),
+                  cli_credentials_get_salt_principal(creds, creds),
                   0, /* Supported enc types, unused */
                   &domain->sid,
                   cli_credentials_get_password_last_changed_time(creds),