diff options
| author | Stefan Metzmacher <metze@samba.org> | 2013-07-27 11:30:13 +0200 |
|---|---|---|
| committer | Stefan Metzmacher <metze@samba.org> | 2014-01-07 12:47:06 +0100 |
| commit | 38d4dba37406515181e4d6f1a1faffc18e652e27 (patch) | |
| tree | d7644727673b23e6167958e6c32422a2ab3a82d6 /source3/winbindd | |
| parent | 11aed7cd3dbd967593b34a206f0802fd0002bf27 (diff) | |
| download | samba-38d4dba37406515181e4d6f1a1faffc18e652e27.tar.gz samba-38d4dba37406515181e4d6f1a1faffc18e652e27.tar.xz samba-38d4dba37406515181e4d6f1a1faffc18e652e27.zip | |
s3:rpc_client: make use of the new netlogon_creds_cli_context
This exchanges rpc_pipe_client->dc with rpc_pipe_client->netlogon_creds
and lets the secure channel session state be stored in node local database.
This is the proper fix for a large number of bugs:
https://bugzilla.samba.org/show_bug.cgi?id=6563
https://bugzilla.samba.org/show_bug.cgi?id=7944
https://bugzilla.samba.org/show_bug.cgi?id=7945
https://bugzilla.samba.org/show_bug.cgi?id=7568
https://bugzilla.samba.org/show_bug.cgi?id=8599
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source3/winbindd')
| -rw-r--r-- | source3/winbindd/winbindd.h | 9 | ||||
| -rw-r--r-- | source3/winbindd/winbindd_cm.c | 36 | ||||
| -rw-r--r-- | source3/winbindd/winbindd_pam.c | 136 |
3 files changed, 37 insertions, 144 deletions
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index afde6857f0..b5fc010d07 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -165,16 +165,7 @@ struct winbindd_domain { time_t startup_time; /* When we set "startup" true. monotonic clock */ bool startup; /* are we in the first 30 seconds after startup_time ? */ - bool can_do_samlogon_ex; /* Due to the lack of finer control what type - * of DC we have, let us try to do a - * credential-chain less samlogon_ex call - * with AD and schannel. If this fails with - * DCERPC_FAULT_OP_RNG_ERROR, then set this - * to False. This variable is around so that - * we don't have to try _ex every time. */ - bool can_do_ncacn_ip_tcp; - bool can_do_validation6; /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 5d920d0a78..d08d7de13f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2049,7 +2049,6 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) domain->active_directory ? "" : "NOT ")); domain->can_do_ncacn_ip_tcp = domain->active_directory; - domain->can_do_validation6 = domain->active_directory; domain->initialized = True; @@ -2250,7 +2249,6 @@ done: domain->name, domain->active_directory ? "" : "NOT ")); domain->can_do_ncacn_ip_tcp = domain->active_directory; - domain->can_do_validation6 = domain->active_directory; TALLOC_FREE(cli); @@ -2291,7 +2289,7 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain ) ***********************************************************************/ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, - struct netlogon_creds_CredentialState **ppdc) + struct netlogon_creds_cli_context **ppdc) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct rpc_pipe_client *netlogon_pipe; @@ -2308,11 +2306,11 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, /* Return a pointer to the struct netlogon_creds_CredentialState from the netlogon pipe. */ - if (!domain->conn.netlogon_pipe->dc) { + if (!domain->conn.netlogon_pipe->netlogon_creds) { return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */ } - *ppdc = domain->conn.netlogon_pipe->dc; + *ppdc = domain->conn.netlogon_pipe->netlogon_creds; return NT_STATUS_OK; } @@ -2321,7 +2319,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, { struct winbindd_cm_conn *conn; NTSTATUS status, result; - struct netlogon_creds_CredentialState *p_creds; + struct netlogon_creds_cli_context *p_creds; char *machine_password = NULL; char *machine_account = NULL; const char *domain_name = NULL; @@ -2433,7 +2431,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, status = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_samr, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, - domain->name, &p_creds, &conn->samr_pipe); + domain->name, p_creds, &conn->samr_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for " @@ -2536,7 +2534,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, struct rpc_pipe_client **cli) { struct winbindd_cm_conn *conn; - struct netlogon_creds_CredentialState *creds; + struct netlogon_creds_cli_context *creds; NTSTATUS status; DEBUG(10,("cm_connect_lsa_tcp\n")); @@ -2567,7 +2565,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, NCACN_IP_TCP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, - &creds, + creds, &conn->lsa_pipe_tcp); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n", @@ -2591,7 +2589,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, { struct winbindd_cm_conn *conn; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - struct netlogon_creds_CredentialState *p_creds; + struct netlogon_creds_cli_context *p_creds; result = init_dc_connection_rpc(domain); if (!NT_STATUS_IS_OK(result)) @@ -2664,7 +2662,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, result = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_lsarpc, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, - domain->name, &p_creds, &conn->lsa_pipe); + domain->name, p_creds, &conn->lsa_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " @@ -2828,10 +2826,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, no_schannel: if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - /* - * NetSamLogonEx only works for schannel - */ - domain->can_do_samlogon_ex = False; /* We're done - just keep the existing connection to NETLOGON * open */ @@ -2847,7 +2841,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, result = cli_rpc_pipe_open_schannel_with_key( conn->cli, &ndr_table_netlogon, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc, + DCERPC_AUTH_LEVEL_PRIVACY, domain->name, + netlogon_pipe->netlogon_creds, &conn->netlogon_pipe); /* We can now close the initial netlogon pipe. */ @@ -2861,15 +2856,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return result; } - /* - * Always try netr_LogonSamLogonEx. We will fall back for NT4 - * which gives DCERPC_FAULT_OP_RNG_ERROR (function not - * supported). We used to only try SamLogonEx for AD, but - * Samba DCs can also do it. And because we don't distinguish - * between Samba and NT4, always try it once. - */ - domain->can_do_samlogon_ex = true; - *cli = conn->netlogon_pipe; return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c356686488..39483a5d5e 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1228,8 +1228,6 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, do { struct rpc_pipe_client *netlogon_pipe; - const struct pipe_auth_data *auth; - uint32_t neg_flags = 0; ZERO_STRUCTP(info3); retry = false; @@ -1278,75 +1276,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, } netr_attempts = 0; - auth = netlogon_pipe->auth; - if (netlogon_pipe->dc) { - neg_flags = netlogon_pipe->dc->negotiate_flags; - } - - /* It is really important to try SamLogonEx here, - * because in a clustered environment, we want to use - * one machine account from multiple physical - * computers. - * - * With a normal SamLogon call, we must keep the - * credentials chain updated and intact between all - * users of the machine account (which would imply - * cross-node communication for every NTLM logon). - * - * (The credentials chain is not per NETLOGON pipe - * connection, but globally on the server/client pair - * by machine name). - * - * When using SamLogonEx, the credentials are not - * supplied, but the session key is implied by the - * wrapping SamLogon context. - * - * -- abartlet 21 April 2008 - * - * It's also important to use NetlogonValidationSamInfo4 (6), - * because it relies on the rpc transport encryption - * and avoids using the global netlogon schannel - * session key to en/decrypt secret information - * like the user_session_key for network logons. - * - * [MS-APDS] 3.1.5.2 NTLM Network Logon - * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and - * NETLOGON_NEG_AUTHENTICATED_RPC set together - * are the indication that the server supports - * NetlogonValidationSamInfo4 (6). And it must only - * be used if "SealSecureChannel" is used. - * - * -- metze 4 February 2011 - */ - - if (auth == NULL) { - domain->can_do_validation6 = false; - } else if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { - domain->can_do_validation6 = false; - } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { - domain->can_do_validation6 = false; - } else if (!(neg_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { - domain->can_do_validation6 = false; - } else if (!(neg_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { - domain->can_do_validation6 = false; - } - - if (domain->can_do_samlogon_ex && domain->can_do_validation6) { - result = rpccli_netlogon_sam_network_logon_ex( - netlogon_pipe, - mem_ctx, - logon_parameters, - server, /* server name */ - username, /* user name */ - domainname, /* target domain */ - workstation, /* workstation */ - chal, - 6, - lm_response, - nt_response, - info3); - } else { - result = rpccli_netlogon_sam_network_logon( + result = rpccli_netlogon_sam_network_logon( netlogon_pipe, mem_ctx, logon_parameters, @@ -1355,48 +1285,10 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, domainname, /* target domain */ workstation, /* workstation */ chal, - domain->can_do_validation6 ? 6 : 3, + -1, /* ignored */ lm_response, nt_response, info3); - } - - if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { - - /* - * It's likely that the server also does not support - * validation level 6 - */ - domain->can_do_validation6 = false; - - if (domain->can_do_samlogon_ex) { - DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " - "retrying with NetSamLogon\n")); - domain->can_do_samlogon_ex = false; - retry = true; - continue; - } - - - /* Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon - * (no Ex). This happens against old Samba - * DCs. Drop the connection. - */ - invalidate_cm_connection(&domain->conn); - result = NT_STATUS_LOGON_FAILURE; - break; - } - - if (domain->can_do_validation6 && - (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) || - NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) || - NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) { - DEBUG(3,("Got a DC that can not do validation level 6, " - "retrying with level 3\n")); - domain->can_do_validation6 = false; - retry = true; - continue; - } /* * we increment this after the "feature negotiation" @@ -1428,6 +1320,30 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, retry = true; } + if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + /* + * Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon + * (no Ex). This happens against old Samba + * DCs, if LogonSamLogonEx() fails with an error + * e.g. NT_STATUS_NO_SUCH_USER or NT_STATUS_WRONG_PASSWORD. + * + * The server will log something like this: + * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX. + * + * This sets the whole connection into a fault_state mode + * and all following request get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. + * + * This also happens to our retry with LogonSamLogonWithFlags() + * and LogonSamLogon(). + * + * In order to recover from this situation, we need to + * drop the connection. + */ + invalidate_cm_connection(&domain->conn); + result = NT_STATUS_LOGON_FAILURE; + break; + } + } while ( (attempts < 2) && retry ); if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT)) { |
