summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald W. Carter <jerry@samba.org>2008-05-23 16:01:45 -0500
committerKarolin Seeger <kseeger@samba.org>2008-06-09 09:22:26 +0200
commita73f5c089f3bff1a400a02a1bae77dd33040e5c7 (patch)
treeb4fa1dee133b7df4590485f717fd5f04226f6b3e
parent43f277a7dd06b800bd15f0b92a8f916e25f1370d (diff)
downloadsamba-a73f5c089f3bff1a400a02a1bae77dd33040e5c7.tar.gz
Manually merge Steven Danneman's patch for SPNEGO auth to a trusted
Win2008 domain (merged from v3-0-test). commit 8dc4e979776aae0ecaa74b51dc1eac78a7631405 Author: Steven Danneman <sdanneman@isilon.com> Date: Wed May 7 13:34:26 2008 -0700 spnego SPN fix when contacting trusted domains cli_session_setup_spnego() was not taking into consideration the situation where we're connecting to a trusted domain, specifically one (like W2K8) which doesn't return a SPN in the NegTokenInit. This caused two problems: 1) When guessing the SPN using kerberos_get_default_realm_from_ccache() we were always using our default realm, not the realm of the domain we're connecting to. 2) When falling back on NTLMSSP for authentication we were passing the name of the domain we're connecting to for use in our credentials when we should be passing our own workgroup name. The fix for both was to split the single "domain" parameter into "user_domain" and "dest_realm" parameters. We use the "user_domain" parameter to pass into the NTLM call, and we used "dest_realm" to create an SPN if none was returned in the NegTokenInit2 packet. If no "dest_realm" is provided we assume we're connecting to our own domain and use the credentials cache to build the SPN. Since we have a reasonable guess at the SPN, I removed the check that defaults us directly to NTLM when negHint is empty. (cherry picked from b78b14c88e8354aadf9ba7644bdb1c29245fe419) (cherry picked from commit f1e6b40bbc8ce249e2f2a85a1d57ed6b8141e3bb)
-rw-r--r--source/libsmb/cliconnect.c41
-rw-r--r--source/winbindd/winbindd_cm.c12
2 files changed, 28 insertions, 25 deletions
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 0f17571e00a..632d91013e7 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -785,12 +785,16 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
/****************************************************************************
Do a spnego encrypted session setup.
+
+ user_domain: The shortname of the domain the user/machine is a member of.
+ dest_realm: The realm we're connecting to, if NULL we use our default realm.
****************************************************************************/
ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
- const char *pass, const char *domain)
+ const char *pass, const char *user_domain,
+ const char * dest_realm)
{
- char *principal;
+ char *principal = NULL;
char *OIDs[ASN1_MAX_OIDS];
int i;
bool got_kerberos_mechanism = False;
@@ -813,8 +817,10 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
/* there is 16 bytes of GUID before the real spnego packet starts */
blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
- /* the server sent us the first part of the SPNEGO exchange in the negprot
- reply */
+ /* The server sent us the first part of the SPNEGO exchange in the
+ * negprot reply. It is WRONG to depend on the principal sent in the
+ * negprot reply, but right now we do it. If we don't receive one,
+ * we try to best guess, then fall back to NTLM. */
if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
data_blob_free(&blob);
return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
@@ -833,18 +839,6 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
- if (got_kerberos_mechanism && (principal == NULL)) {
- /*
- * It is WRONG to depend on the principal sent in the negprot
- * reply, but right now we do it. So for safety (don't
- * segfault later) disable Kerberos when no principal was
- * sent. -- VL
- */
- DEBUG(1, ("Kerberos mech was offered, but no principal was "
- "sent, disabling Kerberos\n"));
- cli->use_kerberos = False;
- }
-
fstrcpy(cli->user_name, user);
#ifdef HAVE_KRB5
@@ -897,7 +891,12 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
- realm = kerberos_get_default_realm_from_ccache();
+ if (dest_realm) {
+ realm = SMB_STRDUP(dest_realm);
+ strupper_m(realm);
+ } else {
+ realm = kerberos_get_default_realm_from_ccache();
+ }
if (realm && *realm) {
if (asprintf(&principal, "%s$@%s",
machine, realm) < 0) {
@@ -914,7 +913,8 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
}
if (principal) {
- rc = cli_session_setup_kerberos(cli, principal, domain);
+ rc = cli_session_setup_kerberos(cli, principal,
+ dest_realm);
if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
SAFE_FREE(principal);
return rc;
@@ -939,7 +939,7 @@ ntlmssp:
account[PTR_DIFF(p,user)] = '\0';
}
- return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, domain));
+ return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
}
/****************************************************************************
@@ -1031,7 +1031,8 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
/* if the server supports extended security then use SPNEGO */
if (cli->capabilities & CAP_EXTENDED_SECURITY) {
- ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
+ ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
+ workgroup, NULL);
if (!ADS_ERR_OK(status)) {
DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
return ads_ntstatus(status);
diff --git a/source/winbindd/winbindd_cm.c b/source/winbindd/winbindd_cm.c
index 74cd5db3217..23bdb6720d9 100644
--- a/source/winbindd/winbindd_cm.c
+++ b/source/winbindd/winbindd_cm.c
@@ -827,14 +827,15 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
(*cli)->use_kerberos = True;
DEBUG(5, ("connecting to %s from %s with kerberos principal "
- "[%s]\n", controller, global_myname(),
- machine_krb5_principal));
+ "[%s] and realm [%s]\n", controller, global_myname(),
+ machine_krb5_principal, domain->alt_name));
winbindd_set_locator_kdc_envs(domain);
ads_status = cli_session_setup_spnego(*cli,
machine_krb5_principal,
- machine_password,
+ machine_password,
+ lp_workgroup(),
domain->name);
if (!ADS_ERR_OK(ads_status)) {
@@ -855,12 +856,13 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
DEBUG(5, ("connecting to %s from %s with username "
"[%s]\\[%s]\n", controller, global_myname(),
- domain->name, machine_account));
+ lp_workgroup(), machine_account));
ads_status = cli_session_setup_spnego(*cli,
machine_account,
machine_password,
- domain->name);
+ lp_workgroup(),
+ NULL);
if (!ADS_ERR_OK(ads_status)) {
DEBUG(4, ("authenticated session setup failed with %s\n",
ads_errstr(ads_status)));