s3-libads Factor out a new routine kerberos_get_principal_from_service_hostname()
authorAndrew Bartlett <abartlet@samba.org>
Wed, 4 Jan 2012 00:39:38 +0000 (11:39 +1100)
committerStefan Metzmacher <metze@samba.org>
Thu, 5 Jan 2012 16:17:28 +0000 (17:17 +0100)
This is now used in the GSE GSSAPI client, so that when we connect to
a target server at the CIFS level, we use the same name to connect
at the DCE/RPC level.

Andrew Bartlett

Signed-off-by: Stefan Metzmacher <metze@samba.org>
source3/libads/kerberos.c
source3/libads/kerberos_proto.h
source3/librpc/crypto/gse.c
source3/libsmb/cliconnect.c

index 76ca0c0cf3936a9ad5d957872d787746d0cdb5da..f260dcaaf0b6f5b78190dca989fac87e9f3d0e9f 100644 (file)
@@ -428,7 +428,7 @@ char* kerberos_secrets_fetch_des_salt( void )
  Caller must free if the return value is not NULL.
 ************************************************************************/
 
-char *kerberos_get_default_realm_from_ccache( void )
+char *kerberos_get_default_realm_from_ccache(TALLOC_CTX *mem_ctx)
 {
        char *realm = NULL;
        krb5_context ctx = NULL;
@@ -455,11 +455,11 @@ char *kerberos_get_default_realm_from_ccache( void )
        }
 
 #if defined(HAVE_KRB5_PRINCIPAL_GET_REALM)
-       realm = SMB_STRDUP(krb5_principal_get_realm(ctx, princ));
+       realm = talloc_strdup(mem_ctx, krb5_principal_get_realm(ctx, princ));
 #elif defined(HAVE_KRB5_PRINC_REALM)
        {
                krb5_data *realm_data = krb5_princ_realm(ctx, princ);
-               realm = SMB_STRNDUP(realm_data->data, realm_data->length);
+               realm = talloc_strndup(mem_ctx, realm_data->data, realm_data->length);
        }
 #endif
 
@@ -479,11 +479,10 @@ char *kerberos_get_default_realm_from_ccache( void )
 }
 
 /************************************************************************
- Routine to get the realm from a given DNS name. Returns malloc'ed memory.
- Caller must free() if the return value is not NULL.
+ Routine to get the realm from a given DNS name.
 ************************************************************************/
 
-char *kerberos_get_realm_from_hostname(const char *hostname)
+char *kerberos_get_realm_from_hostname(TALLOC_CTX *mem_ctx, const char *hostname)
 {
 #if defined(HAVE_KRB5_GET_HOST_REALM) && defined(HAVE_KRB5_FREE_HOST_REALM)
 #if defined(HAVE_KRB5_REALM_TYPE)
@@ -512,7 +511,7 @@ char *kerberos_get_realm_from_hostname(const char *hostname)
        }
 
        if (realm_list && realm_list[0]) {
-               realm = SMB_STRDUP(realm_list[0]);
+               realm = talloc_strdup(mem_ctx, realm_list[0]);
        }
 
   out:
@@ -531,6 +530,43 @@ char *kerberos_get_realm_from_hostname(const char *hostname)
 #endif
 }
 
+char *kerberos_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx,
+                                                  const char *service,
+                                                  const char *remote_name)
+{
+       char *realm = NULL;
+       char *host = NULL;
+       char *principal;
+       host = strchr_m(remote_name, '.');
+       if (host) {
+               /* DNS name. */
+               realm = kerberos_get_realm_from_hostname(talloc_tos(), remote_name);
+       } else {
+               /* NetBIOS name - use our realm. */
+               realm = kerberos_get_default_realm_from_ccache(talloc_tos());
+       }
+
+       if (realm == NULL || *realm == '\0') {
+               realm = talloc_strdup(talloc_tos(), lp_realm());
+               if (!realm) {
+                       return NULL;
+               }
+               DEBUG(3,("kerberos_get_principal_from_service_hostname: "
+                        "cannot get realm from, "
+                        "desthost %s or default ccache. Using default "
+                        "smb.conf realm %s\n",
+                        remote_name,
+                        realm));
+       }
+
+       principal = talloc_asprintf(mem_ctx,
+                                   "%s/%s@%s",
+                                   service, remote_name,
+                                   realm);
+       TALLOC_FREE(realm);
+       return principal;
+}
+
 /************************************************************************
  Routine to get the salting principal for this service.  This is 
  maintained for backwards compatibilty with releases prior to 3.0.24.
index ff1082a59bf221c15bebd15cafea807d08ef35f5..094f38dca2e171bbcc2031cf9b8430baf9cfeee3 100644 (file)
@@ -62,8 +62,11 @@ int ads_kdestroy(const char *cc_name);
 char* kerberos_standard_des_salt( void );
 bool kerberos_secrets_store_des_salt( const char* salt );
 char* kerberos_secrets_fetch_des_salt( void );
-char *kerberos_get_default_realm_from_ccache( void );
-char *kerberos_get_realm_from_hostname(const char *hostname);
+char *kerberos_get_default_realm_from_ccache(TALLOC_CTX *mem_ctx);
+char *kerberos_get_realm_from_hostname(TALLOC_CTX *mem_ctx, const char *hostname);
+char *kerberos_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx,
+                                                  const char *service,
+                                                  const char *remote_name);
 
 bool kerberos_secrets_store_salting_principal(const char *service,
                                              int enctype,
index b4e59da47580cd3bc65ea10842ede9781381ceeb..0f97978256fcf8d40746aec167294928b62efbe6 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "includes.h"
 #include "gse.h"
+#include "libads/kerberos_proto.h"
 
 #if defined(HAVE_KRB5) && defined(HAVE_GSS_WRAP_IOV)
 
@@ -247,15 +248,22 @@ NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
-       name_buffer.value = talloc_asprintf(gse_ctx,
-                                           "%s@%s", service, server);
+       /* Guess the realm based on the supplied service, and avoid the GSS libs
+          doing DNS lookups which may fail.
+
+          TODO: Loop with the KDC on some more combinations (local
+          realm in particular), possibly falling back to
+          GSS_C_NT_HOSTBASED_SERVICE
+       */
+       name_buffer.value = kerberos_get_principal_from_service_hostname(gse_ctx,
+                                                                        service, server);
        if (!name_buffer.value) {
                status = NT_STATUS_NO_MEMORY;
                goto err_out;
        }
        name_buffer.length = strlen((char *)name_buffer.value);
        gss_maj = gss_import_name(&gss_min, &name_buffer,
-                                 GSS_C_NT_HOSTBASED_SERVICE,
+                                 GSS_C_NT_USER_NAME,
                                  &gse_ctx->server_name);
        if (gss_maj) {
                DEBUG(0, ("gss_import_name failed for %s, with [%s]\n",
index 4f98f5c5e92c305b57d0bfd1cf4f1346621e848b..76e32565e4b2bb2a347f4eedd7894495201d8c1d 100644 (file)
@@ -1931,56 +1931,30 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
                        !is_ipaddress(remote_name) &&
                        !strequal(STAR_SMBSERVER,
                                  remote_name)) {
-                       char *realm = NULL;
-                       char *host = NULL;
                        DEBUG(3,("cli_session_setup_spnego: using target "
                                 "hostname not SPNEGO principal\n"));
 
-                       host = strchr_m(remote_name, '.');
                        if (dest_realm) {
-                               realm = SMB_STRDUP(dest_realm);
-                               if (!realm) {
-                                       return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+                               char *realm = strupper_talloc(talloc_tos(), dest_realm);
+                               if (realm) {
+                                       principal = talloc_asprintf(talloc_tos(),
+                                                                   "cifs/%s@%s",
+                                                                   remote_name,
+                                                                   realm);
+                                       TALLOC_FREE(realm);
                                }
-                               strupper_m(realm);
                        } else {
-                               if (host) {
-                                       /* DNS name. */
-                                       realm = kerberos_get_realm_from_hostname(remote_name);
-                               } else {
-                                       /* NetBIOS name - use our realm. */
-                                       realm = kerberos_get_default_realm_from_ccache();
-                               }
+                               principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
+                                                                                        "cifs",
+                                                                                        remote_name);
                        }
 
-                       if (realm == NULL || *realm == '\0') {
-                               realm = SMB_STRDUP(lp_realm());
-                               if (!realm) {
-                                       return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-                               }
-                               strupper_m(realm);
-                               DEBUG(3,("cli_session_setup_spnego: cannot "
-                                       "get realm from dest_realm %s, "
-                                       "desthost %s. Using default "
-                                       "smb.conf realm %s\n",
-                                       dest_realm ? dest_realm : "<null>",
-                                       remote_name,
-                                       realm));
-                       }
-
-                       principal = talloc_asprintf(talloc_tos(),
-                                                   "cifs/%s@%s",
-                                                   remote_name,
-                                                   realm);
                        if (!principal) {
-                               SAFE_FREE(realm);
                                return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
                        }
                        DEBUG(3,("cli_session_setup_spnego: guessed "
                                "server principal=%s\n",
                                principal ? principal : "<null>"));
-
-                       SAFE_FREE(realm);
                }
 
                if (principal) {