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 <[email protected]>
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 <[email protected]>
    Reviewed-by: Andreas Schneider <[email protected]>
    
    Autobuild-User(master): Günther Deschner <[email protected]>
    Autobuild-Date(master): Fri Sep 26 08:22:45 CEST 2014 on sn-devel-104

commit 7e0b8fcce5572c88d50993a1dbd90f65638ba90f
Author: Andreas Schneider <[email protected]>
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 <[email protected]>
    Reviewed-by: Guenther Deschner <[email protected]>

commit 5d58b92f8fcbc509f4fe2bd3617bcaeada1806b6
Author: Andreas Schneider <[email protected]>
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 <[email protected]>
    Reviewed-by: Guenther Deschner <[email protected]>

commit e1ee4c8bc7018db7787dd9a0be6d3aa40a477ee2
Author: Andreas Schneider <[email protected]>
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 <[email protected]>
    Reviewed-by: Guenther Deschner <[email protected]>

commit 4eaa4ccbdf279f1ff6d8218b36d92aeea0114cd8
Author: Andreas Schneider <[email protected]>
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 <[email protected]>
    Reviewed-by: Guenther Deschner <[email protected]>

commit 83c62bd3f5945bbe295cbfbd153736d4c709b3a6
Author: Andreas Schneider <[email protected]>
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 <[email protected]>
    Reviewed-by: Guenther Deschner <[email protected]>

-----------------------------------------------------------------------

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

Reply via email to