summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--source3/libnet/libnet_join.c3
-rw-r--r--source3/libnet/libnet_samsync.c19
-rw-r--r--source3/rpc_client/cli_netlogon.c436
-rw-r--r--source3/rpc_client/cli_pipe.c139
-rw-r--r--source3/rpc_client/cli_pipe.h2
-rw-r--r--source3/rpc_client/cli_pipe_schannel.c3
-rw-r--r--source3/rpc_client/rpc_client.h2
-rw-r--r--source3/rpcclient/cmd_netlogon.c57
-rw-r--r--source3/winbindd/winbindd.h9
-rw-r--r--source3/winbindd/winbindd_cm.c36
-rw-r--r--source3/winbindd/winbindd_pam.c136
-rwxr-xr-xsource3/wscript_build6
12 files changed, 250 insertions, 598 deletions
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index c1eccda1af..5dc620f270 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -1279,7 +1279,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name,
status = cli_rpc_pipe_open_schannel_with_key(
cli, &ndr_table_netlogon, NCACN_NP,
DCERPC_AUTH_LEVEL_PRIVACY,
- netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd);
+ netbios_domain_name,
+ netlogon_pipe->netlogon_creds, &pipe_hnd);
cli_shutdown(cli);
diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c
index a10378558c..02d3fc6ce7 100644
--- a/source3/libnet/libnet_samsync.c
+++ b/source3/libnet/libnet_samsync.c
@@ -30,6 +30,7 @@
#include "../librpc/gen_ndr/ndr_netlogon_c.h"
#include "../libcli/security/security.h"
#include "messages.h"
+#include "../libcli/auth/netlogon_creds_cli.h"
/**
* Fix up the delta, dealing with encryption issues so that the final
@@ -213,8 +214,15 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
do {
struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
+ struct netlogon_creds_CredentialState *creds = NULL;
- netlogon_creds_client_authenticator(ctx->cli->dc, &credential);
+ status = netlogon_creds_cli_lock(ctx->cli->netlogon_creds,
+ mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ netlogon_creds_client_authenticator(creds, &credential);
if (ctx->single_object_replication &&
!ctx->force_full_replication) {
@@ -254,28 +262,33 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
}
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(creds);
return status;
}
/* Check returned credentials. */
- if (!netlogon_creds_client_check(ctx->cli->dc,
+ if (!netlogon_creds_client_check(creds,
&return_authenticator.cred)) {
+ TALLOC_FREE(creds);
DEBUG(0,("credentials chain check failed\n"));
return NT_STATUS_ACCESS_DENIED;
}
if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
+ TALLOC_FREE(creds);
return result;
}
if (NT_STATUS_IS_ERR(result)) {
+ TALLOC_FREE(creds);
break;
}
samsync_fix_delta_array(mem_ctx,
- ctx->cli->dc,
+ creds,
database_id,
delta_enum_array);
+ TALLOC_FREE(creds);
/* Process results */
callback_status = ctx->ops->process_objects(mem_ctx, database_id,
diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index 5e8a2fca41..fcd24d6f4c 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -23,11 +23,13 @@
#include "includes.h"
#include "rpc_client/rpc_client.h"
#include "../libcli/auth/libcli_auth.h"
+#include "../libcli/auth/netlogon_creds_cli.h"
#include "../librpc/gen_ndr/ndr_netlogon_c.h"
#include "rpc_client/cli_netlogon.h"
#include "rpc_client/init_netlogon.h"
#include "rpc_client/util_netlogon.h"
#include "../libcli/security/security.h"
+#include "lib/param/param.h"
/****************************************************************************
Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
@@ -44,113 +46,81 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
enum netr_SchannelType sec_chan_type,
uint32_t *neg_flags_inout)
{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct loadparm_context *lp_ctx;
NTSTATUS status;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- struct netr_Credential clnt_chal_send;
- struct netr_Credential srv_chal_recv;
struct samr_Password password;
- bool retried = false;
fstring mach_acct;
- uint32_t neg_flags = *neg_flags_inout;
struct dcerpc_binding_handle *b = cli->binding_handle;
+ struct netlogon_creds_CredentialState *creds = NULL;
if (!ndr_syntax_id_equal(&cli->abstract_syntax,
&ndr_table_netlogon.syntax_id)) {
+ TALLOC_FREE(frame);
return NT_STATUS_INVALID_PARAMETER;
}
- TALLOC_FREE(cli->dc);
-
- /* Store the machine account password we're going to use. */
- memcpy(password.hash, machine_pwd, 16);
-
- fstr_sprintf( mach_acct, "%s$", machine_account);
-
- again:
- /* Create the client challenge. */
- generate_random_buffer(clnt_chal_send.data, 8);
-
- /* Get the server challenge. */
- status = dcerpc_netr_ServerReqChallenge(b, talloc_tos(),
- cli->srv_name_slash,
- clnt_name,
- &clnt_chal_send,
- &srv_chal_recv,
- &result);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- if (!NT_STATUS_IS_OK(result)) {
- return result;
+ if (!strequal(lp_netbios_name(), clnt_name)) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_INVALID_PARAMETER;
}
- /* Calculate the session key and client credentials */
+ TALLOC_FREE(cli->netlogon_creds);
- cli->dc = netlogon_creds_client_init(cli,
- mach_acct,
- clnt_name,
- sec_chan_type,
- &clnt_chal_send,
- &srv_chal_recv,
- &password,
- &clnt_chal_send,
- neg_flags);
+ fstr_sprintf( mach_acct, "%s$", machine_account);
- if (!cli->dc) {
+ lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
+ if (lp_ctx == NULL) {
+ TALLOC_FREE(frame);
return NT_STATUS_NO_MEMORY;
}
-
- /*
- * Send client auth-2 challenge and receive server repy.
- */
-
- status = dcerpc_netr_ServerAuthenticate2(b, talloc_tos(),
- cli->srv_name_slash,
- cli->dc->account_name,
- sec_chan_type,
- cli->dc->computer_name,
- &clnt_chal_send, /* input. */
- &srv_chal_recv, /* output. */
- &neg_flags,
- &result);
+ status = netlogon_creds_cli_context_global(lp_ctx,
+ NULL, /* msg_ctx */
+ mach_acct,
+ sec_chan_type,
+ server_name,
+ domain,
+ cli, &cli->netlogon_creds);
+ talloc_unlink(frame, lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
return status;
}
- /* we might be talking to NT4, so let's downgrade in that case and retry
- * with the returned neg_flags - gd */
- if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
- retried = true;
- TALLOC_FREE(cli->dc);
- goto again;
+ status = netlogon_creds_cli_get(cli->netlogon_creds,
+ frame, &creds);
+ if (NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("rpccli_netlogon_setup_creds: server %s using "
+ "cached credential\n",
+ cli->desthost));
+ *neg_flags_inout = creds->negotiate_flags;
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
}
- if (!NT_STATUS_IS_OK(result)) {
- return result;
- }
-
- /*
- * Check the returned value using the initial
- * server received challenge.
- */
-
- if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) {
- /*
- * Server replied with bad credential. Fail.
- */
- DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
- "replied with bad credential\n",
- cli->desthost ));
- return NT_STATUS_ACCESS_DENIED;
- }
+ /* Store the machine account password we're going to use. */
+ memcpy(password.hash, machine_pwd, 16);
DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
"chain established.\n",
cli->desthost ));
- cli->dc->negotiate_flags = neg_flags;
- *neg_flags_inout = neg_flags;
+ status = netlogon_creds_cli_auth(cli->netlogon_creds, b,
+ password, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ status = netlogon_creds_cli_get(cli->netlogon_creds,
+ frame, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ *neg_flags_inout = creds->negotiate_flags;
+ TALLOC_FREE(frame);
return NT_STATUS_OK;
}
@@ -163,20 +133,16 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
const char *username,
const char *password,
const char *workstation,
- uint16_t validation_level,
+ uint16_t _ignored_validation_level,
int logon_type)
{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
NTSTATUS status;
- struct netr_Authenticator clnt_creds;
- struct netr_Authenticator ret_creds;
union netr_LogonLevel *logon;
- union netr_Validation validation;
- uint8_t authoritative;
+ uint16_t validation_level = 0;
+ union netr_Validation *validation = NULL;
+ uint8_t authoritative = 0;
+ uint32_t flags = 0;
fstring clnt_name_slash;
- struct dcerpc_binding_handle *b = cli->binding_handle;
-
- ZERO_STRUCT(ret_creds);
logon = talloc_zero(mem_ctx, union netr_LogonLevel);
if (!logon) {
@@ -191,8 +157,6 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
/* Initialise input parameters */
- netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
-
switch (logon_type) {
case NetlogonInteractiveInformation: {
@@ -208,17 +172,6 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
- if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
- netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16);
- netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16);
- } else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
- netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
- netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
- } else {
- netlogon_creds_des_encrypt(cli->dc, &lmpassword);
- netlogon_creds_des_encrypt(cli->dc, &ntpassword);
- }
-
password_info->identity_info.domain_name.string = domain;
password_info->identity_info.parameter_control = logon_parameters;
password_info->identity_info.logon_id_low = 0xdead;
@@ -281,28 +234,20 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
return NT_STATUS_INVALID_INFO_CLASS;
}
- status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
- cli->srv_name_slash,
- lp_netbios_name(),
- &clnt_creds,
- &ret_creds,
- logon_type,
- logon,
- validation_level,
- &validation,
- &authoritative,
- &result);
+ status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
+ cli->binding_handle,
+ logon_type,
+ logon,
+ mem_ctx,
+ &validation_level,
+ &validation,
+ &authoritative,
+ &flags);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- /* Always check returned credentials */
- if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
- DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- return result;
+ return NT_STATUS_OK;
}
static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
@@ -366,29 +311,24 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
const char *domain,
const char *workstation,
const uint8 chal[8],
- uint16_t validation_level,
+ uint16_t _ignored_validation_level,
DATA_BLOB lm_response,
DATA_BLOB nt_response,
struct netr_SamInfo3 **info3)
{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
NTSTATUS status;
const char *workstation_name_slash;
- const char *server_name_slash;
- struct netr_Authenticator clnt_creds;
- struct netr_Authenticator ret_creds;
union netr_LogonLevel *logon = NULL;
struct netr_NetworkInfo *network_info;
- uint8_t authoritative;
- union netr_Validation validation;
+ uint16_t validation_level = 0;
+ union netr_Validation *validation = NULL;
+ uint8_t authoritative = 0;
+ uint32_t flags = 0;
struct netr_ChallengeResponse lm;
struct netr_ChallengeResponse nt;
- struct dcerpc_binding_handle *b = cli->binding_handle;
*info3 = NULL;
- ZERO_STRUCT(ret_creds);
-
ZERO_STRUCT(lm);
ZERO_STRUCT(nt);
@@ -402,21 +342,13 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
return NT_STATUS_NO_MEMORY;
}
- netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
-
- if (server[0] != '\\' && server[1] != '\\') {
- server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
- } else {
- server_name_slash = server;
- }
-
if (workstation[0] != '\\' && workstation[1] != '\\') {
workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
} else {
workstation_name_slash = workstation;
}
- if (!workstation_name_slash || !server_name_slash) {
+ if (!workstation_name_slash) {
DEBUG(0, ("talloc_asprintf failed!\n"));
return NT_STATUS_NO_MEMORY;
}
@@ -443,40 +375,27 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
/* Marshall data and send request */
- status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
- server_name_slash,
- lp_netbios_name(),
- &clnt_creds,
- &ret_creds,
- NetlogonNetworkInformation,
- logon,
- validation_level,
- &validation,
- &authoritative,
- &result);
+ status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
+ cli->binding_handle,
+ NetlogonNetworkInformation,
+ logon,
+ mem_ctx,
+ &validation_level,
+ &validation,
+ &authoritative,
+ &flags);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- /* Always check returned credentials. */
- if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
- DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (!NT_STATUS_IS_OK(result)) {
- return result;
- }
-
- netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level,
- &validation);
-
- result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3);
- if (!NT_STATUS_IS_OK(result)) {
- return result;
+ status = map_validation_to_info3(mem_ctx,
+ validation_level, validation,
+ info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- return result;
+ return NT_STATUS_OK;
}
NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
@@ -492,100 +411,18 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
DATA_BLOB nt_response,
struct netr_SamInfo3 **info3)
{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- NTSTATUS status;
- const char *workstation_name_slash;
- const char *server_name_slash;
- union netr_LogonLevel *logon = NULL;
- struct netr_NetworkInfo *network_info;
- uint8_t authoritative;
- union netr_Validation validation;
- struct netr_ChallengeResponse lm;
- struct netr_ChallengeResponse nt;
- uint32_t flags = 0;
- struct dcerpc_binding_handle *b = cli->binding_handle;
-
- *info3 = NULL;
-
- ZERO_STRUCT(lm);
- ZERO_STRUCT(nt);
-
- logon = talloc_zero(mem_ctx, union netr_LogonLevel);
- if (!logon) {
- return NT_STATUS_NO_MEMORY;
- }
-
- network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
- if (!network_info) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (server[0] != '\\' && server[1] != '\\') {
- server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
- } else {
- server_name_slash = server;
- }
-
- if (workstation[0] != '\\' && workstation[1] != '\\') {
- workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
- } else {
- workstation_name_slash = workstation;
- }
-
- if (!workstation_name_slash || !server_name_slash) {
- DEBUG(0, ("talloc_asprintf failed!\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- /* Initialise input parameters */
-
- lm.data = lm_response.data;
- lm.length = lm_response.length;
- nt.data = nt_response.data;
- nt.length = nt_response.length;
-
- network_info->identity_info.domain_name.string = domain;
- network_info->identity_info.parameter_control = logon_parameters;
- network_info->identity_info.logon_id_low = 0xdead;
- network_info->identity_info.logon_id_high = 0xbeef;
- network_info->identity_info.account_name.string = username;
- network_info->identity_info.workstation.string = workstation_name_slash;
-
- memcpy(network_info->challenge, chal, 8);
- network_info->nt = nt;
- network_info->lm = lm;
-
- logon->network = network_info;
-
- /* Marshall data and send request */
-
- status = dcerpc_netr_LogonSamLogonEx(b, mem_ctx,
- server_name_slash,
- lp_netbios_name(),
- NetlogonNetworkInformation,
- logon,
- validation_level,
- &validation,
- &authoritative,
- &flags,
- &result);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (!NT_STATUS_IS_OK(result)) {
- return result;
- }
-
- netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level,
- &validation);
-
- result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3);
- if (!NT_STATUS_IS_OK(result)) {
- return result;
- }
-
- return result;
+ return rpccli_netlogon_sam_network_logon(cli,
+ mem_ctx,
+ logon_parameters,
+ server,
+ username,
+ domain,
+ workstation,
+ chal,
+ validation_level,
+ lm_response,
+ nt_response,
+ info3);
}
/*********************************************************
@@ -605,11 +442,9 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
const unsigned char new_trust_passwd_hash[16],
enum netr_SchannelType sec_channel_type)
{
- NTSTATUS result, status;
- struct netr_Authenticator clnt_creds, srv_cred;
- struct dcerpc_binding_handle *b = cli->binding_handle;
+ NTSTATUS result;
- if (!cli->dc) {
+ if (cli->netlogon_creds == NULL) {
uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS |
NETLOGON_NEG_SUPPORTS_AES;
result = rpccli_netlogon_setup_creds(cli,
@@ -627,77 +462,16 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
}
}
- netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
-
- if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
-
- struct netr_CryptPassword new_password;
- uint32_t old_timeout;
-
- init_netr_CryptPassword(new_trust_pwd_cleartext,
- cli->dc,
- &new_password);
-
- old_timeout = dcerpc_binding_handle_set_timeout(b, 600000);
-
- status = dcerpc_netr_ServerPasswordSet2(b, mem_ctx,
- cli->srv_name_slash,
- cli->dc->account_name,
- sec_channel_type,
- cli->dc->computer_name,
- &clnt_creds,
- &srv_cred,
- &new_password,
- &result);
-
- dcerpc_binding_handle_set_timeout(b, old_timeout);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("dcerpc_netr_ServerPasswordSet2 failed: %s\n",
- nt_errstr(status)));
- return status;
- }
- } else {
-
- struct samr_Password new_password;
- uint32_t old_timeout;
-
- memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash));
- netlogon_creds_des_encrypt(cli->dc, &new_password);
-
- old_timeout = dcerpc_binding_handle_set_timeout(b, 600000);
-
- status = dcerpc_netr_ServerPasswordSet(b, mem_ctx,
- cli->srv_name_slash,
- cli->dc->account_name,
- sec_channel_type,
- cli->dc->computer_name,
- &clnt_creds,
- &srv_cred,
- &new_password,
- &result);
-
- dcerpc_binding_handle_set_timeout(b, old_timeout);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("dcerpc_netr_ServerPasswordSet failed: %s\n",
- nt_errstr(status)));
- return status;
- }
- }
-
- /* Always check returned credentials. */
- if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
- DEBUG(0,("credentials chain check failed\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
+ result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds,
+ cli->binding_handle,
+ new_trust_pwd_cleartext,
+ NULL); /* new_version */
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(0,("dcerpc_netr_ServerPasswordSet{2} failed: %s\n",
+ DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n",
nt_errstr(result)));
return result;
}
- return result;
+ return NT_STATUS_OK;
}
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index b6908be7e2..7f79046fc7 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -24,6 +24,7 @@
#include "librpc/gen_ndr/ndr_epmapper_c.h"
#include "../librpc/gen_ndr/ndr_dssetup.h"
#include "../libcli/auth/schannel.h"
+#include "../libcli/auth/netlogon_creds_cli.h"
#include "auth_generic.h"
#include "librpc/gen_ndr/ndr_dcerpc.h"
#include "librpc/gen_ndr/ndr_netlogon_c.h"
@@ -3024,34 +3025,39 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
enum dcerpc_transport_t transport,
enum dcerpc_AuthLevel auth_level,
const char *domain,
- struct netlogon_creds_CredentialState **pdc,
+ struct netlogon_creds_cli_context *netlogon_creds,
struct rpc_pipe_client **_rpccli)
{
struct rpc_pipe_client *rpccli;
struct pipe_auth_data *rpcauth;
+ struct netlogon_creds_CredentialState *creds = NULL;
NTSTATUS status;
- NTSTATUS result;
- struct netlogon_creds_CredentialState save_creds;
- struct netr_Authenticator auth;
- struct netr_Authenticator return_auth;
- union netr_Capabilities capabilities;
const char *target_service = table->authservices->names[0];
+ int rpc_pipe_bind_dbglvl = 0;
status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+ status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(rpccli);
+ return status;
+ }
+
status = rpccli_generic_bind_data(rpccli,
DCERPC_AUTH_TYPE_SCHANNEL,
auth_level,
NULL,
target_service,
domain,
- (*pdc)->computer_name,
+ creds->computer_name,
NULL,
CRED_AUTO_USE_KERBEROS,
- *pdc,
+ creds,
&rpcauth);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
@@ -3060,120 +3066,43 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
return status;
}
- /*
- * The credentials on a new netlogon pipe are the ones we are passed
- * in - copy them over
- *
- * This may get overwritten... in rpc_pipe_bind()...
- */
- rpccli->dc = netlogon_creds_copy(rpccli, *pdc);
- if (rpccli->dc == NULL) {
- TALLOC_FREE(rpccli);
- return NT_STATUS_NO_MEMORY;
- }
-
status = rpc_pipe_bind(rpccli, rpcauth);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
+ rpc_pipe_bind_dbglvl = 1;
+ netlogon_creds_cli_delete(netlogon_creds, &creds);
+ }
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
- "cli_rpc_pipe_bind failed with error %s\n",
- nt_errstr(status) ));
+ DEBUG(rpc_pipe_bind_dbglvl,
+ ("cli_rpc_pipe_open_schannel_with_key: "
+ "rpc_pipe_bind failed with error %s\n",
+ nt_errstr(status)));
TALLOC_FREE(rpccli);
return status;
}
- if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
- goto done;
- }
-
- save_creds = *rpccli->dc;
- ZERO_STRUCT(return_auth);
- ZERO_STRUCT(capabilities);
+ TALLOC_FREE(creds);
- netlogon_creds_client_authenticator(&save_creds, &auth);
-
- status = dcerpc_netr_LogonGetCapabilities(rpccli->binding_handle,
- talloc_tos(),
- rpccli->srv_name_slash,
- save_creds.computer_name,
- &auth, &return_auth,
- 1, &capabilities,
- &result);
- if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
- if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
- DEBUG(5, ("AES was negotiated and the error was %s - "
- "downgrade detected\n",
- nt_errstr(status)));
- TALLOC_FREE(rpccli);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
-
- /* This is probably an old Samba Version */
- DEBUG(5, ("We are checking against an NT or old Samba - %s\n",
- nt_errstr(status)));
+ if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
goto done;
}
+ status = netlogon_creds_cli_check(netlogon_creds,
+ rpccli->binding_handle);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n",
+ DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
nt_errstr(status)));
TALLOC_FREE(rpccli);
return status;
}
- if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
- if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
- /* This means AES isn't supported. */
- DEBUG(5, ("AES was negotiated and the result was %s - "
- "downgrade detected\n",
- nt_errstr(result)));
- TALLOC_FREE(rpccli);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
-
- /* This is probably an old Windows version */
- DEBUG(5, ("We are checking against an win2k3 or Samba - %s\n",
- nt_errstr(result)));
- goto done;
- }
-
- /*
- * We need to check the credential state here, cause win2k3 and earlier
- * returns NT_STATUS_NOT_IMPLEMENTED
- */
- if (!netlogon_creds_client_check(&save_creds, &return_auth.cred)) {
- /*
- * Server replied with bad credential. Fail.
- */
- DEBUG(0,("cli_rpc_pipe_open_schannel_with_key: server %s "
- "replied with bad credential\n",
- rpccli->desthost));
- TALLOC_FREE(rpccli);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
- *rpccli->dc = save_creds;
-
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n",
- nt_errstr(result)));
- TALLOC_FREE(rpccli);
- return result;
- }
-
- if (!(save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) {
- /* This means AES isn't supported. */
- DEBUG(5, ("AES is not negotiated, but netr_LogonGetCapabilities "
- "was OK - downgrade detected\n"));
- TALLOC_FREE(rpccli);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
- }
-
- if (save_creds.negotiate_flags != capabilities.server_capabilities) {
- DEBUG(0, ("The client capabilities don't match the server "
- "capabilities: local[0x%08X] remote[0x%08X]\n",
- save_creds.negotiate_flags,
- capabilities.server_capabilities));
+ status = netlogon_creds_cli_context_copy(netlogon_creds,
+ rpccli,
+ &rpccli->netlogon_creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("netlogon_creds_cli_context_copy failed with %s\n",
+ nt_errstr(status)));
TALLOC_FREE(rpccli);
- return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ return status;
}
done:
diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h
index 1bfb551cf3..4e9f84a333 100644
--- a/source3/rpc_client/cli_pipe.h
+++ b/source3/rpc_client/cli_pipe.h
@@ -98,7 +98,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
enum dcerpc_transport_t transport,
enum dcerpc_AuthLevel auth_level,
const char *domain,
- struct netlogon_creds_CredentialState **pdc,
+ struct netlogon_creds_cli_context *netlogon_creds,
struct rpc_pipe_client **presult);
NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c
index aaae44b512..e3d65c8620 100644
--- a/source3/rpc_client/cli_pipe_schannel.c
+++ b/source3/rpc_client/cli_pipe_schannel.c
@@ -112,7 +112,8 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
}
status = cli_rpc_pipe_open_schannel_with_key(
- cli, table, transport, auth_level, domain, &netlogon_pipe->dc,
+ cli, table, transport, auth_level, domain,
+ netlogon_pipe->netlogon_creds,
&result);
/* Now we've bound using the session key we can close the netlog pipe. */
diff --git a/source3/rpc_client/rpc_client.h b/source3/rpc_client/rpc_client.h
index 8024f01821..7c4cceb863 100644
--- a/source3/rpc_client/rpc_client.h
+++ b/source3/rpc_client/rpc_client.h
@@ -50,7 +50,7 @@ struct rpc_pipe_client {
struct pipe_auth_data *auth;
/* The following is only non-null on a netlogon client pipe. */
- struct netlogon_creds_CredentialState *dc;
+ struct netlogon_creds_cli_context *netlogon_creds;
};
#endif /* _RPC_CLIENT_H */
diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c
index d92434b23c..2e0b5e5a87 100644
--- a/source3/rpcclient/cmd_netlogon.c
+++ b/source3/rpcclient/cmd_netlogon.c
@@ -26,6 +26,7 @@
#include "../librpc/gen_ndr/ndr_netlogon_c.h"
#include "rpc_client/cli_netlogon.h"
#include "secrets.h"
+#include "../libcli/auth/netlogon_creds_cli.h"
static WERROR cmd_netlogon_logon_ctrl2(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx, int argc,
@@ -630,8 +631,15 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli,
do {
struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
+ struct netlogon_creds_CredentialState *creds = NULL;
- netlogon_creds_client_authenticator(cli->dc, &credential);
+ status = netlogon_creds_cli_lock(cli->netlogon_creds,
+ mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ netlogon_creds_client_authenticator(creds, &credential);
status = dcerpc_netr_DatabaseSync2(b, mem_ctx,
logon_server,
@@ -645,15 +653,18 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli,
0xffff,
&result);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(creds);
return status;
}
/* Check returned credentials. */
- if (!netlogon_creds_client_check(cli->dc,
+ if (!netlogon_creds_client_check(creds,
&return_authenticator.cred)) {
DEBUG(0,("credentials chain check failed\n"));
+ TALLOC_FREE(creds);
return NT_STATUS_ACCESS_DENIED;
}
+ TALLOC_FREE(creds);
if (NT_STATUS_IS_ERR(result)) {
break;
@@ -699,8 +710,15 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli,
do {
struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
+ struct netlogon_creds_CredentialState *creds = NULL;
+
+ status = netlogon_creds_cli_lock(cli->netlogon_creds,
+ mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- netlogon_creds_client_authenticator(cli->dc, &credential);
+ netlogon_creds_client_authenticator(creds, &credential);
status = dcerpc_netr_DatabaseDeltas(b, mem_ctx,
logon_server,
@@ -713,15 +731,18 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli,
0xffff,
&result);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(creds);
return status;
}
/* Check returned credentials. */
- if (!netlogon_creds_client_check(cli->dc,
+ if (!netlogon_creds_client_check(creds,
&return_authenticator.cred)) {
DEBUG(0,("credentials chain check failed\n"));
+ TALLOC_FREE(creds);
return NT_STATUS_ACCESS_DENIED;
}
+ TALLOC_FREE(creds);
if (NT_STATUS_IS_ERR(result)) {
break;
@@ -1129,6 +1150,7 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli,
struct netr_ChangeLogEntry e;
uint32_t rid = 500;
struct dcerpc_binding_handle *b = cli->binding_handle;
+ struct netlogon_creds_CredentialState *creds = NULL;
if (argc > 2) {
fprintf(stderr, "Usage: %s <user rid>\n", argv[0]);
@@ -1158,7 +1180,13 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli,
return status;
}
- netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
+ status = netlogon_creds_cli_lock(cli->netlogon_creds,
+ mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ netlogon_creds_client_authenticator(creds, &clnt_creds);
ZERO_STRUCT(e);
@@ -1176,13 +1204,16 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli,
&delta_enum_array,
&result);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(creds);
return status;
}
- if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
+ if (!netlogon_creds_client_check(creds, &srv_cred.cred)) {
DEBUG(0,("credentials chain check failed\n"));
+ TALLOC_FREE(creds);
return NT_STATUS_ACCESS_DENIED;
}
+ TALLOC_FREE(creds);
return result;
}
@@ -1198,6 +1229,7 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli,
union netr_Capabilities capabilities;
uint32_t level = 1;
struct dcerpc_binding_handle *b = cli->binding_handle;
+ struct netlogon_creds_CredentialState *creds = NULL;
if (argc > 2) {
fprintf(stderr, "Usage: %s <level>\n", argv[0]);
@@ -1210,7 +1242,13 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli,
ZERO_STRUCT(return_authenticator);
- netlogon_creds_client_authenticator(cli->dc, &credential);
+ status = netlogon_creds_cli_lock(cli->netlogon_creds,
+ mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ netlogon_creds_client_authenticator(creds, &credential);
status = dcerpc_netr_LogonGetCapabilities(b, mem_ctx,
cli->desthost,
@@ -1221,14 +1259,17 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli,
&capabilities,
&result);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(creds);
return status;
}
- if (!netlogon_creds_client_check(cli->dc,
+ if (!netlogon_creds_client_check(creds,
&return_authenticator.cred)) {
DEBUG(0,("credentials chain check failed\n"));
+ TALLOC_FREE(creds);
return NT_STATUS_ACCESS_DENIED;
}
+ TALLOC_FREE(creds);
printf("capabilities: 0x%08x\n", capabilities.server_capabilities);
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)) {
diff --git a/source3/wscript_build b/source3/wscript_build
index ecddfd9dca..c5dc521cf6 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -84,8 +84,8 @@ bld.SAMBA3_LIBRARY('msrpc3',
deps='''ndr ndr-standard
RPC_NDR_EPMAPPER NTLMSSP_COMMON COMMON_SCHANNEL LIBCLI_AUTH
LIBTSOCKET gse dcerpc-binding
- libsmb
- ndr-table''',
+ libsmb ndr-table NETLOGON_CREDS_CLI
+ ''',
private_library=True)
bld.SAMBA3_LIBRARY('gpo',
@@ -763,7 +763,7 @@ bld.SAMBA3_LIBRARY('libcli_lsa3',
bld.SAMBA3_LIBRARY('libcli_netlogon3',
source='rpc_client/cli_netlogon.c rpc_client/util_netlogon.c',
- deps='RPC_NDR_NETLOGON INIT_NETLOGON cliauth param',
+ deps='msrpc3 RPC_NDR_NETLOGON INIT_NETLOGON cliauth param NETLOGON_CREDS_CLI',
private_library=True)
bld.SAMBA3_LIBRARY('cli_spoolss',