summaryrefslogtreecommitdiffstats
path: root/source3/winbindd
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2013-07-27 11:30:13 +0200
committerStefan Metzmacher <metze@samba.org>2014-01-07 12:47:06 +0100
commit38d4dba37406515181e4d6f1a1faffc18e652e27 (patch)
treed7644727673b23e6167958e6c32422a2ab3a82d6 /source3/winbindd
parent11aed7cd3dbd967593b34a206f0802fd0002bf27 (diff)
downloadsamba-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.h9
-rw-r--r--source3/winbindd/winbindd_cm.c36
-rw-r--r--source3/winbindd/winbindd_pam.c136
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)) {