From 4884f5d23af41a0b88b98a0485cb3935beb820fe Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 08:52:20 +0100 Subject: In cm_prepare_connection(), only get auth user creds if we need to. Michael (This used to be commit 164bfb25d7b5cfeffeb4d81958b7629a11ca5d5e) --- source3/winbindd/winbindd_cm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 3f6544965d..0a96e04052 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -676,8 +676,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - *retry = True; got_mutex = secrets_named_mutex(controller, @@ -795,6 +793,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, (*cli)->use_kerberos = False; + cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); + if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) && (strlen(ipc_username) > 0)) { -- cgit From 5d9c97703432bbca7d45948708b5b21a3718559a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 12:47:28 +0100 Subject: Streamline logic in cm_connect_netlogon() by retrieving trust password only, when it will be used. Michael (This used to be commit cdc60d8ae8c0ef804206b20b451e9557f97d4439) --- source3/winbindd/winbindd_cm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 0a96e04052..d5c8b9955f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2219,10 +2219,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return NT_STATUS_OK; } - if ((IS_DC || domain->primary) && !get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result); if (netlogon_pipe == NULL) { @@ -2234,11 +2230,16 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags &= ~NETLOGON_NEG_SCHANNEL; goto no_schannel; } - + if (lp_client_schannel() != False) { neg_flags |= NETLOGON_NEG_SCHANNEL; } + if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { + cli_rpc_pipe_close(netlogon_pipe); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + /* if we are a DC and this is a trusted domain, then we need to use our domain name in the net_req_auth2() request */ -- cgit From f793c99ca54d62cb8142607e8449f5b5b3a5e79d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 13:05:44 +0100 Subject: Let get_trust_pw() determine the machine_account_name to use. Up to now each caller used its own logic. This eliminates code paths where there was a special treatment of the following situation: the domain given is not our workgroup (i.e. our own domain) and we are not a DC (i.e. it is not a typical trusted domain situation). In situation the given domain name was previously used as the machine account name, resulting in an account name of DOMAIN\\DOMAIN$, which does not seem very reasonable to me. get_trust_pw would not have obtained a password in this situation anyways. I hope I have not missed an important point here! Michael (This used to be commit 6ced4a7f88798dc449a667d63bc29bf6c569291f) --- source3/winbindd/winbindd_cm.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d5c8b9955f..adb9d11edc 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2235,27 +2235,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags |= NETLOGON_NEG_SCHANNEL; } - if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { - cli_rpc_pipe_close(netlogon_pipe); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - /* if we are a DC and this is a trusted domain, then we need to use our - domain name in the net_req_auth2() request */ - - if ( IS_DC - && !strequal(domain->name, lp_workgroup()) - && lp_allow_trusted_domains() ) + if (!get_trust_pw(domain->name, mach_pwd, &account_name, + &sec_chan_type)) { - account_name = lp_workgroup(); - } else { - account_name = domain->primary ? - global_myname() : domain->name; - } - - if (account_name == NULL) { cli_rpc_pipe_close(netlogon_pipe); - return NT_STATUS_NO_MEMORY; + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } result = rpccli_netlogon_setup_creds( -- cgit From 31f221ed9316c8dc2f4911d7b8ddcdf8b74367db Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 14:07:32 +0100 Subject: Rename get_trust_pw() to get_trust_pw_hash(). Michael (This used to be commit 0cde7ac9cb39a0026a38ccf66dbecefc12931074) --- source3/winbindd/winbindd_cm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index adb9d11edc..d8040d79ac 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2235,8 +2235,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, neg_flags |= NETLOGON_NEG_SCHANNEL; } - if (!get_trust_pw(domain->name, mach_pwd, &account_name, - &sec_chan_type)) + if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, + &sec_chan_type)) { cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; -- cgit From a493c7baac311e9ac0a560e4412d07df150f4407 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 15:39:36 +0100 Subject: Streamline and fix logic of cm_prepare_connection(). Do not attempt to do a session setup when in a trusted domain situation (this gives STATUS_NOLOGON_TRUSTED_DOMAIN_ACCOUNT). Use get_trust_pw_clear to get machine trust account. Only call this when the results is really used. Use the proper domain and account name for session setup. Michael (This used to be commit 18c66a364e0ddc4960769871ca190944f7fe5c44) --- source3/winbindd/winbindd_cm.c | 62 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d8040d79ac..00d9092dc3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -646,8 +646,13 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, struct cli_state **cli, bool *retry) { - char *machine_password, *machine_krb5_principal, *machine_account; - char *ipc_username, *ipc_domain, *ipc_password; + char *machine_password = NULL; + char *machine_krb5_principal = NULL; + char *machine_account = NULL; + const char *account_name = NULL; + char *ipc_username = NULL; + char *ipc_domain = NULL; + char *ipc_password = NULL; bool got_mutex; @@ -661,21 +666,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, DEBUG(10,("cm_prepare_connection: connecting to DC %s for domain %s\n", controller, domain->name )); - machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, - NULL); - - if (asprintf(&machine_account, "%s$", global_myname()) == -1) { - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - - if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), - lp_realm()) == -1) { - SAFE_FREE(machine_account); - SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; - } - *retry = True; got_mutex = secrets_named_mutex(controller, @@ -732,10 +722,32 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = NT_STATUS_UNSUCCESSFUL; goto done; } - - if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { + + if (!is_trusted_domain_situation(domain->name) && + (*cli)->protocol >= PROTOCOL_NT1 && + (*cli)->capabilities & CAP_EXTENDED_SECURITY) + { ADS_STATUS ads_status; + if (!get_trust_pw_clear(domain->name, &machine_password, + &account_name, NULL)) + { + result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + goto done; + } + + if (asprintf(&machine_account, "%s$", account_name) == -1) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + + if (asprintf(&machine_krb5_principal, "%s$@%s", account_name, + lp_realm()) == -1) + { + result = NT_STATUS_NO_MEMORY; + goto done; + } + if (lp_security() == SEC_ADS) { /* Try a krb5 session */ @@ -750,7 +762,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, ads_status = cli_session_setup_spnego(*cli, machine_krb5_principal, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4,("failed kerberos session setup with %s\n", @@ -760,7 +772,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } @@ -770,12 +782,12 @@ 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(), - lp_workgroup(), machine_account)); + domain->name, machine_account)); ads_status = cli_session_setup_spnego(*cli, machine_account, machine_password, - lp_workgroup()); + domain->name); if (!ADS_ERR_OK(ads_status)) { DEBUG(4, ("authenticated session setup failed with %s\n", ads_errstr(ads_status))); @@ -784,12 +796,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, result = ads_ntstatus(ads_status); if (NT_STATUS_IS_OK(result)) { /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ - cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + cli_init_creds(*cli, machine_account, domain->name, machine_password); goto session_setup_done; } } - /* Fall back to non-kerberos session setup */ + /* Fall back to non-kerberos session setup with auth_user */ (*cli)->use_kerberos = False; -- cgit From 13e0e4bdf25d00bdf021851d4f5a9e906212c357 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 16:32:38 +0100 Subject: Refactor out assembling of trust creds (pw, account name, principal). Michael (This used to be commit 481f18b20d6d5ee12c62120a3559bb16cc98e465) --- source3/winbindd/winbindd_cm.c | 55 +++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 17 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 00d9092dc3..cc7a0cc671 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -635,6 +635,40 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain, return True; } +/** + * Helper function to assemble trust password and account name + */ +static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, + char **machine_password, + char **machine_account, + char **machine_krb5_principal) +{ + const char *account_name; + + if (!get_trust_pw_clear(domain->name, machine_password, + &account_name, NULL)) + { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + if ((machine_account != NULL) && + (asprintf(machine_account, "%s$", account_name) == -1)) + { + return NT_STATUS_NO_MEMORY; + } + + /* this is at least correct when domain is our domain, + * which is the only case, when this is currently used: */ + if ((machine_krb5_principal != NULL) && + (asprintf(machine_krb5_principal, "%s$@%s", account_name, + domain->alt_name) == -1)) + { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + /************************************************************************ Given a fd with a just-connected TCP connection to a DC, open a connection to the pipe. @@ -649,7 +683,6 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, char *machine_password = NULL; char *machine_krb5_principal = NULL; char *machine_account = NULL; - const char *account_name = NULL; char *ipc_username = NULL; char *ipc_domain = NULL; char *ipc_password = NULL; @@ -729,22 +762,10 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, { ADS_STATUS ads_status; - if (!get_trust_pw_clear(domain->name, &machine_password, - &account_name, NULL)) - { - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - - if (asprintf(&machine_account, "%s$", account_name) == -1) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - if (asprintf(&machine_krb5_principal, "%s$@%s", account_name, - lp_realm()) == -1) - { - result = NT_STATUS_NO_MEMORY; + result = get_trust_creds(domain, &machine_password, + &machine_account, + &machine_krb5_principal); + if (!NT_STATUS_IS_OK(result)) { goto done; } -- cgit From 9104d2bf79e92ccdca3e6406bda9f0facea89ddb Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 11 Dec 2007 16:34:39 +0100 Subject: Make cm_connect_sam() try harder to connect autheticated. Even if the session setup was anonymous, try and collect trust creds with get_trust_creds() and use these before falling back to schannel. This is the first attempt to fix interdomain trusts. (get password policy and stuff) Michael (This used to be commit e180bbd45452435e981192028a0ad90078c04236) --- source3/winbindd/winbindd_cm.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index cc7a0cc671..cb366a293c 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1968,6 +1968,9 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring conn_pwd; struct dcinfo *p_dcinfo; + char *machine_password = NULL; + char *machine_account = NULL; + char *domain_name = NULL; result = init_dc_connection(domain); if (!NT_STATUS_IS_OK(result)) { @@ -1990,34 +1993,46 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, pwd_get_cleartext(&conn->cli->pwd, conn_pwd); if ((conn->cli->user_name[0] == '\0') || (conn->cli->domain[0] == '\0') || - (conn_pwd[0] == '\0')) { - DEBUG(10, ("cm_connect_sam: No no user available for " - "domain %s, trying schannel\n", conn->cli->domain)); + (conn_pwd[0] == '\0')) + { + result = get_trust_creds(domain, &machine_password, + &machine_account, NULL); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10, ("cm_connect_sam: No no user available for " + "domain %s, trying schannel\n", conn->cli->domain)); + goto schannel; + } + domain_name = domain->name; goto schannel; + } else { + machine_password = conn_pwd; + machine_account = conn->cli->user_name; + domain_name = conn->cli->domain; } + /* We have an authenticated connection. Use a NTLMSSP SPNEGO authenticated SAMR pipe with sign & seal. */ conn->samr_pipe = cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, PI_SAMR, PIPE_AUTH_LEVEL_PRIVACY, - conn->cli->domain, - conn->cli->user_name, - conn_pwd, &result); + domain_name, + machine_account, + machine_password, &result); if (conn->samr_pipe == NULL) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR " "pipe for domain %s using NTLMSSP " "authenticated pipe: user %s\\%s. Error was " - "%s\n", domain->name, conn->cli->domain, - conn->cli->user_name, nt_errstr(result))); + "%s\n", domain->name, domain_name, + machine_account, nt_errstr(result))); goto schannel; } DEBUG(10,("cm_connect_sam: connected to SAMR pipe for " "domain %s using NTLMSSP authenticated " "pipe: user %s\\%s\n", domain->name, - conn->cli->domain, conn->cli->user_name )); + domain_name, machine_account)); result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, @@ -2102,6 +2117,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, *cli = conn->samr_pipe; *sam_handle = conn->sam_domain_handle; + SAFE_FREE(machine_password); + SAFE_FREE(machine_account); return result; } -- cgit