The branch, v3-0-test has been updated
       via  83b04c60fac76ccd2d5aecb14f8896a07d488b1f (commit)
      from  945bbd14bb1c8ec11365d52a7897ca17e95c9053 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-0-test


- Log -----------------------------------------------------------------
commit 83b04c60fac76ccd2d5aecb14f8896a07d488b1f
Author: Günther Deschner <[EMAIL PROTECTED]>
Date:   Thu Jan 31 13:05:36 2008 +0100

    Enable v3-0-test to successfully join a windows 2008 domain controller.
    
    This is hand-merged from a couple of commits from 3-2-test, cherry-picking 
was
    hardly possible without importing all the ldap sign/seal work from metze.
    
    Guenther

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

Summary of changes:
 source/include/ads.h       |    3 +
 source/libads/sasl.c       |  140 ++++++++++++++++++++++++++++++++------------
 source/libads/util.c       |   57 ++++++++++++++++++
 source/libsmb/cliconnect.c |    3 +-
 4 files changed, 164 insertions(+), 39 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/include/ads.h b/source/include/ads.h
index fcaeb20..24884f5 100644
--- a/source/include/ads.h
+++ b/source/include/ads.h
@@ -321,4 +321,7 @@ typedef struct {
        int val;
        int critical;
 } ads_control;
+
+#define ADS_IGNORE_PRINCIPAL "[EMAIL PROTECTED]"
+
 #endif /* _INCLUDE_ADS_H_ */
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index 0067a19..40749be 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -137,10 +137,81 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT 
*ads)
 }
 
 #ifdef HAVE_KRB5
+struct ads_service_principal {
+        char *string;
+#ifdef HAVE_GSSAPI
+        gss_name_t name;
+#endif
+};
+
+static void ads_free_service_principal(struct ads_service_principal *p)
+{
+       SAFE_FREE(p->string);
+
+#ifdef HAVE_GSSAPI
+       if (p->name) {
+               uint32 minor_status;
+               gss_release_name(&minor_status, &p->name);
+       }
+#endif
+       ZERO_STRUCTP(p);
+}
+
+static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
+                                                const char *given_principal,
+                                                struct ads_service_principal 
*p)
+{
+       ADS_STATUS status;
+#ifdef HAVE_GSSAPI
+       gss_buffer_desc input_name;
+       /* GSS_KRB5_NT_PRINCIPAL_NAME */
+       gss_OID_desc nt_principal =
+       {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
+       uint32 minor_status;
+       int gss_rc;
+#endif
+
+       ZERO_STRUCTP(p);
+
+       /* I've seen a child Windows 2000 domain not send
+          the principal name back in the first round of
+          the SASL bind reply.  So we guess based on server
+          name and realm.  --jerry  */
+       /* Also try best guess when we get the w2k8 ignore
+          principal back - gd */
+
+       if (!given_principal ||
+           strequal(given_principal, ADS_IGNORE_PRINCIPAL)) {
+
+               status = ads_guess_service_principal(ads, &p->string);
+               if (!ADS_ERR_OK(status)) {
+                       return status;
+               }
+       } else {
+               p->string = SMB_STRDUP(given_principal);
+               if (!p->string) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+       }
+
+#ifdef HAVE_GSSAPI
+       input_name.value = p->string;
+       input_name.length = strlen(p->string);
+
+       gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, 
&p->name);
+       if (gss_rc) {
+               ads_free_service_principal(p);
+               return ADS_ERROR_GSS(gss_rc, minor_status);
+       }
+#endif
+
+       return ADS_SUCCESS;
+}
+
 /* 
    perform a LDAP/SASL/SPNEGO/KRB5 bind
 */
-static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char 
*principal)
+static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char 
*principal)
 {
        DATA_BLOB blob = data_blob(NULL, 0);
        struct berval cred, *scred = NULL;
@@ -167,6 +238,13 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT 
*ads, const char *princip
 
        return ADS_ERROR(rc);
 }
+
+static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,
+                                           struct ads_service_principal *p)
+{
+       return ads_sasl_spnego_rawkrb5_bind(ads, p->string);
+}
+
 #endif
 
 /* 
@@ -178,7 +256,7 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
        int rc, i;
        ADS_STATUS status;
        DATA_BLOB blob;
-       char *principal = NULL;
+       char *given_principal = NULL;
        char *OIDs[ASN1_MAX_OIDS];
 #ifdef HAVE_KRB5
        BOOL got_kerberos_mechanism = False;
@@ -201,7 +279,7 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 
        /* the server sent us the first part of the SPNEGO exchange in the 
negprot 
           reply */
-       if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
+       if (!spnego_parse_negTokenInit(blob, OIDs, &given_principal)) {
                data_blob_free(&blob);
                status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
                goto failed;
@@ -219,42 +297,23 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 #endif
                free(OIDs[i]);
        }
-       DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", 
principal));
+       DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", 
given_principal));
 
 #ifdef HAVE_KRB5
        if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
            got_kerberos_mechanism) 
        {
-               /* I've seen a child Windows 2000 domain not send 
-                  the principal name back in the first round of 
-                  the SASL bind reply.  So we guess based on server
-                  name and realm.  --jerry  */
-               if ( !principal ) {
-                       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 )
-                                       return ADS_ERROR(LDAP_NO_MEMORY);
-
-                               strlower_m( server );
-                               strupper_m( server_realm );                     
        
-                               asprintf( &principal, "ldap/[EMAIL PROTECTED]", 
server, server_realm );
-
-                               SAFE_FREE( server );
-                               SAFE_FREE( server_realm );
-
-                               if ( !principal )
-                                       return ADS_ERROR(LDAP_NO_MEMORY);       
                        
-                       }
-                       
+               struct ads_service_principal p;
+
+               status = ads_generate_service_principal(ads, given_principal, 
&p);
+               SAFE_FREE(given_principal);
+               if (!ADS_ERR_OK(status)) {
+                       return status;
                }
-               
-               status = ads_sasl_spnego_krb5_bind(ads, principal);
+
+               status = ads_sasl_spnego_krb5_bind(ads, &p);
                if (ADS_ERR_OK(status)) {
-                       SAFE_FREE(principal);
+                       ads_free_service_principal(&p);
                        return status;
                }
 
@@ -264,19 +323,26 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
                status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 
 
                if (ADS_ERR_OK(status)) {
-                       status = ads_sasl_spnego_krb5_bind(ads, principal);
+                       status = ads_sasl_spnego_krb5_bind(ads, &p);
+                       if (!ADS_ERR_OK(status)) {
+                               DEBUG(0,("kinit succeeded but "
+                                       "ads_sasl_spnego_krb5_bind failed: 
%s\n",
+                                       ads_errstr(status)));
+                       }
                }
 
+               ads_free_service_principal(&p);
+
                /* only fallback to NTLMSSP if allowed */
                if (ADS_ERR_OK(status) || 
                    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
-                       SAFE_FREE(principal);
                        return status;
                }
-       }
+       } else
 #endif
-
-       SAFE_FREE(principal);
+       {
+               SAFE_FREE(given_principal);
+       }
 
        /* lets do NTLMSSP ... this has the big advantage that we don't need
           to sync clocks, and we don't rely on special versions of the krb5 
diff --git a/source/libads/util.c b/source/libads/util.c
index eb6dccb..365f72e 100644
--- a/source/libads/util.c
+++ b/source/libads/util.c
@@ -52,4 +52,61 @@ failed:
        SAFE_FREE(password);
        return ret;
 }
+
+ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
+                                      char **returned_principal)
+{
+       char *princ = NULL;
+
+       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) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+
+               strlower_m(server);
+               strupper_m(server_realm);
+               asprintf(&princ, "ldap/[EMAIL PROTECTED]", server, 
server_realm);
+
+               SAFE_FREE(server);
+               SAFE_FREE(server_realm);
+
+               if (!princ) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+       } 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) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+
+               strlower_m(server);
+               strupper_m(server_realm);
+               asprintf(&princ, "ldap/[EMAIL PROTECTED]", server, 
server_realm);
+
+               SAFE_FREE(server);
+               SAFE_FREE(server_realm);
+
+               if (!princ) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+       }
+
+       if (!princ) {
+               return ADS_ERROR(LDAP_PARAM_ERROR);
+       }
+
+       *returned_principal = princ;
+
+       return ADS_SUCCESS;
+}
+
 #endif
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 3168dd1..2f6606f 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -866,8 +866,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, 
const char *user,
                /* If we get a bad principal, try to guess it if
                   we have a valid host NetBIOS name.
                 */
-               if (strequal(principal,
-                               "[EMAIL PROTECTED]")) {
+               if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
                        SAFE_FREE(principal);
                }
                if (principal == NULL &&


-- 
Samba Shared Repository

Reply via email to