summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libads/kerberos.c50
-rw-r--r--source3/libads/kerberos_proto.h7
-rw-r--r--source3/librpc/crypto/gse.c14
-rw-r--r--source3/libsmb/cliconnect.c46
4 files changed, 69 insertions, 48 deletions
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 76ca0c0cf3..f260dcaaf0 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -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.
diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h
index ff1082a59b..094f38dca2 100644
--- a/source3/libads/kerberos_proto.h
+++ b/source3/libads/kerberos_proto.h
@@ -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,
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c
index b4e59da475..0f97978256 100644
--- a/source3/librpc/crypto/gse.c
+++ b/source3/librpc/crypto/gse.c
@@ -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",
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 4f98f5c5e9..76e32565e4 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -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) {