summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/configure.in24
-rw-r--r--source3/libads/kerberos.c52
-rw-r--r--source3/libsmb/cliconnect.c50
3 files changed, 118 insertions, 8 deletions
diff --git a/source3/configure.in b/source3/configure.in
index 7272ae4d9a..ac60b6f645 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -4221,6 +4221,30 @@ if test x"$with_ads_support" != x"no"; then
fi
fi
+ AC_CACHE_CHECK([for krb5_principal_get_realm],
+ samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM,[
+ AC_TRY_LINK([#include <krb5.h>],
+ [krb5_context ctx = NULL; krb5_principal princ = NULL; const char *str = krb5_principal_get_realm(ctx, princ);],
+ samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM=yes,
+ samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM=no)])
+
+ if test x"$samba_cv_HAVE_KRB5_PRINCIPAL_GET_REALM" = x"yes"; then
+ AC_DEFINE(HAVE_KRB5_PRINCIPAL_GET_REALM,1,
+ [Whether the function krb5_principal_get_realm is defined])
+ fi
+
+ AC_CACHE_CHECK([for krb5_princ_realm],
+ samba_cv_HAVE_KRB5_PRINC_REALM,[
+ AC_TRY_LINK([#include <krb5.h>],
+ [krb5_context ctx = NULL; krb5_principal princ = NULL; const char *str = krb5_princ_realm(ctx, princ)->data;],
+ samba_cv_HAVE_KRB5_PRINC_REALM=yes,
+ samba_cv_HAVE_KRB5_PRINC_REALM=no)])
+
+ if test x"$samba_cv_HAVE_KRB5_PRINC_REALM" = x"yes"; then
+ AC_DEFINE(HAVE_KRB5_PRINC_REALM,1,
+ [Whether the macro krb5_princ_realm is defined])
+ fi
+
#
#
# Now the decisions whether we can support krb5
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 29e5661d3c..02e14f468d 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -487,6 +487,58 @@ char* kerberos_secrets_fetch_des_salt( void )
return salt;
}
+/************************************************************************
+ Routine to get the default realm from the kerberos credentials cache.
+ Caller must free if the return value is not NULL.
+************************************************************************/
+
+char *kerberos_get_default_realm_from_ccache( void )
+{
+ char *realm = NULL;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal princ = NULL;
+
+ initialize_krb5_error_table();
+ if (krb5_init_context(&ctx)) {
+ return NULL;
+ }
+
+ DEBUG(5,("kerberos_get_default_realm_from_ccache: "
+ "Trying to read krb5 cache: %s\n",
+ krb5_cc_default_name(ctx)));
+ if (krb5_cc_default(ctx, &cc)) {
+ DEBUG(0,("kerberos_get_default_realm_from_ccache: "
+ "failed to read default cache\n"));
+ goto out;
+ }
+ if (krb5_cc_get_principal(ctx, cc, &princ)) {
+ DEBUG(0,("kerberos_get_default_realm_from_ccache: "
+ "failed to get default principal\n"));
+ goto done;
+ }
+
+#if defined(HAVE_KRB5_PRINCIPAL_GET_REALM)
+ realm = SMB_STRDUP(krb5_principal_get_realm(ctx, princ));
+#elif defined(HAVE_KRB5_PRINC_REALM)
+ realm = SMB_STRDUP(krb5_princ_realm(ctx, princ)->data);
+#endif
+
+ out:
+
+ if (princ) {
+ krb5_free_principal(ctx, princ);
+ }
+ if (cc) {
+ krb5_cc_close(ctx, cc);
+ }
+ if (ctx) {
+ krb5_free_context(ctx);
+ }
+done:
+ return realm;
+}
+
/************************************************************************
Routine to get the salting principal for this service. This is
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 45c202090e..52ff69953e 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -37,6 +37,8 @@ static const struct {
{-1,NULL}
};
+static const char *star_smbserver_name = "*SMBSERVER";
+
/**
* Set the user session key for a connection
* @param cli The cli structure to add it too
@@ -858,10 +860,42 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
}
}
- rc = cli_session_setup_kerberos(cli, principal, domain);
- if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
+ /* If we get a bad principal, try to guess it if
+ we have a valid host NetBIOS name.
+ */
+ if (strequal(principal,
+ "not_defined_in_RFC4178@please_ignore")) {
SAFE_FREE(principal);
- return rc;
+ }
+
+ if (principal == NULL &&
+ !is_ipaddress(cli->desthost) &&
+ !strequal(star_smbserver_name,
+ cli->desthost)) {
+ char *realm = NULL;
+ DEBUG(3,("cli_session_setup_spnego: got a "
+ "bad server principal, trying to guess ...\n"));
+
+ realm = kerberos_get_default_realm_from_ccache();
+ if (realm && *realm) {
+ if (asprintf(&principal, "%s$@%s",
+ cli->desthost, realm) < 0) {
+ 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) {
+ rc = cli_session_setup_kerberos(cli, principal, domain);
+ if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
+ SAFE_FREE(principal);
+ return rc;
+ }
}
}
#endif
@@ -1432,7 +1466,7 @@ NTSTATUS cli_connect(struct cli_state *cli,
/* reasonable default hostname */
if (!host) {
- host = "*SMBSERVER";
+ host = star_smbserver_name;
}
fstrcpy(cli->desthost, host);
@@ -1580,8 +1614,8 @@ again:
*p = 0;
goto again;
}
- if (strcmp(called.name, "*SMBSERVER")) {
- make_nmb_name(&called , "*SMBSERVER", 0x20);
+ if (strcmp(called.name, star_smbserver_name)) {
+ make_nmb_name(&called , star_smbserver_name, 0x20);
goto again;
}
return NT_STATUS_BAD_NETWORK_NAME;
@@ -1706,7 +1740,7 @@ bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srcho
*/
if(is_ipaddress(desthost)) {
- make_nmb_name(&called, "*SMBSERVER", 0x20);
+ make_nmb_name(&called, star_smbserver_name, 0x20);
} else {
make_nmb_name(&called, desthost, 0x20);
}
@@ -1715,7 +1749,7 @@ bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srcho
NTSTATUS status;
struct nmb_name smbservername;
- make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
+ make_nmb_name(&smbservername, star_smbserver_name, 0x20);
/*
* If the name wasn't *SMBSERVER then