[PR PATCH] [Updated] samba-tool domain trust: fix trust compatibility to Windows Server 1709 and FreeIPA

Alexander Bokovoy ab at samba.org
Thu Mar 1 09:41:34 UTC 2018


On to, 01 maalis 2018, Stefan Metzmacher via samba-technical wrote:
> Am 01.03.2018 um 08:54 schrieb Alexander Bokovoy via samba-technical:
> > On to, 01 maalis 2018, Stefan Metzmacher via samba-technical wrote:
> >> Hi Alexander,
> >>
> >>>> As we only use remote_netlogon_info.dc_unc can we
> >>>> add get_netlogon_dc_unc() that falls back to netr_GetDcName()
> >>>> against the remote dc.
> >>>>
> >>>> That would also help if we try to implement trusts against
> >>>> an NT4 style domain.
> >>> Makes sense. Updated patches attached.
> >>
> >> Thanks much better:-)!
> >> Is that tested against FreeIPA?
> > Not yet, in my plans for today as I'm trying to figure out what else we
> > are missing in TDO salt principals.
> 
> The salt principal for the BLA$ user object is 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$'.
Yes, exactly. It doesn't affect Samba AD DC trying to contact Windows AD
DC because KDC advertises salt and Samba always generates the key on the
fly. However, it does affect SSSD on FreeIPA masters because in IPA case
KDC has all keys pregenerated at the time Kerberos principals are
created when trust is added and SSSD uses a keytab to authenticate as
TDO.

I have a patch that passes userAccountControl to
smb_krb5_salt_principal() and it should fix the problem. The patch is
against 4.7.

> trustAuthOutgoing/trustAuthIncoming is
> 'W4EDOM-L4.BASEkrbtgtBLA.BASE', which we handle correct.
Yep. Also pure Kerberos level cross-realm TGT works.

-- 
/ Alexander Bokovoy
-------------- next part --------------
>From b529c960dfb1f2a54dd9b78f6b76a11c4b0a1206 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <ab at samba.org>
Date: Fri, 16 Feb 2018 18:15:28 +0200
Subject: [PATCH] WIP: krb5-samba: interdomain trust uses different salt
 principal

Salt principal for the interdomain trust is krbtgt/DOMAIN at REALM where
DOMAIN is the sAMAccountName without the dollar sign ($)
---
 auth/credentials/credentials_krb5.c            |  9 +++++---
 lib/krb5_wrap/krb5_samba.c                     | 31 ++++++++++++++++----------
 lib/krb5_wrap/krb5_samba.h                     |  2 +-
 source3/passdb/machine_account_secrets.c       |  3 ++-
 source4/dsdb/samdb/ldb_modules/password_hash.c |  5 ++++-
 5 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c
index b88497dcace..fbd4c8a1ca1 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))) {
@@ -998,8 +999,10 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
 	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_DNS_DOMAIN:
+		uac_flags = UF_INTERDOMAIN_TRUST_ACCOUNT;
 	default:
 		upn = cli_credentials_get_principal(cred, mem_ctx);
 		if (upn == NULL) {
@@ -1012,7 +1015,7 @@ _PUBLIC_ int cli_credentials_get_keytab(struct cli_credentials *cred,
 	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 7c461e5c286..285f4ad9abd 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)
 {
@@ -493,7 +493,7 @@ int smb_krb5_salt_principal(const char *realm,
 	/*
 	 * Determine a salting principal
 	 */
-	if (is_computer) {
+	if (uac_flags & UF_MACHINE_ACCOUNT_MASK) {
 		int computer_len = 0;
 		char *tmp = NULL;
 
@@ -502,16 +502,23 @@ 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);
+		} else {
+			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);
 		}
 
-		principal = strlower_talloc(frame, tmp);
-		TALLOC_FREE(tmp);
 		if (principal == NULL) {
 			TALLOC_FREE(frame);
 			return ENOMEM;
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/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index 75f31cb04e2..fb53ee7b9b8 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 /* uac_flags */,
 					      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 96113b542d9..af80b983a29 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -47,6 +47,7 @@
 #include "lib/krb5_wrap/krb5_samba.h"
 #include "auth/common_auth.h"
 #include "lib/messaging/messaging.h"
+#include "../libds/common/flags.h"
 
 #ifdef ENABLE_GPGME
 #undef class
@@ -676,15 +677,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) {
-- 
2.14.3



More information about the samba-technical mailing list