[SCM] Samba Shared Repository - branch master updated
Günther Deschner
gd at samba.org
Fri Sep 26 00:23:04 MDT 2014
The branch, master has been updated
via 0aacbe7 s3-libnet: Make sure we do not overwrite precreated SPNs.
via 7e0b8fc s3-libnet: Add libnet_join_get_machine_spns().
via 5d58b92 s3-libads: Add all machine account principals to the keytab.
via e1ee4c8 s3-libads: Add function to search for an element in an array.
via 4eaa4cc s3-libads: Add a function to retrieve the SPNs of a computer account.
via 83c62bd s3-libads: Improve service principle guessing.
from 69a7e3c s4: libcli: ldap message - Ensure all asn1_XX returns are checked.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 0aacbe78bb40d76b65087c2a197c92b0101e625e
Author: Günther Deschner <gd at samba.org>
Date: Fri Sep 26 03:35:43 2014 +0200
s3-libnet: Make sure we do not overwrite precreated SPNs.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
Signed-off-by: Günther Deschner <gd at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
Autobuild-User(master): Günther Deschner <gd at samba.org>
Autobuild-Date(master): Fri Sep 26 08:22:45 CEST 2014 on sn-devel-104
commit 7e0b8fcce5572c88d50993a1dbd90f65638ba90f
Author: Andreas Schneider <asn at samba.org>
Date: Fri Sep 26 03:09:08 2014 +0200
s3-libnet: Add libnet_join_get_machine_spns().
BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Guenther Deschner <gd at samba.org>
commit 5d58b92f8fcbc509f4fe2bd3617bcaeada1806b6
Author: Andreas Schneider <asn at samba.org>
Date: Wed Sep 24 10:51:33 2014 +0200
s3-libads: Add all machine account principals to the keytab.
This adds all SPNs defined in the DC for the computer account to the
keytab using 'net ads keytab create -P'.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=9985
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Guenther Deschner <gd at samba.org>
commit e1ee4c8bc7018db7787dd9a0be6d3aa40a477ee2
Author: Andreas Schneider <asn at samba.org>
Date: Wed Sep 24 09:23:58 2014 +0200
s3-libads: Add function to search for an element in an array.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Guenther Deschner <gd at samba.org>
commit 4eaa4ccbdf279f1ff6d8218b36d92aeea0114cd8
Author: Andreas Schneider <asn at samba.org>
Date: Wed Sep 24 09:22:03 2014 +0200
s3-libads: Add a function to retrieve the SPNs of a computer account.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=9984
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Guenther Deschner <gd at samba.org>
commit 83c62bd3f5945bbe295cbfbd153736d4c709b3a6
Author: Andreas Schneider <asn at samba.org>
Date: Tue Sep 23 14:09:41 2014 +0200
s3-libads: Improve service principle guessing.
If the name passed to the net command with the -S options is the long
hostname of the domaincontroller and not the 15 char NetBIOS name we
should construct a FQDN with the realm to get a Kerberos ticket.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=10829
Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Guenther Deschner <gd at samba.org>
-----------------------------------------------------------------------
Summary of changes:
source3/libads/ads_proto.h | 8 +++
source3/libads/kerberos_keytab.c | 74 ++++++++++++++++-------
source3/libads/ldap.c | 91 ++++++++++++++++++++++++++++
source3/libads/sasl.c | 124 ++++++++++++++++++++------------------
source3/libnet/libnet_join.c | 59 +++++++++++++++++-
5 files changed, 273 insertions(+), 83 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h
index 17a84d1..1e34247 100644
--- a/source3/libads/ads_proto.h
+++ b/source3/libads/ads_proto.h
@@ -87,6 +87,14 @@ ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
const char *name, const char **vals);
uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name);
uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name);
+
+bool ads_element_in_array(const char **el_array, size_t num_el, const char *el);
+
+ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx,
+ ADS_STRUCT *ads,
+ const char *machine_name,
+ char ***spn_array,
+ size_t *num_spns);
ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machine_name);
ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_name,
const char *my_fqdn, const char *spn);
diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c
index 6a1ba75..43c755c 100644
--- a/source3/libads/kerberos_keytab.c
+++ b/source3/libads/kerberos_keytab.c
@@ -510,20 +510,57 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
krb5_kt_cursor cursor;
krb5_keytab_entry kt_entry;
krb5_kvno kvno;
- int i, found = 0;
+ size_t found = 0;
char *sam_account_name, *upn;
char **oldEntries = NULL, *princ_s[26];
- TALLOC_CTX *tmpctx = NULL;
+ TALLOC_CTX *frame;
char *machine_name;
+ char **spn_array;
+ size_t num_spns;
+ size_t i;
+ ADS_STATUS status;
- /* these are the main ones we need */
- ret = ads_keytab_add_entry(ads, "host");
- if (ret != 0) {
- DEBUG(1, (__location__ ": ads_keytab_add_entry failed while "
- "adding 'host' principal.\n"));
- return ret;
+ frame = talloc_stackframe();
+ if (frame == NULL) {
+ ret = -1;
+ goto done;
+ }
+
+ status = ads_get_service_principal_names(frame,
+ ads,
+ lp_netbios_name(),
+ &spn_array,
+ &num_spns);
+ if (!ADS_ERR_OK(status)) {
+ ret = -1;
+ goto done;
}
+ for (i = 0; i < num_spns; i++) {
+ char *srv_princ;
+ char *p;
+
+ srv_princ = strlower_talloc(frame, spn_array[i]);
+ if (srv_princ == NULL) {
+ ret = -1;
+ goto done;
+ }
+
+ p = strchr_m(srv_princ, '/');
+ if (p == NULL) {
+ continue;
+ }
+ p[0] = '\0';
+
+ /* Add the SPNs found on the DC */
+ ret = ads_keytab_add_entry(ads, srv_princ);
+ if (ret != 0) {
+ DEBUG(1, ("ads_keytab_add_entry failed while "
+ "adding '%s' principal.\n",
+ spn_array[i]));
+ goto done;
+ }
+ }
#if 0 /* don't create the CIFS/... keytab entries since no one except smbd
really needs them and we will fall back to verifying against
@@ -546,24 +583,17 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
if (ret) {
DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
error_message(ret)));
- return ret;
- }
-
- tmpctx = talloc_init(__location__);
- if (!tmpctx) {
- DEBUG(0, (__location__ ": talloc_init() failed!\n"));
- ret = -1;
goto done;
}
- machine_name = talloc_strdup(tmpctx, lp_netbios_name());
+ machine_name = talloc_strdup(frame, lp_netbios_name());
if (!machine_name) {
ret = -1;
goto done;
}
/* now add the userPrincipalName and sAMAccountName entries */
- sam_account_name = ads_get_samaccountname(ads, tmpctx, machine_name);
+ sam_account_name = ads_get_samaccountname(ads, frame, machine_name);
if (!sam_account_name) {
DEBUG(0, (__location__ ": unable to determine machine "
"account's name in AD!\n"));
@@ -587,7 +617,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
}
/* remember that not every machine account will have a upn */
- upn = ads_get_upn(ads, tmpctx, machine_name);
+ upn = ads_get_upn(ads, frame, machine_name);
if (upn) {
ret = ads_keytab_add_entry(ads, upn);
if (ret != 0) {
@@ -599,7 +629,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
/* Now loop through the keytab and update any other existing entries */
kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name);
- if (kvno == -1) {
+ if (kvno == (krb5_kvno)-1) {
DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to "
"determine the system's kvno.\n"));
goto done;
@@ -632,12 +662,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
* have a race condition where someone else could add entries after
* we've counted them. Re-open asap to minimise the race. JRA.
*/
- DEBUG(3, (__location__ ": Found %d entries in the keytab.\n", found));
+ DEBUG(3, (__location__ ": Found %zd entries in the keytab.\n", found));
if (!found) {
goto done;
}
- oldEntries = talloc_array(tmpctx, char *, found);
+ oldEntries = talloc_array(frame, char *, found);
if (!oldEntries) {
DEBUG(1, (__location__ ": Failed to allocate space to store "
"the old keytab entries (talloc failed?).\n"));
@@ -711,7 +741,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
done:
TALLOC_FREE(oldEntries);
- TALLOC_FREE(tmpctx);
+ TALLOC_FREE(frame);
{
krb5_keytab_entry zero_kt_entry;
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 8fed8fd..06b4895 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1915,6 +1915,97 @@ ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machin
}
/**
+ * @brief Search for an element in a string array.
+ *
+ * @param[in] el_array The string array to search.
+ *
+ * @param[in] num_el The number of elements in the string array.
+ *
+ * @param[in] el The string to search.
+ *
+ * @return True if found, false if not.
+ */
+bool ads_element_in_array(const char **el_array, size_t num_el, const char *el)
+{
+ size_t i;
+
+ if (el_array == NULL || num_el == 0 || el == NULL) {
+ return false;
+ }
+
+ for (i = 0; i < num_el && el_array[i] != NULL; i++) {
+ int cmp;
+
+ cmp = strcasecmp_m(el_array[i], el);
+ if (cmp == 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * @brief This gets the service principal names of an existing computer account.
+ *
+ * @param[in] mem_ctx The memory context to use to allocate the spn array.
+ *
+ * @param[in] ads The ADS context to use.
+ *
+ * @param[in] machine_name The NetBIOS name of the computer, which is used to
+ * identify the computer account.
+ *
+ * @param[in] spn_array A pointer to store the array for SPNs.
+ *
+ * @param[in] num_spns The number of principals stored in the array.
+ *
+ * @return 0 on success, or a ADS error if a failure occured.
+ */
+ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx,
+ ADS_STRUCT *ads,
+ const char *machine_name,
+ char ***spn_array,
+ size_t *num_spns)
+{
+ ADS_STATUS status;
+ LDAPMessage *res = NULL;
+ char *dn;
+ 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;
+ }
+
+ dn = ads_get_dn(ads, mem_ctx, res);
+ if (dn == NULL) {
+ status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ goto done;
+ }
+
+ *spn_array = ads_pull_strings(ads,
+ mem_ctx,
+ res,
+ "servicePrincipalName",
+ num_spns);
+
+done:
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+/**
* This adds a service principal name to an existing computer account
* (found by hostname) in AD.
* @param ads An initialized ADS_STRUCT
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 6890fb2..8a9e157 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -714,88 +714,96 @@ static void ads_free_service_principal(struct ads_service_principal *p)
static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
char **returned_principal)
{
+ ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
char *princ = NULL;
+ TALLOC_CTX *frame;
+ char *server = NULL;
+ char *realm = NULL;
+ int rc;
- if (ads->server.realm && ads->server.ldap_server) {
- char *server, *server_realm;
-
- server = SMB_STRDUP(ads->server.ldap_server);
- server_realm = SMB_STRDUP(ads->server.realm);
-
- if (!server || !server_realm) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ frame = talloc_stackframe();
+ if (frame == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
- if (!strlower_m(server)) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
+ if (ads->server.realm && ads->server.ldap_server) {
+ server = strlower_talloc(frame, ads->server.ldap_server);
+ if (server == NULL) {
+ goto out;
}
- if (!strupper_m(server_realm)) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
+ realm = strupper_talloc(frame, ads->server.realm);
+ if (realm == NULL) {
+ goto out;
}
- if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ /*
+ * If we got a name which is bigger than a NetBIOS name,
+ * but isn't a FQDN, create one.
+ */
+ if (strlen(server) > 15 && strstr(server, ".") == NULL) {
+ char *dnsdomain;
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
+ dnsdomain = strlower_talloc(frame, ads->server.realm);
+ if (dnsdomain == NULL) {
+ goto out;
+ }
- if (!princ) {
- return ADS_ERROR(LDAP_NO_MEMORY);
+ server = talloc_asprintf(frame,
+ "%s.%s",
+ server, dnsdomain);
+ if (server == NULL) {
+ goto out;
+ }
}
} else if (ads->config.realm && ads->config.ldap_server_name) {
- char *server, *server_realm;
-
- server = SMB_STRDUP(ads->config.ldap_server_name);
- server_realm = SMB_STRDUP(ads->config.realm);
-
- if (!server || !server_realm) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
+ server = strlower_talloc(frame, ads->config.ldap_server_name);
+ if (server == NULL) {
+ goto out;
}
- if (!strlower_m(server)) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
+ realm = strupper_talloc(frame, ads->config.realm);
+ if (realm == NULL) {
+ goto out;
}
- if (!strupper_m(server_realm)) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
- if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
- return ADS_ERROR(LDAP_NO_MEMORY);
- }
+ /*
+ * If we got a name which is bigger than a NetBIOS name,
+ * but isn't a FQDN, create one.
+ */
+ if (strlen(server) > 15 && strstr(server, ".") == NULL) {
+ char *dnsdomain;
- SAFE_FREE(server);
- SAFE_FREE(server_realm);
+ dnsdomain = strlower_talloc(frame, ads->server.realm);
+ if (dnsdomain == NULL) {
+ goto out;
+ }
- if (!princ) {
- return ADS_ERROR(LDAP_NO_MEMORY);
+ server = talloc_asprintf(frame,
+ "%s.%s",
+ server, dnsdomain);
+ if (server == NULL) {
+ goto out;
+ }
}
}
- if (!princ) {
- return ADS_ERROR(LDAP_PARAM_ERROR);
+ if (server == NULL || realm == NULL) {
+ goto out;
+ }
+
+ rc = asprintf(&princ, "ldap/%s@%s", server, realm);
+ if (rc == -1 || princ == NULL) {
+ status = ADS_ERROR(LDAP_PARAM_ERROR);
+ goto out;
}
*returned_principal = princ;
- return ADS_SUCCESS;
+ status = ADS_SUCCESS;
+out:
+ TALLOC_FREE(frame);
+ return status;
}
static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index fe348d1..381a59c 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -360,6 +360,26 @@ static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx,
return status;
}
+static ADS_STATUS libnet_join_get_machine_spns(TALLOC_CTX *mem_ctx,
+ struct libnet_JoinCtx *r,
+ char ***spn_array,
+ size_t *num_spns)
+{
+ ADS_STATUS status;
+
+ if (r->in.machine_name == NULL) {
+ return ADS_ERROR_SYSTEM(EINVAL);
+ }
+
+ status = ads_get_service_principal_names(mem_ctx,
+ r->in.ads,
+ r->in.machine_name,
+ spn_array,
+ num_spns);
+
+ return status;
+}
+
/****************************************************************
Set a machines dNSHostName and servicePrincipalName attributes
****************************************************************/
@@ -370,8 +390,10 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
ADS_STATUS status;
ADS_MODLIST mods;
fstring my_fqdn;
- const char *spn_array[3] = {NULL, NULL, NULL};
+ const char **spn_array = NULL;
+ size_t num_spns = 0;
char *spn = NULL;
+ bool ok;
/* Find our DN */
@@ -380,6 +402,14 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
return status;
}
+ status = libnet_join_get_machine_spns(mem_ctx,
+ r,
+ discard_const_p(char **, &spn_array),
+ &num_spns);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(5, ("Retrieving the servicePrincipalNames failed.\n"));
+ }
+
/* Windows only creates HOST/shortname & HOST/fqdn. */
spn = talloc_asprintf(mem_ctx, "HOST/%s", r->in.machine_name);
@@ -389,7 +419,15 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
if (!strupper_m(spn)) {
return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
}
- spn_array[0] = spn;
+
+ ok = ads_element_in_array(spn_array, num_spns, spn);
+ if (!ok) {
+ ok = add_string_to_array(spn_array, spn,
+ &spn_array, (int *)&num_spns);
+ if (!ok) {
+ return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
+ }
+ }
if (!name_to_fqdn(my_fqdn, r->in.machine_name)
|| (strchr(my_fqdn, '.') == NULL)) {
@@ -406,8 +444,23 @@ static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
if (!spn) {
return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
}
- spn_array[1] = spn;
+
--
Samba Shared Repository
More information about the samba-cvs
mailing list