Blob Blame History Raw
From 881e3b47a17d7d0b3687ef26d782fc3281a8faa3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 29 Nov 2019 13:48:24 +0100
Subject: [PATCH 1/7] s3:libads: prefer ENCTYPE_AES256_CTS_HMAC_SHA1_96 in
 ads_keytab_add_entry()

This is currently not critical as we only use keytabs
only as acceptor, but in future we'll also use them
for kinit() and there we should prefer the newest type.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 source3/libads/kerberos_keytab.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 7d193e1a600..bc35d5edbe4 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -240,11 +240,11 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 	krb5_data password;
 	krb5_kvno kvno;
         krb5_enctype enctypes[6] = {
-#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
-		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-#endif
 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
 		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+#endif
+#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
+		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
 #endif
 		ENCTYPE_ARCFOUR_HMAC,
 		0
-- 
2.24.1


From bc27267b33d989468d7d993e4db2bd9b649bd996 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 16:50:45 +0200
Subject: [PATCH 2/7] Add a test to check dNSHostName with netbios aliases

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/nb_alias_dnshostname |  2 ++
 testprogs/blackbox/test_net_ads.sh        | 14 ++++++++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 selftest/knownfail.d/nb_alias_dnshostname

diff --git a/selftest/knownfail.d/nb_alias_dnshostname b/selftest/knownfail.d/nb_alias_dnshostname
new file mode 100644
index 00000000000..3c14e9931b9
--- /dev/null
+++ b/selftest/knownfail.d/nb_alias_dnshostname
@@ -0,0 +1,2 @@
+^samba4.blackbox.net_ads.nb_alias check dNSHostName
+^samba4.blackbox.net_ads.nb_alias check main SPN
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index 95c0cf76f90..6073ea972f9 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -220,6 +220,20 @@ testit_grep "dns alias addl" $dns_alias2 $VALGRIND $net_tool ads search -P samac
 ##Goodbye...
 testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
 
+# netbios aliases tests
+testit "join nb_alias" $VALGRIND $net_tool --option=netbiosaliases=nb_alias1,nb_alias2 ads join -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
+
+testit "testjoin nb_alias" $VALGRIND $net_tool ads testjoin || failed=`expr $failed + 1`
+
+testit_grep "nb_alias check dNSHostName" $fqdn $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ dNSHostName || failed=`expr $failed + 1`
+testit_grep "nb_alias check main SPN" ${uc_netbios}.${lc_realm} $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1`
+
+testit_grep "nb_alias1 SPN" nb_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1`
+testit_grep "nb_alias2 SPN" nb_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ servicePrincipalName || failed=`expr $failed + 1`
+
+##Goodbye...
+testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
+
 #
 # Test createcomputer option of 'net ads join'
 #
-- 
2.24.1


From f270db1ce1c0c6efc38fc467c8c0c89b13aaa479 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 15:52:46 +0200
Subject: [PATCH 3/7] Fix accidental overwrite of dnsHostName by the last
 netbios alias

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/nb_alias_dnshostname | 2 --
 source3/libnet/libnet_join.c              | 5 +++--
 2 files changed, 3 insertions(+), 4 deletions(-)
 delete mode 100644 selftest/knownfail.d/nb_alias_dnshostname

diff --git a/selftest/knownfail.d/nb_alias_dnshostname b/selftest/knownfail.d/nb_alias_dnshostname
deleted file mode 100644
index 3c14e9931b9..00000000000
--- a/selftest/knownfail.d/nb_alias_dnshostname
+++ /dev/null
@@ -1,2 +0,0 @@
-^samba4.blackbox.net_ads.nb_alias check dNSHostName
-^samba4.blackbox.net_ads.nb_alias check main SPN
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index eb8e0ea17f7..22162186f61 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -507,6 +507,7 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 	ADS_STATUS status;
 	ADS_MODLIST mods;
 	fstring my_fqdn;
+	fstring my_alias;
 	const char **spn_array = NULL;
 	size_t num_spns = 0;
 	char *spn = NULL;
@@ -587,11 +588,11 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 		/*
 		 * Add HOST/netbiosname.domainname
 		 */
-		fstr_sprintf(my_fqdn, "%s.%s",
+		fstr_sprintf(my_alias, "%s.%s",
 			     *netbios_aliases,
 			     lp_dnsdomain());
 
-		spn = talloc_asprintf(frame, "HOST/%s", my_fqdn);
+		spn = talloc_asprintf(frame, "HOST/%s", my_alias);
 		if (spn == NULL) {
 			status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
 			goto done;
-- 
2.24.1


From 3ab241317947fbb6b75060f67c47e57be6fb1459 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 13:25:17 +0200
Subject: [PATCH 4/7] Refactor ads_keytab_add_entry() to make it iterable

so we can more easily add msDS-AdditionalDnsHostName entries.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 source3/libads/kerberos_keytab.c | 197 +++++++++++++++++--------------
 1 file changed, 107 insertions(+), 90 deletions(-)

diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index bc35d5edbe4..c46e98a4270 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -228,18 +228,16 @@ out:
 	return ok;
 }
 
-/**********************************************************************
- Adds a single service principal, i.e. 'host' to the system keytab
-***********************************************************************/
-
-int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
+static int add_kt_entry_etypes(krb5_context context, TALLOC_CTX *tmpctx,
+			       ADS_STRUCT *ads, const char *salt_princ_s,
+			       krb5_keytab keytab, krb5_kvno kvno,
+			       const char *srvPrinc, const char *my_fqdn,
+			       krb5_data *password, bool update_ads)
 {
 	krb5_error_code ret = 0;
-	krb5_context context = NULL;
-	krb5_keytab keytab = NULL;
-	krb5_data password;
-	krb5_kvno kvno;
-        krb5_enctype enctypes[6] = {
+	char *princ_s = NULL;
+	char *short_princ_s = NULL;
+	krb5_enctype enctypes[4] = {
 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
 		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
 #endif
@@ -249,65 +247,7 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 		ENCTYPE_ARCFOUR_HMAC,
 		0
 	};
-	char *princ_s = NULL;
-	char *short_princ_s = NULL;
-	char *salt_princ_s = NULL;
-	char *password_s = NULL;
-	char *my_fqdn;
-	TALLOC_CTX *tmpctx = NULL;
-	int i;
-
-	ret = smb_krb5_init_context_common(&context);
-	if (ret) {
-		DBG_ERR("kerberos init context failed (%s)\n",
-			error_message(ret));
-		return -1;
-	}
-
-	ret = ads_keytab_open(context, &keytab);
-	if (ret != 0) {
-		goto out;
-	}
-
-	/* retrieve the password */
-	if (!secrets_init()) {
-		DEBUG(1, (__location__ ": secrets_init failed\n"));
-		ret = -1;
-		goto out;
-	}
-	password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-	if (!password_s) {
-		DEBUG(1, (__location__ ": failed to fetch machine password\n"));
-		ret = -1;
-		goto out;
-	}
-	ZERO_STRUCT(password);
-	password.data = password_s;
-	password.length = strlen(password_s);
-
-	/* we need the dNSHostName value here */
-	tmpctx = talloc_init(__location__);
-	if (!tmpctx) {
-		DEBUG(0, (__location__ ": talloc_init() failed!\n"));
-		ret = -1;
-		goto out;
-	}
-
-	my_fqdn = ads_get_dnshostname(ads, tmpctx, lp_netbios_name());
-	if (!my_fqdn) {
-		DEBUG(0, (__location__ ": unable to determine machine "
-			  "account's dns name in AD!\n"));
-		ret = -1;
-		goto out;
-	}
-
-	/* make sure we have a single instance of a the computer account */
-	if (!ads_has_samaccountname(ads, tmpctx, lp_netbios_name())) {
-		DEBUG(0, (__location__ ": unable to determine machine "
-			  "account's short name in AD!\n"));
-		ret = -1;
-		goto out;
-	}
+	size_t i;
 
 	/* Construct our principal */
 	if (strchr_m(srvPrinc, '@')) {
@@ -356,22 +296,6 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 		}
 	}
 
-	kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name());
-	if (kvno == -1) {
-		/* -1 indicates failure, everything else is OK */
-		DEBUG(1, (__location__ ": ads_get_machine_kvno failed to "
-			 "determine the system's kvno.\n"));
-		ret = -1;
-		goto out;
-	}
-
-	salt_princ_s = kerberos_secrets_fetch_salt_princ();
-	if (salt_princ_s == NULL) {
-		DBG_WARNING("kerberos_secrets_fetch_salt_princ() failed\n");
-		ret = -1;
-		goto out;
-	}
-
 	for (i = 0; enctypes[i]; i++) {
 
 		/* add the fqdn principal to the keytab */
@@ -381,11 +305,11 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 					    princ_s,
 					    salt_princ_s,
 					    enctypes[i],
-					    &password,
+					    password,
 					    false,
 					    false);
 		if (ret) {
-			DEBUG(1, (__location__ ": Failed to add entry to keytab\n"));
+			DBG_WARNING("Failed to add entry to keytab\n");
 			goto out;
 		}
 
@@ -397,16 +321,109 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 						    short_princ_s,
 						    salt_princ_s,
 						    enctypes[i],
-						    &password,
+						    password,
 						    false,
 						    false);
 			if (ret) {
-				DEBUG(1, (__location__
-					  ": Failed to add short entry to keytab\n"));
+				DBG_WARNING("Failed to add short entry to keytab\n");
 				goto out;
 			}
 		}
 	}
+out:
+	return ret;
+}
+
+/**********************************************************************
+ Adds a single service principal, i.e. 'host' to the system keytab
+***********************************************************************/
+
+int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
+{
+	krb5_error_code ret = 0;
+	krb5_context context = NULL;
+	krb5_keytab keytab = NULL;
+	krb5_data password;
+	krb5_kvno kvno;
+	char *salt_princ_s = NULL;
+	char *password_s = NULL;
+	char *my_fqdn;
+	TALLOC_CTX *tmpctx = NULL;
+
+	ret = smb_krb5_init_context_common(&context);
+	if (ret) {
+		DBG_ERR("kerberos init context failed (%s)\n",
+			error_message(ret));
+		return -1;
+	}
+
+	ret = ads_keytab_open(context, &keytab);
+	if (ret != 0) {
+		goto out;
+	}
+
+	/* retrieve the password */
+	if (!secrets_init()) {
+		DBG_WARNING("secrets_init failed\n");
+		ret = -1;
+		goto out;
+	}
+	password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
+	if (!password_s) {
+		DBG_WARNING("failed to fetch machine password\n");
+		ret = -1;
+		goto out;
+	}
+	ZERO_STRUCT(password);
+	password.data = password_s;
+	password.length = strlen(password_s);
+
+	/* we need the dNSHostName value here */
+	tmpctx = talloc_init(__location__);
+	if (!tmpctx) {
+		DBG_ERR("talloc_init() failed!\n");
+		ret = -1;
+		goto out;
+	}
+
+	my_fqdn = ads_get_dnshostname(ads, tmpctx, lp_netbios_name());
+	if (!my_fqdn) {
+		DBG_ERR("unable to determine machine account's dns name in "
+			"AD!\n");
+		ret = -1;
+		goto out;
+	}
+
+	/* make sure we have a single instance of a the computer account */
+	if (!ads_has_samaccountname(ads, tmpctx, lp_netbios_name())) {
+		DBG_ERR("unable to determine machine account's short name in "
+			"AD!\n");
+		ret = -1;
+		goto out;
+	}
+
+	kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name());
+	if (kvno == -1) {
+		/* -1 indicates failure, everything else is OK */
+		DBG_WARNING("ads_get_machine_kvno failed to determine the "
+			    "system's kvno.\n");
+		ret = -1;
+		goto out;
+	}
+
+	salt_princ_s = kerberos_secrets_fetch_salt_princ();
+	if (salt_princ_s == NULL) {
+		DBG_WARNING("kerberos_secrets_fetch_salt_princ() failed\n");
+		ret = -1;
+		goto out;
+	}
+
+	ret = add_kt_entry_etypes(context, tmpctx, ads, salt_princ_s, keytab,
+				  kvno, srvPrinc, my_fqdn, &password,
+				  update_ads);
+	if (ret != 0) {
+		goto out;
+	}
 
 out:
 	SAFE_FREE(salt_princ_s);
-- 
2.24.1


From 42936021a1af2214b7a43f56f67d4c130fdde080 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 17:55:12 +0200
Subject: [PATCH 5/7] Add a test for msDS-AdditionalDnsHostName entries in
 keytab

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/dns_alias_keytab | 2 ++
 testprogs/blackbox/test_net_ads.sh    | 9 +++++++++
 2 files changed, 11 insertions(+)
 create mode 100644 selftest/knownfail.d/dns_alias_keytab

diff --git a/selftest/knownfail.d/dns_alias_keytab b/selftest/knownfail.d/dns_alias_keytab
new file mode 100644
index 00000000000..216592e1210
--- /dev/null
+++ b/selftest/knownfail.d/dns_alias_keytab
@@ -0,0 +1,2 @@
+^samba4.blackbox.net_ads.dns alias1 check keytab
+^samba4.blackbox.net_ads.dns alias2 check keytab
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index 6073ea972f9..a40b477a173 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -217,6 +217,15 @@ testit_grep "dns alias SPN" $dns_alias2 $VALGRIND $net_tool ads search -P samacc
 testit_grep "dns alias addl" $dns_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 testit_grep "dns alias addl" $dns_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 
+dedicated_keytab_file="$PREFIX_ABS/test_dns_aliases_dedicated_krb5.keytab"
+
+testit "dns alias create_keytab" $VALGRIND $net_tool ads keytab create --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+testit_grep "dns alias1 check keytab" "host/${dns_alias1}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+testit_grep "dns alias2 check keytab" "host/${dns_alias2}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+rm -f $dedicated_keytab_file
+
 ##Goodbye...
 testit "leave" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
 
-- 
2.24.1


From f45843d11260e10c88bea1d21314093c77ff07a0 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 15:36:28 +0200
Subject: [PATCH 6/7] Add msDS-AdditionalDnsHostName entries to the keytab

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/dns_alias_keytab |  2 --
 source3/libads/ads_proto.h            |  5 +++
 source3/libads/kerberos_keytab.c      | 21 +++++++++++++
 source3/libads/ldap.c                 | 45 +++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 2 deletions(-)
 delete mode 100644 selftest/knownfail.d/dns_alias_keytab

diff --git a/selftest/knownfail.d/dns_alias_keytab b/selftest/knownfail.d/dns_alias_keytab
deleted file mode 100644
index 216592e1210..00000000000
--- a/selftest/knownfail.d/dns_alias_keytab
+++ /dev/null
@@ -1,2 +0,0 @@
-^samba4.blackbox.net_ads.dns alias1 check keytab
-^samba4.blackbox.net_ads.dns alias2 check keytab
diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h
index 495ef5d3325..cd9c1082681 100644
--- a/source3/libads/ads_proto.h
+++ b/source3/libads/ads_proto.h
@@ -137,6 +137,11 @@ ADS_STATUS ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
 					enum ads_extended_dn_flags flags,
 					struct dom_sid *sid);
 char* ads_get_dnshostname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name );
+ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
+                                            ADS_STRUCT *ads,
+                                            const char *machine_name,
+                                            char ***hostnames_array,
+                                            size_t *num_hostnames);
 char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name );
 bool ads_has_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name );
 ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index c46e98a4270..da363741d10 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -349,6 +349,8 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 	char *password_s = NULL;
 	char *my_fqdn;
 	TALLOC_CTX *tmpctx = NULL;
+	char **hostnames_array = NULL;
+	size_t num_hostnames = 0;
 
 	ret = smb_krb5_init_context_common(&context);
 	if (ret) {
@@ -425,6 +427,25 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads)
 		goto out;
 	}
 
+	if (ADS_ERR_OK(ads_get_additional_dns_hostnames(tmpctx, ads,
+							lp_netbios_name(),
+							&hostnames_array,
+							&num_hostnames))) {
+		size_t i;
+
+		for (i = 0; i < num_hostnames; i++) {
+
+			ret = add_kt_entry_etypes(context, tmpctx, ads,
+						  salt_princ_s, keytab,
+						  kvno, srvPrinc,
+						  hostnames_array[i],
+						  &password, update_ads);
+			if (ret != 0) {
+				goto out;
+			}
+		}
+	}
+
 out:
 	SAFE_FREE(salt_princ_s);
 	TALLOC_FREE(tmpctx);
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index f0fcf9fcd56..f6fde5e19e1 100755
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1377,6 +1377,7 @@ char *ads_parent_dn(const char *dn)
 		"unicodePwd",
 
 		/* Additional attributes Samba checks */
+		"msDS-AdditionalDnsHostName",
 		"msDS-SupportedEncryptionTypes",
 		"nTSecurityDescriptor",
 
@@ -3668,6 +3669,50 @@ out:
 /********************************************************************
 ********************************************************************/
 
+ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
+					    ADS_STRUCT *ads,
+					    const char *machine_name,
+					    char ***hostnames_array,
+					    size_t *num_hostnames)
+{
+	ADS_STATUS status;
+	LDAPMessage *res = NULL;
+	int count;
+
+	status = ads_find_machine_acct(ads,
+				       &res,
+				       machine_name);
+	if (!ADS_ERR_OK(status)) {
+		DEBUG(1,("Host Account for %s not found... skipping operation.\n",
+			 machine_name));
+		return status;
+	}
+
+	count = ads_count_replies(ads, res);
+	if (count != 1) {
+		status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+		goto done;
+	}
+
+	*hostnames_array = ads_pull_strings(ads, mem_ctx, res,
+					    "msDS-AdditionalDnsHostName",
+					    num_hostnames);
+	if (*hostnames_array == NULL) {
+		DEBUG(1, ("Host account for %s does not have msDS-AdditionalDnsHostName.\n",
+			  machine_name));
+		status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+		goto done;
+	}
+
+done:
+	ads_msgfree(ads, res);
+
+	return status;
+}
+
+/********************************************************************
+********************************************************************/
+
 char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name )
 {
 	LDAPMessage *res = NULL;
-- 
2.24.1


From f039d0ae9f1a2f110d1b73dc4ee41aa030efe06e Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Wed, 27 May 2020 15:54:12 +0200
Subject: [PATCH 7/7] Add net-ads-join dnshostname=fqdn option

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14396

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Fri May 29 13:33:28 UTC 2020 on sn-devel-184
---
 docs-xml/manpages/net.8.xml        |  7 ++++++-
 source3/libnet/libnet_join.c       |  7 ++++++-
 source3/librpc/idl/libnet_join.idl |  1 +
 source3/utils/net_ads.c            |  9 ++++++++-
 testprogs/blackbox/test_net_ads.sh | 15 +++++++++++++++
 5 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index 37dd30b7864..cbab9c63a5e 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -481,7 +481,7 @@ The remote server must be specified with the -S option.
 
 <refsect2>
 <title>[RPC|ADS] JOIN [TYPE] [--no-dns-updates] [-U username[%password]]
-[createupn=UPN] [createcomputer=OU] [machinepass=PASS]
+[dnshostname=FQDN] [createupn=UPN] [createcomputer=OU] [machinepass=PASS]
 [osName=string osVer=string] [options]</title>
 
 <para>
@@ -496,6 +496,11 @@ be created.</para>
 joining the domain.
 </para>
 
+<para>
+[FQDN] (ADS only) set the dnsHosName attribute during the join.
+The default format is netbiosname.dnsdomain.
+</para>
+
 <para>
 [UPN] (ADS only) set the principalname attribute during the join.  The default
 format is host/netbiosname@REALM.
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index 22162186f61..a087587bba7 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -546,7 +546,12 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
 		goto done;
 	}
 
-	fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name, lp_dnsdomain());
+	if (r->in.dnshostname != NULL) {
+		fstr_sprintf(my_fqdn, "%s", r->in.dnshostname);
+	} else {
+		fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name,
+			     lp_dnsdomain());
+	}
 
 	if (!strlower_m(my_fqdn)) {
 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
diff --git a/source3/librpc/idl/libnet_join.idl b/source3/librpc/idl/libnet_join.idl
index e45034d40da..03d919863b5 100644
--- a/source3/librpc/idl/libnet_join.idl
+++ b/source3/librpc/idl/libnet_join.idl
@@ -37,6 +37,7 @@ interface libnetjoin
 		[in] string os_servicepack,
 		[in] boolean8 create_upn,
 		[in] string upn,
+		[in] string dnshostname,
 		[in] boolean8 modify_config,
 		[in,unique] ads_struct *ads,
 		[in] boolean8 debug,
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 95a6ed74b78..dd3c650be8b 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -1710,6 +1710,8 @@ static int net_ads_join_usage(struct net_context *c, int argc, const char **argv
 {
 	d_printf(_("net ads join [--no-dns-updates] [options]\n"
 	           "Valid options:\n"));
+	d_printf(_("   dnshostname=FQDN      Set the dnsHostName attribute during the join.\n"
+		   "                         The default is in the form netbiosname.dnsdomain\n"));
 	d_printf(_("   createupn[=UPN]       Set the userPrincipalName attribute during the join.\n"
 		   "                         The default UPN is in the form host/netbiosname@REALM.\n"));
 	d_printf(_("   createcomputer=OU     Precreate the computer account in a specific OU.\n"
@@ -1830,6 +1832,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 	const char *domain = lp_realm();
 	WERROR werr = WERR_NERR_SETUPNOTJOINED;
 	bool createupn = false;
+	const char *dnshostname = NULL;
 	const char *machineupn = NULL;
 	const char *machine_password = NULL;
 	const char *create_in_ou = NULL;
@@ -1870,7 +1873,10 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 	/* process additional command line args */
 
 	for ( i=0; i<argc; i++ ) {
-		if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
+		if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
+			dnshostname = get_string_param(argv[i]);
+		}
+		else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
 			createupn = true;
 			machineupn = get_string_param(argv[i]);
 		}
@@ -1938,6 +1944,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 	r->in.domain_name_type	= domain_name_type;
 	r->in.create_upn	= createupn;
 	r->in.upn		= machineupn;
+	r->in.dnshostname	= dnshostname;
 	r->in.account_ou	= create_in_ou;
 	r->in.os_name		= os_name;
 	r->in.os_version	= os_version;
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index a40b477a173..85257f445d8 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -277,6 +277,21 @@ rm -f $dedicated_keytab_file
 
 testit "leave+createupn" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
 
+#
+# Test dnshostname option of 'net ads join'
+#
+testit "join+dnshostname" $VALGRIND $net_tool ads join -U$DC_USERNAME%$DC_PASSWORD dnshostname="alt.hostname.$HOSTNAME" || failed=`expr $failed + 1`
+
+testit_grep "check dnshostname opt" "dNSHostName: alt.hostname.$HOSTNAME" $ldbsearch -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM -s base -b "CN=$HOSTNAME,CN=Computers,$base_dn" || failed=`expr $failed + 1`
+
+testit "create_keytab+dnshostname" $VALGRIND $net_tool ads keytab create --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+testit_grep "check dnshostname+keytab" "host/alt.hostname.$HOSTNAME@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+
+rm -f $dedicated_keytab_file
+
+testit "leave+dnshostname" $VALGRIND $net_tool ads leave -U$DC_USERNAME%$DC_PASSWORD || failed=`expr $failed + 1`
+
 rm -rf $BASEDIR/$WORKDIR
 
 exit $failed
-- 
2.24.1

From e5fde8987d365631c5c8b5efc1f5d1a0fc73861d Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Thu, 11 Jun 2020 21:05:07 +0300
Subject: [PATCH 1/4] Fix a typo in recent net man page changes

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 docs-xml/manpages/net.8.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index cbab9c63a5e..951ddcd7c3a 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -497,7 +497,7 @@ joining the domain.
 </para>
 
 <para>
-[FQDN] (ADS only) set the dnsHosName attribute during the join.
+[FQDN] (ADS only) set the dnsHostName attribute during the join.
 The default format is netbiosname.dnsdomain.
 </para>
 
-- 
2.25.4


From 626fe6a01845692b652fb3ae2119d9defbc6f173 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Tue, 16 Jun 2020 22:01:49 +0300
Subject: [PATCH 2/4] selftest: add tests for binary msDS-AdditionalDnsHostName

Like the short names added implicitly by Windows DC.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/binary_addl_hostname |  3 +++
 testprogs/blackbox/test_net_ads.sh        | 22 ++++++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 selftest/knownfail.d/binary_addl_hostname

diff --git a/selftest/knownfail.d/binary_addl_hostname b/selftest/knownfail.d/binary_addl_hostname
new file mode 100644
index 00000000000..559db1df507
--- /dev/null
+++ b/selftest/knownfail.d/binary_addl_hostname
@@ -0,0 +1,3 @@
+^samba4.blackbox.net_ads.dns alias1 check keytab
+^samba4.blackbox.net_ads.dns alias2 check keytab
+^samba4.blackbox.net_ads.addl short check keytab
diff --git a/testprogs/blackbox/test_net_ads.sh b/testprogs/blackbox/test_net_ads.sh
index 85257f445d8..eef4a31a6a7 100755
--- a/testprogs/blackbox/test_net_ads.sh
+++ b/testprogs/blackbox/test_net_ads.sh
@@ -41,6 +41,11 @@ if [ -x "$BINDIR/ldbdel" ]; then
 	ldbdel="$BINDIR/ldbdel"
 fi
 
+ldbmodify="ldbmodify"
+if [ -x "$BINDIR/ldbmodify" ]; then
+	ldbmodify="$BINDIR/ldbmodify"
+fi
+
 # Load test functions
 . `dirname $0`/subunit.sh
 
@@ -217,12 +222,29 @@ testit_grep "dns alias SPN" $dns_alias2 $VALGRIND $net_tool ads search -P samacc
 testit_grep "dns alias addl" $dns_alias1 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 testit_grep "dns alias addl" $dns_alias2 $VALGRIND $net_tool ads search -P samaccountname=$netbios\$ msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
 
+# Test binary msDS-AdditionalDnsHostName like ones added by Windows DC
+short_alias_file="$PREFIX_ABS/short_alias_file"
+printf 'short_alias\0$' > $short_alias_file
+cat > $PREFIX_ABS/tmpldbmodify <<EOF
+dn: CN=$HOSTNAME,$computers_dn
+changetype: modify
+add: msDS-AdditionalDnsHostName
+msDS-AdditionalDnsHostName:< file://$short_alias_file
+EOF
+
+testit "add binary msDS-AdditionalDnsHostName" $VALGRIND $ldbmodify -k yes -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM $PREFIX_ABS/tmpldbmodify || failed=`expr $failed + 1`
+
+testit_grep "addl short alias" short_alias $ldbsearch --show-binary -U$DC_USERNAME%$DC_PASSWORD -H ldap://$SERVER.$REALM -s base -b "CN=$HOSTNAME,CN=Computers,$base_dn" msDS-AdditionalDnsHostName || failed=`expr $failed + 1`
+
+rm -f $PREFIX_ABS/tmpldbmodify $short_alias_file
+
 dedicated_keytab_file="$PREFIX_ABS/test_dns_aliases_dedicated_krb5.keytab"
 
 testit "dns alias create_keytab" $VALGRIND $net_tool ads keytab create --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
 
 testit_grep "dns alias1 check keytab" "host/${dns_alias1}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
 testit_grep "dns alias2 check keytab" "host/${dns_alias2}@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
+testit_grep "addl short check keytab" "host/short_alias@$REALM" $net_tool ads keytab list --option="kerberosmethod=dedicatedkeytab" --option="dedicatedkeytabfile=$dedicated_keytab_file" || failed=`expr $failed + 1`
 
 rm -f $dedicated_keytab_file
 
-- 
2.25.4


From f28264208b50507c7dc0605b5ad3084ffe9e1785 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Thu, 11 Jun 2020 16:51:27 +0300
Subject: [PATCH 3/4] Properly handle msDS-AdditionalDnsHostName returned from
 Windows DC

Windows DC adds short names for each specified msDS-AdditionalDnsHostName
attribute, but these have a suffix of "\0$" and thus fail with
ldap_get_values(), use ldap_get_values_len() instead.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
 selftest/knownfail.d/binary_addl_hostname |  3 --
 source3/libads/ldap.c                     | 38 +++++++++++++++++++++--
 2 files changed, 35 insertions(+), 6 deletions(-)
 delete mode 100644 selftest/knownfail.d/binary_addl_hostname

diff --git a/selftest/knownfail.d/binary_addl_hostname b/selftest/knownfail.d/binary_addl_hostname
deleted file mode 100644
index 559db1df507..00000000000
--- a/selftest/knownfail.d/binary_addl_hostname
+++ /dev/null
@@ -1,3 +0,0 @@
-^samba4.blackbox.net_ads.dns alias1 check keytab
-^samba4.blackbox.net_ads.dns alias2 check keytab
-^samba4.blackbox.net_ads.addl short check keytab
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index f6fde5e19e1..ed52d4a969e 100755
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -3669,6 +3669,40 @@ out:
 /********************************************************************
 ********************************************************************/
 
+static char **get_addl_hosts(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+			      LDAPMessage *msg, size_t *num_values)
+{
+	const char *field = "msDS-AdditionalDnsHostName";
+	struct berval **values = NULL;
+	char **ret = NULL;
+	size_t i, converted_size;
+
+	values = ldap_get_values_len(ads->ldap.ld, msg, field);
+	if (values == NULL) {
+		return NULL;
+	}
+
+	*num_values = ldap_count_values_len(values);
+
+	ret = talloc_array(mem_ctx, char *, *num_values + 1);
+	if (ret == NULL) {
+		ldap_value_free_len(values);
+		return NULL;
+	}
+
+	for (i = 0; i < *num_values; i++) {
+		if (!pull_utf8_talloc(mem_ctx, &ret[i], values[i]->bv_val,
+				      &converted_size)) {
+			ldap_value_free_len(values);
+			return NULL;
+		}
+	}
+	ret[i] = NULL;
+
+	ldap_value_free_len(values);
+	return ret;
+}
+
 ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
 					    ADS_STRUCT *ads,
 					    const char *machine_name,
@@ -3694,9 +3728,7 @@ ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx,
 		goto done;
 	}
 
-	*hostnames_array = ads_pull_strings(ads, mem_ctx, res,
-					    "msDS-AdditionalDnsHostName",
-					    num_hostnames);
+	*hostnames_array = get_addl_hosts(ads, mem_ctx, res, num_hostnames);
 	if (*hostnames_array == NULL) {
 		DEBUG(1, ("Host account for %s does not have msDS-AdditionalDnsHostName.\n",
 			  machine_name));
-- 
2.25.4


From bb712cccd55b8a68865f72ebe48bdceae9995a94 Mon Sep 17 00:00:00 2001
From: Isaac Boukris <iboukris@gmail.com>
Date: Sat, 20 Jun 2020 17:17:33 +0200
Subject: [PATCH 4/4] Fix usage of ldap_get_values_len for
 msDS-AdditionalDnsHostName

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14406

Signed-off-by: Isaac Boukris <iboukris@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
Autobuild-Date(master): Mon Jun 22 09:59:04 UTC 2020 on sn-devel-184
---
 source3/libads/ldap.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index ed52d4a969e..7ef7e7e8420 100755
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -3691,8 +3691,12 @@ static char **get_addl_hosts(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
 	}
 
 	for (i = 0; i < *num_values; i++) {
-		if (!pull_utf8_talloc(mem_ctx, &ret[i], values[i]->bv_val,
-				      &converted_size)) {
+		ret[i] = NULL;
+		if (!convert_string_talloc(mem_ctx, CH_UTF8, CH_UNIX,
+					   values[i]->bv_val,
+					   strnlen(values[i]->bv_val,
+						   values[i]->bv_len),
+					   &ret[i], &converted_size)) {
 			ldap_value_free_len(values);
 			return NULL;
 		}
-- 
2.25.4