diff --git a/source3/configure.in b/source3/configure.in index 7740b3a..f64110b 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -3660,6 +3660,9 @@ if test x"$with_ads_support" != x"no"; then AC_CHECK_FUNC_EXT(krb5_get_creds_opt_set_impersonate, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_get_creds, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_get_credentials_for_user, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_get_host_realm, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_free_host_realm, $KRB5_LIBS) + # MIT krb5 1.8 does not expose this call (yet) AC_CHECK_DECLS(krb5_get_credentials_for_user, [], [], [#include ]) @@ -4002,6 +4005,18 @@ if test x"$with_ads_support" != x"no"; then [Whether the WRFILE:-keytab is supported]) fi + AC_CACHE_CHECK([for krb5_realm type], + samba_cv_HAVE_KRB5_REALM_TYPE,[ + AC_TRY_COMPILE([#include ], + [krb5_realm realm;], + samba_cv_HAVE_KRB5_REALM_TYPE=yes, + samba_cv_HAVE_KRB5_REALM_TYPE=no)]) + + if test x"$samba_cv_HAVE_KRB5_REALM_TYPE" = x"yes"; then + AC_DEFINE(HAVE_KRB5_REALM_TYPE,1, + [Whether the type krb5_realm exists]) + fi + AC_CACHE_CHECK([for krb5_princ_realm returns krb5_realm or krb5_data], samba_cv_KRB5_PRINC_REALM_RETURNS_REALM,[ AC_TRY_COMPILE([#include ], diff --git a/source3/include/proto.h b/source3/include/proto.h index f0ccc92..fa4a40c 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1795,6 +1795,8 @@ 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); + bool kerberos_secrets_store_salting_principal(const char *service, int enctype, const char *principal); diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index af8ea39..7fb4ec3 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -525,6 +525,58 @@ char *kerberos_get_default_realm_from_ccache( void ) return realm; } +/************************************************************************ + Routine to get the realm from a given DNS name. Returns malloc'ed memory. + Caller must free() if the return value is not NULL. +************************************************************************/ + +char *kerberos_get_realm_from_hostname(const char *hostname) +{ +#if defined(HAVE_KRB5_GET_HOST_REALM) && defined(HAVE_KRB5_FREE_HOST_REALM) +#if defined(HAVE_KRB5_REALM_TYPE) + /* Heimdal. */ + krb5_realm *realm_list = NULL; +#else + /* MIT */ + char **realm_list = NULL; +#endif + char *realm = NULL; + krb5_error_code kerr; + krb5_context ctx = NULL; + + initialize_krb5_error_table(); + if (krb5_init_context(&ctx)) { + return NULL; + } + + kerr = krb5_get_host_realm(ctx, hostname, &realm_list); + if (kerr != 0) { + DEBUG(3,("kerberos_get_realm_from_hostname %s: " + "failed %s\n", + hostname ? hostname : "(NULL)", + error_message(kerr) )); + goto out; + } + + if (realm_list && realm_list[0]) { + realm = SMB_STRDUP(realm_list[0]); + } + + out: + + if (ctx) { + if (realm_list) { + krb5_free_host_realm(ctx, realm_list); + realm_list = NULL; + } + krb5_free_context(ctx); + ctx = NULL; + } + return realm; +#else + return NULL; +#endif +} /************************************************************************ Routine to get the salting principal for this service. This is diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 31f848c..a81cb06 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1287,6 +1287,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, host = strchr_m(cli->desthost, '.'); if (host) { + /* We had a '.' in the name. */ machine = SMB_STRNDUP(cli->desthost, host - cli->desthost); } else { @@ -1300,11 +1301,29 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, realm = SMB_STRDUP(dest_realm); strupper_m(realm); } else { - realm = kerberos_get_default_realm_from_ccache(); + if (host) { + /* DNS name. */ + realm = kerberos_get_realm_from_hostname(cli->desthost); + } else { + /* NetBIOS name - use our realm. */ + realm = kerberos_get_default_realm_from_ccache(); + } } + if (realm && *realm) { - principal = talloc_asprintf(NULL, "%s$@%s", - machine, realm); + if (host) { + /* DNS name. */ + principal = talloc_asprintf(talloc_tos(), + "cifs/%s@%s", + cli->desthost, + realm); + } else { + /* NetBIOS name, use machine account. */ + principal = talloc_asprintf(talloc_tos(), + "%s$@%s", + machine, + realm); + } if (!principal) { SAFE_FREE(machine); SAFE_FREE(realm);