summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bokovoy <ab@samba.org>2018-02-16 18:15:28 +0200
committerStefan Metzmacher <metze@samba.org>2018-09-05 18:44:46 +0200
commitdccaea50ce57d6718ffd937cc8b97b64c98c0e79 (patch)
tree5ab4c0bfc4b52ba467c2ac85939a2c77fd13c7f5
parentb31ba498125995dcb67451e4cb28cc27f9e799ed (diff)
downloadsamba-dccaea50ce57d6718ffd937cc8b97b64c98c0e79.tar.gz
krb5-samba: interdomain trust uses different salt principal
Salt principal for the interdomain trust is krbtgt/DOMAIN@REALM where DOMAIN is the sAMAccountName without the dollar sign ($) The salt principal for the BLA$ user object was generated wrong. dn: CN=bla.base,CN=System,DC=w4edom-l4,DC=base securityIdentifier: S-1-5-21-4053568372-2049667917-3384589010 trustDirection: 3 trustPartner: bla.base trustPosixOffset: -2147483648 trustType: 2 trustAttributes: 8 flatName: BLA dn: CN=BLA$,CN=Users,DC=w4edom-l4,DC=base userAccountControl: 2080 primaryGroupID: 513 objectSid: S-1-5-21-278041429-3399921908-1452754838-1597 accountExpires: 9223372036854775807 sAMAccountName: BLA$ sAMAccountType: 805306370 pwdLastSet: 131485652467995000 The salt stored by Windows in the package_PrimaryKerberosBlob (within supplementalCredentials) seems to be 'W4EDOM-L4.BASEkrbtgtBLA' for the above trust and Samba stores 'W4EDOM-L4.BASEBLA$'. While the salt used when building the keys from trustAuthOutgoing/trustAuthIncoming is 'W4EDOM-L4.BASEkrbtgtBLA.BASE', which we handle correct. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13539 Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Signed-off-by: Alexander Bokovoy <ab@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Wed Sep 5 03:57:22 CEST 2018 on sn-devel-144 (cherry picked from commit f3e349bebc443133fdbe4e14b148ca8db8237060) Autobuild-User(v4-7-test): Stefan Metzmacher <metze@samba.org> Autobuild-Date(v4-7-test): Wed Sep 5 18:44:46 CEST 2018 on sn-devel-144
-rw-r--r--auth/credentials/credentials_krb5.c16
-rw-r--r--lib/krb5_wrap/krb5_samba.c61
-rw-r--r--lib/krb5_wrap/krb5_samba.h2
-rw-r--r--selftest/knownfail.d/trust_user_account1
-rw-r--r--source3/passdb/machine_account_secrets.c3
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c6
6 files changed, 63 insertions, 26 deletions
diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c
index b88497dcace..fb4679747c0 100644
--- a/auth/credentials/credentials_krb5.c
+++ b/auth/credentials/credentials_krb5.c
@@ -34,6 +34,7 @@
#include "auth/kerberos/kerberos_util.h"
#include "auth/kerberos/pac_utils.h"
#include "param/param.h"
+#include "../libds/common/flags.h"
static void cli_credentials_invalidate_client_gss_creds(
struct cli_credentials *cred,
@@ -971,7 +972,7 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
const char *upn = NULL;
const char *realm = cli_credentials_get_realm(cred);
char *salt_principal = NULL;
- bool is_computer = false;
+ uint32_t uac_flags = 0;
if (cred->keytab_obtained >= (MAX(cred->principal_obtained,
cred->username_obtained))) {
@@ -996,9 +997,15 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
switch (cred->secure_channel_type) {
case SEC_CHAN_WKSTA:
- case SEC_CHAN_BDC:
case SEC_CHAN_RODC:
- is_computer = true;
+ 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);
@@ -1006,13 +1013,14 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
TALLOC_FREE(mem_ctx);
return ENOMEM;
}
+ uac_flags = UF_NORMAL_ACCOUNT;
break;
}
ret = smb_krb5_salt_principal(realm,
username, /* sAMAccountName */
upn, /* userPrincipalName */
- is_computer,
+ uac_flags,
mem_ctx,
&salt_principal);
if (ret) {
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c
index 0ba8aaecaea..73e89ea9525 100644
--- a/lib/krb5_wrap/krb5_samba.c
+++ b/lib/krb5_wrap/krb5_samba.c
@@ -24,6 +24,7 @@
#include "system/filesys.h"
#include "krb5_samba.h"
#include "lib/crypto/crypto.h"
+#include "../libds/common/flags.h"
#ifdef HAVE_COM_ERR_H
#include <com_err.h>
@@ -445,8 +446,7 @@ int smb_krb5_get_pw_salt(krb5_context context,
* @param[in] userPrincipalName The userPrincipalName attribute of the object
* or NULL is not available.
*
- * @param[in] is_computer The indication of the object includes
- * objectClass=computer.
+ * @param[in] uac_flags UF_ACCOUNT_TYPE_MASKed userAccountControl field
*
* @param[in] mem_ctx The TALLOC_CTX to allocate _salt_principal.
*
@@ -459,7 +459,7 @@ int smb_krb5_get_pw_salt(krb5_context context,
int smb_krb5_salt_principal(const char *realm,
const char *sAMAccountName,
const char *userPrincipalName,
- bool is_computer,
+ uint32_t uac_flags,
TALLOC_CTX *mem_ctx,
char **_salt_principal)
{
@@ -480,6 +480,23 @@ int smb_krb5_salt_principal(const char *realm,
return EINVAL;
}
+ if (uac_flags & ~UF_ACCOUNT_TYPE_MASK) {
+ /*
+ * catch callers which still
+ * pass 'true'.
+ */
+ TALLOC_FREE(frame);
+ return EINVAL;
+ }
+ if (uac_flags == 0) {
+ /*
+ * catch callers which still
+ * pass 'false'.
+ */
+ TALLOC_FREE(frame);
+ return EINVAL;
+ }
+
upper_realm = strupper_talloc(frame, realm);
if (upper_realm == NULL) {
TALLOC_FREE(frame);
@@ -493,7 +510,7 @@ int smb_krb5_salt_principal(const char *realm,
/*
* Determine a salting principal
*/
- if (is_computer) {
+ if (uac_flags & UF_TRUST_ACCOUNT_MASK) {
int computer_len = 0;
char *tmp = NULL;
@@ -502,20 +519,32 @@ int smb_krb5_salt_principal(const char *realm,
computer_len -= 1;
}
- tmp = talloc_asprintf(frame, "host/%*.*s.%s",
- computer_len, computer_len,
- sAMAccountName, realm);
- if (tmp == NULL) {
- TALLOC_FREE(frame);
- return ENOMEM;
- }
+ if (uac_flags & UF_INTERDOMAIN_TRUST_ACCOUNT) {
+ principal = talloc_asprintf(frame, "krbtgt/%*.*s",
+ computer_len, computer_len,
+ sAMAccountName);
+ if (principal == NULL) {
+ TALLOC_FREE(frame);
+ return ENOMEM;
+ }
+ } else {
- principal = strlower_talloc(frame, tmp);
- TALLOC_FREE(tmp);
- if (principal == NULL) {
- TALLOC_FREE(frame);
- return ENOMEM;
+ tmp = talloc_asprintf(frame, "host/%*.*s.%s",
+ computer_len, computer_len,
+ sAMAccountName, realm);
+ if (tmp == NULL) {
+ TALLOC_FREE(frame);
+ return ENOMEM;
+ }
+
+ principal = strlower_talloc(frame, tmp);
+ TALLOC_FREE(tmp);
+ if (principal == NULL) {
+ TALLOC_FREE(frame);
+ return ENOMEM;
+ }
}
+
principal_len = strlen(principal);
} else if (userPrincipalName != NULL) {
diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h
index 315d3c3492e..8305c1f77af 100644
--- a/lib/krb5_wrap/krb5_samba.h
+++ b/lib/krb5_wrap/krb5_samba.h
@@ -353,7 +353,7 @@ int smb_krb5_get_pw_salt(krb5_context context,
int smb_krb5_salt_principal(const char *realm,
const char *sAMAccountName,
const char *userPrincipalName,
- bool is_computer,
+ uint32_t uac_flags,
TALLOC_CTX *mem_ctx,
char **_salt_principal);
int smb_krb5_salt_principal2data(krb5_context context,
diff --git a/selftest/knownfail.d/trust_user_account b/selftest/knownfail.d/trust_user_account
deleted file mode 100644
index 1de5052b11d..00000000000
--- a/selftest/knownfail.d/trust_user_account
+++ /dev/null
@@ -1 +0,0 @@
-^samba4.blackbox.trust_user_account.get.virtualKerberosSalt.for.TDA
diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index d36fa268a4b..ce435ef3404 100644
--- a/source3/passdb/machine_account_secrets.c
+++ b/source3/passdb/machine_account_secrets.c
@@ -36,6 +36,7 @@
#include "lib/crypto/crypto.h"
#include "lib/krb5_wrap/krb5_samba.h"
#include "lib/util/time_basic.h"
+#include "../libds/common/flags.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
@@ -1600,7 +1601,7 @@ NTSTATUS secrets_store_JoinCtx(const struct libnet_JoinCtx *r)
ret = smb_krb5_salt_principal(info->domain_info.dns_domain.string,
info->account_name,
NULL /* userPrincipalName */,
- true /* is_computer */,
+ UF_WORKSTATION_TRUST_ACCOUNT,
info, &p);
if (ret != 0) {
status = krb5_to_nt_status(ret);
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 3a2582106d3..87784f0ed4c 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -128,7 +128,6 @@ struct setup_password_fields_io {
NTTIME pwdLastSet;
const char *sAMAccountName;
const char *user_principal_name;
- bool is_computer;
bool is_krbtgt;
uint32_t restrictions;
struct dom_sid *account_sid;
@@ -676,15 +675,17 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io)
krb5_data salt;
krb5_keyblock key;
krb5_data cleartext_data;
+ uint32_t uac_flags = 0;
ldb = ldb_module_get_ctx(io->ac->module);
cleartext_data.data = (char *)io->n.cleartext_utf8->data;
cleartext_data.length = io->n.cleartext_utf8->length;
+ uac_flags = io->u.userAccountControl & UF_ACCOUNT_TYPE_MASK;
krb5_ret = smb_krb5_salt_principal(io->ac->status->domain_data.realm,
io->u.sAMAccountName,
io->u.user_principal_name,
- io->u.is_computer,
+ uac_flags,
io->ac,
&salt_principal);
if (krb5_ret) {
@@ -3151,7 +3152,6 @@ static int setup_io(struct ph_context *ac,
"sAMAccountName", NULL);
io->u.user_principal_name = ldb_msg_find_attr_as_string(info_msg,
"userPrincipalName", NULL);
- io->u.is_computer = ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
/* Ensure it has an objectSID too */
io->u.account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");