More forest trust related patches
Stefan (metze) Metzmacher
metze at samba.org
Tue Feb 10 01:41:29 MST 2015
Hi,
there're some more patches ready in my master4-forest-ok branch.
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master4-forest-ok
Please review and push:-)
Thanks!
metze
-------------- next part --------------
From 4c1381c5872099724c65c1a61fb96973eecafab9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 09:06:32 +0100
Subject: [PATCH 01/17] auth/credentials: add a missing talloc check to
cli_credentials_set_nt_hash()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
auth/credentials/credentials_ntlm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c
index 5e9aeed..f339c9b 100644
--- a/auth/credentials/credentials_ntlm.c
+++ b/auth/credentials/credentials_ntlm.c
@@ -276,6 +276,9 @@ _PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
cli_credentials_set_password(cred, NULL, obtained);
if (nt_hash) {
cred->nt_hash = talloc(cred, struct samr_Password);
+ if (cred->nt_hash == NULL) {
+ return false;
+ }
*cred->nt_hash = *nt_hash;
} else {
cred->nt_hash = NULL;
--
1.9.1
From f732938da5a27793e36227b1a40b58ba8b887b41 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 09:04:42 +0100
Subject: [PATCH 02/17] auth/credentials: add
cli_credentials_[g|s]et_old_nt_hash()
The machine and trust accounts it's important to retry
netr_Authenticate3() with the previous (old) nt_hash.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
auth/credentials/credentials.c | 42 +++++++++++++++++++++++++++++++++
auth/credentials/credentials.h | 4 ++++
auth/credentials/credentials_internal.h | 1 +
auth/credentials/credentials_ntlm.c | 17 +++++++++++++
4 files changed, 64 insertions(+)
diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c
index a9e4fc8..42aa2a3 100644
--- a/auth/credentials/credentials.c
+++ b/auth/credentials/credentials.c
@@ -70,6 +70,7 @@ _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
cred->bind_dn = NULL;
cred->nt_hash = NULL;
+ cred->old_nt_hash = NULL;
cred->lm_response.data = NULL;
cred->lm_response.length = 0;
@@ -481,6 +482,7 @@ _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
/* Don't print the actual password in talloc memory dumps */
talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password");
}
+ cred->old_nt_hash = NULL;
return true;
}
@@ -525,6 +527,46 @@ _PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credential
}
/**
+ * Obtain the old password, in the form MD4(unicode(password)) for this credentials context.
+ *
+ * Sometimes we only have this much of the password, while the rest of
+ * the time this call avoids calling E_md4hash themselves.
+ *
+ * @param cred credentials context
+ * @retval If set, the cleartext password, otherwise NULL
+ */
+_PUBLIC_ struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
+ TALLOC_CTX *mem_ctx)
+{
+ const char *old_password = NULL;
+
+ if (cred->old_nt_hash != NULL) {
+ struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
+ if (!nt_hash) {
+ return NULL;
+ }
+
+ *nt_hash = *cred->old_nt_hash;
+
+ return nt_hash;
+ }
+
+ old_password = cli_credentials_get_old_password(cred);
+ if (old_password) {
+ struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
+ if (!nt_hash) {
+ return NULL;
+ }
+
+ E_md4hash(old_password, nt_hash->hash);
+
+ return nt_hash;
+ }
+
+ return NULL;
+}
+
+/**
* Obtain the 'short' or 'NetBIOS' domain for this credentials context.
* @param cred credentials context
* @retval The domain set on this context.
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index 814f016..d875fb5 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -146,6 +146,8 @@ struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx);
void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained);
struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
TALLOC_CTX *mem_ctx);
+struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
+ TALLOC_CTX *mem_ctx);
bool cli_credentials_set_realm(struct cli_credentials *cred,
const char *val,
enum credentials_obtained obtained);
@@ -197,6 +199,8 @@ bool cli_credentials_set_utf16_password(struct cli_credentials *cred,
bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
const struct samr_Password *nt_hash,
enum credentials_obtained obtained);
+bool cli_credentials_set_old_nt_hash(struct cli_credentials *cred,
+ const struct samr_Password *nt_hash);
bool cli_credentials_set_ntlm_response(struct cli_credentials *cred,
const DATA_BLOB *lm_response,
const DATA_BLOB *nt_response,
diff --git a/auth/credentials/credentials_internal.h b/auth/credentials/credentials_internal.h
index d05d153..aa01ccc 100644
--- a/auth/credentials/credentials_internal.h
+++ b/auth/credentials/credentials_internal.h
@@ -60,6 +60,7 @@ struct cli_credentials {
/* Allows authentication from a keytab or similar */
struct samr_Password *nt_hash;
+ struct samr_Password *old_nt_hash;
/* Allows NTLM pass-though authentication */
DATA_BLOB lm_response;
diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c
index f339c9b..327cf13 100644
--- a/auth/credentials/credentials_ntlm.c
+++ b/auth/credentials/credentials_ntlm.c
@@ -289,6 +289,23 @@ _PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
return false;
}
+_PUBLIC_ bool cli_credentials_set_old_nt_hash(struct cli_credentials *cred,
+ const struct samr_Password *nt_hash)
+{
+ cli_credentials_set_old_password(cred, NULL, CRED_SPECIFIED);
+ if (nt_hash) {
+ cred->old_nt_hash = talloc(cred, struct samr_Password);
+ if (cred->old_nt_hash == NULL) {
+ return false;
+ }
+ *cred->old_nt_hash = *nt_hash;
+ } else {
+ cred->old_nt_hash = NULL;
+ }
+
+ return true;
+}
+
_PUBLIC_ bool cli_credentials_set_ntlm_response(struct cli_credentials *cred,
const DATA_BLOB *lm_response,
const DATA_BLOB *nt_response,
--
1.9.1
From 66719ee454712b237c4048ec452d09486b1983ce Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 30 Jan 2015 16:20:27 +0000
Subject: [PATCH 03/17] auth/credentials: add
cli_credentials_set_old_utf16_password()
This is required to set the previous trust account password.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
auth/credentials/credentials.h | 2 ++
auth/credentials/credentials_ntlm.c | 47 +++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h
index d875fb5..fdedd63 100644
--- a/auth/credentials/credentials.h
+++ b/auth/credentials/credentials.h
@@ -196,6 +196,8 @@ void cli_credentials_set_kvno(struct cli_credentials *cred,
bool cli_credentials_set_utf16_password(struct cli_credentials *cred,
const DATA_BLOB *password_utf16,
enum credentials_obtained obtained);
+bool cli_credentials_set_old_utf16_password(struct cli_credentials *cred,
+ const DATA_BLOB *password_utf16);
bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
const struct samr_Password *nt_hash,
enum credentials_obtained obtained);
diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c
index 327cf13..4e12277 100644
--- a/auth/credentials/credentials_ntlm.c
+++ b/auth/credentials/credentials_ntlm.c
@@ -268,6 +268,53 @@ _PUBLIC_ bool cli_credentials_set_utf16_password(struct cli_credentials *cred,
return false;
}
+/*
+ * Set a old utf16 password on the credentials context.
+ *
+ * This is required because the nt_hash is calculated over the raw utf16 blob,
+ * which might not be completely valid utf16, which means the conversion
+ * from CH_UTF16MUNGED to CH_UTF8 might loose information.
+ */
+_PUBLIC_ bool cli_credentials_set_old_utf16_password(struct cli_credentials *cred,
+ const DATA_BLOB *password_utf16)
+{
+ struct samr_Password *nt_hash = NULL;
+ char *password_talloc = NULL;
+ size_t password_len = 0;
+ bool ok;
+
+ if (password_utf16 == NULL) {
+ return cli_credentials_set_old_password(cred, NULL, CRED_SPECIFIED);
+ }
+
+ nt_hash = talloc(cred, struct samr_Password);
+ if (nt_hash == NULL) {
+ return false;
+ }
+
+ ok = convert_string_talloc(cred,
+ CH_UTF16MUNGED, CH_UTF8,
+ password_utf16->data,
+ password_utf16->length,
+ (void *)&password_talloc,
+ &password_len);
+ if (!ok) {
+ TALLOC_FREE(nt_hash);
+ return false;
+ }
+
+ ok = cli_credentials_set_old_password(cred, password_talloc, CRED_SPECIFIED);
+ TALLOC_FREE(password_talloc);
+ if (!ok) {
+ TALLOC_FREE(nt_hash);
+ return false;
+ }
+
+ mdfour(nt_hash->hash, password_utf16->data, password_utf16->length);
+ cred->old_nt_hash = nt_hash;
+ return true;
+}
+
_PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
const struct samr_Password *nt_hash,
enum credentials_obtained obtained)
--
1.9.1
From 6e544182de446dde6eae6bcba1d73692e702e5a5 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 30 Jan 2015 16:54:06 +0000
Subject: [PATCH 04/17] s3:cli_netlogon: cli_credentials_get_old_nt_hash() in
rpccli_setup_netlogon_creds_with_creds()
This way we'll fallback to use the previous machine/trust account password
if required.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/rpc_client/cli_netlogon.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index b08c10f..4fd7155 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -236,12 +236,15 @@ NTSTATUS rpccli_setup_netlogon_creds_with_creds(struct cli_state *cli,
return NT_STATUS_NO_MEMORY;
}
+ previous_nt_hash = cli_credentials_get_old_nt_hash(creds, talloc_tos());
+
status = rpccli_setup_netlogon_creds(cli, transport,
netlogon_creds,
force_reauth,
*current_nt_hash,
previous_nt_hash);
TALLOC_FREE(current_nt_hash);
+ TALLOC_FREE(previous_nt_hash);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
--
1.9.1
From 25cedd134bf0dea6cefb44c1dfeb74ab6973ce47 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 09:49:16 +0100
Subject: [PATCH 05/17] s3:rpc_client: remove unused auth_level paramter of
cli_rpc_pipe_open_schannel()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/rpc_client/cli_pipe.h | 1 -
source3/rpc_client/cli_pipe_schannel.c | 1 -
source3/rpcclient/rpcclient.c | 1 -
source3/utils/net_rpc.c | 2 +-
4 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h
index 16946c5..01edaa4 100644
--- a/source3/rpc_client/cli_pipe.h
+++ b/source3/rpc_client/cli_pipe.h
@@ -117,7 +117,6 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
struct messaging_context *msg_ctx,
const struct ndr_interface_table *table,
enum dcerpc_transport_t transport,
- enum dcerpc_AuthLevel auth_level,
const char *domain,
struct rpc_pipe_client **presult,
TALLOC_CTX *mem_ctx,
diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c
index 7b53cf0..0825663 100644
--- a/source3/rpc_client/cli_pipe_schannel.c
+++ b/source3/rpc_client/cli_pipe_schannel.c
@@ -41,7 +41,6 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
struct messaging_context *msg_ctx,
const struct ndr_interface_table *table,
enum dcerpc_transport_t transport,
- enum dcerpc_AuthLevel auth_level,
const char *domain,
struct rpc_pipe_client **presult,
TALLOC_CTX *mem_ctx,
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
index 9dec094..f002548 100644
--- a/source3/rpcclient/rpcclient.c
+++ b/source3/rpcclient/rpcclient.c
@@ -734,7 +734,6 @@ static NTSTATUS do_cmd(struct cli_state *cli,
cli, rpcclient_msg_ctx,
cmd_entry->table,
default_transport,
- pipe_default_auth_level,
get_cmdline_auth_info_domain(auth_info),
&cmd_entry->rpc_pipe,
talloc_autofree_context(),
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index bf659a8..2df009d 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -195,7 +195,7 @@ int run_rpc_command(struct net_context *c,
TALLOC_FREE(c->netlogon_creds);
nt_status = cli_rpc_pipe_open_schannel(
cli, c->msg_ctx, table, NCACN_NP,
- DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
+ domain_name,
&pipe_hnd, c, &c->netlogon_creds);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
--
1.9.1
From 6e4795944cb7c77cba4047c40eaac2b47b95418c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 09:34:45 +0100
Subject: [PATCH 06/17] s3:rpc_client: use cli_credentials based functions in
cli_rpc_pipe_open_schannel()
This simplifies the code and allows the previous password to be passed
through the stack.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/rpc_client/cli_pipe_schannel.c | 68 ++++++++--------------------------
1 file changed, 15 insertions(+), 53 deletions(-)
diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c
index 0825663..5e309fd 100644
--- a/source3/rpc_client/cli_pipe_schannel.c
+++ b/source3/rpc_client/cli_pipe_schannel.c
@@ -50,76 +50,38 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
const char *dc_name = smbXcli_conn_remote_name(cli->conn);
struct rpc_pipe_client *result = NULL;
NTSTATUS status;
+ struct cli_credentials *cli_creds = NULL;
struct netlogon_creds_cli_context *netlogon_creds = NULL;
- struct netlogon_creds_CredentialState *creds = NULL;
- uint32_t netlogon_flags = 0;
- enum netr_SchannelType sec_chan_type = 0;
- const char *_account_name = NULL;
- const char *account_name = NULL;
- struct samr_Password current_nt_hash;
- struct samr_Password *previous_nt_hash = NULL;
- bool ok;
- ok = get_trust_pw_hash(domain,
- current_nt_hash.hash,
- &_account_name,
- &sec_chan_type);
- if (!ok) {
- TALLOC_FREE(frame);
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
-
- account_name = talloc_asprintf(frame, "%s$", _account_name);
- if (account_name == NULL) {
- SAFE_FREE(previous_nt_hash);
- TALLOC_FREE(frame);
- return NT_STATUS_NO_MEMORY;
- }
-
- status = rpccli_create_netlogon_creds(dc_name,
- domain,
- account_name,
- sec_chan_type,
- msg_ctx,
- frame,
- &netlogon_creds);
+ status = pdb_get_trust_credentials(domain, NULL,
+ frame, &cli_creds);
if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(previous_nt_hash);
TALLOC_FREE(frame);
return status;
}
- status = rpccli_setup_netlogon_creds(cli, transport,
- netlogon_creds,
- false, /* force_reauth */
- current_nt_hash,
- previous_nt_hash);
- SAFE_FREE(previous_nt_hash);
+ status = rpccli_create_netlogon_creds_with_creds(cli_creds,
+ dc_name,
+ msg_ctx,
+ frame,
+ &netlogon_creds);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
return status;
}
- status = netlogon_creds_cli_get(netlogon_creds,
- frame,
- &creds);
+ status = rpccli_setup_netlogon_creds_with_creds(cli, transport,
+ netlogon_creds,
+ false, /* force_reauth */
+ cli_creds);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
return status;
}
- netlogon_flags = creds->negotiate_flags;
- TALLOC_FREE(creds);
-
- if (!(netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
- TALLOC_FREE(frame);
- return NT_STATUS_DOWNGRADE_DETECTED;
- }
-
- status = cli_rpc_pipe_open_schannel_with_key(
- cli, table, transport, domain,
- netlogon_creds,
- &result);
+ status = cli_rpc_pipe_open_schannel_with_creds(cli, table, transport,
+ cli_creds, netlogon_creds,
+ &result);
if (NT_STATUS_IS_OK(status)) {
*presult = result;
if (pcreds != NULL) {
--
1.9.1
From e100e295a34d3b9dc6e8fd44e59fcab2c44c7066 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 10:05:37 +0100
Subject: [PATCH 07/17] s3:rpc_client: handle !NETLOGON_NEG_AUTHENTICATED_RPC
in cli_rpc_pipe_open_schannel()
This is only allowed with special config options ("client schannel = no",
"require strong key = no" and "reject md5 servers = no").
By default we require NETLOGON_NEG_AUTHENTICATED_RPC.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/rpc_client/cli_pipe_schannel.c | 40 +++++++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c
index 5e309fd..1790247 100644
--- a/source3/rpc_client/cli_pipe_schannel.c
+++ b/source3/rpc_client/cli_pipe_schannel.c
@@ -52,6 +52,8 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
NTSTATUS status;
struct cli_credentials *cli_creds = NULL;
struct netlogon_creds_cli_context *netlogon_creds = NULL;
+ struct netlogon_creds_CredentialState *creds = NULL;
+ uint32_t netlogon_flags;
status = pdb_get_trust_credentials(domain, NULL,
frame, &cli_creds);
@@ -79,16 +81,38 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
return status;
}
- status = cli_rpc_pipe_open_schannel_with_creds(cli, table, transport,
- cli_creds, netlogon_creds,
- &result);
- if (NT_STATUS_IS_OK(status)) {
- *presult = result;
- if (pcreds != NULL) {
- *pcreds = talloc_move(mem_ctx, &netlogon_creds);
+ status = netlogon_creds_cli_get(netlogon_creds, frame, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ netlogon_flags = creds->negotiate_flags;
+ TALLOC_FREE(creds);
+
+ if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
+ status = cli_rpc_pipe_open_schannel_with_creds(cli, table,
+ transport,
+ cli_creds,
+ netlogon_creds,
+ &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ return status;
+ }
+ } else {
+ status = cli_rpc_pipe_open_noauth(cli, table, &result);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ return status;
}
}
+ *presult = result;
+ if (pcreds != NULL) {
+ *pcreds = talloc_move(mem_ctx, &netlogon_creds);
+ }
+
TALLOC_FREE(frame);
- return status;
+ return NT_STATUS_OK;
}
--
1.9.1
From e5c3f19ae3222ff7f20f1a0b816a461b1eb62ae4 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 09:25:35 +0100
Subject: [PATCH 08/17] s3:rpcclient: make use of
rpccli_[create|setup]_netlogon_creds_with_creds()
This passing struct cli_credentials allows the usage of the previous password.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/rpcclient/rpcclient.c | 57 +++++++++++++++----------------------------
1 file changed, 19 insertions(+), 38 deletions(-)
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
index f002548..5e0dc7a 100644
--- a/source3/rpcclient/rpcclient.c
+++ b/source3/rpcclient/rpcclient.c
@@ -760,58 +760,39 @@ static NTSTATUS do_cmd(struct cli_state *cli,
if (rpcclient_netlogon_creds == NULL && ok) {
const char *dc_name = cmd_entry->rpc_pipe->desthost;
const char *domain = get_cmdline_auth_info_domain(auth_info);
- enum netr_SchannelType sec_chan_type = 0;
- const char *_account_name = NULL;
- const char *account_name = NULL;
- struct samr_Password current_nt_hash = {
- .hash = { 0 },
- };
- struct samr_Password *previous_nt_hash = NULL;
-
- if (!get_trust_pw_hash(get_cmdline_auth_info_domain(auth_info),
- current_nt_hash.hash, &_account_name,
- &sec_chan_type))
- {
- DEBUG(0, ("Failed to fetch trust password for %s to connect to %s.\n",
- get_cmdline_auth_info_domain(auth_info),
- cmd_entry->table->name));
- TALLOC_FREE(cmd_entry->rpc_pipe);
- talloc_free(mem_ctx);
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
+ struct cli_credentials *creds = NULL;
- account_name = talloc_asprintf(mem_ctx, "%s$", _account_name);
- if (account_name == NULL) {
- DEBUG(0, ("Out of memory creating account name to connect to %s.\n",
- cmd_entry->table->name));
+ ntresult = pdb_get_trust_credentials(domain, NULL,
+ mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(ntresult)) {
+ DEBUG(0, ("Failed to fetch trust credentials for "
+ "%s to connect to %s: %s\n",
+ domain, cmd_entry->table->name,
+ nt_errstr(ntresult)));
TALLOC_FREE(cmd_entry->rpc_pipe);
- SAFE_FREE(previous_nt_hash);
- TALLOC_FREE(mem_ctx);
- return NT_STATUS_NO_MEMORY;
+ talloc_free(mem_ctx);
+ return ntresult;
}
- ntresult = rpccli_create_netlogon_creds(dc_name,
- domain,
- account_name,
- sec_chan_type,
- rpcclient_msg_ctx,
- talloc_autofree_context(),
- &rpcclient_netlogon_creds);
+ ntresult = rpccli_create_netlogon_creds_with_creds(creds,
+ dc_name,
+ rpcclient_msg_ctx,
+ talloc_autofree_context(),
+ &rpcclient_netlogon_creds);
if (!NT_STATUS_IS_OK(ntresult)) {
DEBUG(0, ("Could not initialise credentials for %s.\n",
cmd_entry->table->name));
TALLOC_FREE(cmd_entry->rpc_pipe);
- SAFE_FREE(previous_nt_hash);
TALLOC_FREE(mem_ctx);
return ntresult;
}
- ntresult = rpccli_setup_netlogon_creds(cli, NCACN_NP,
+ ntresult = rpccli_setup_netlogon_creds_with_creds(cli,
+ NCACN_NP,
rpcclient_netlogon_creds,
false, /* force_reauth */
- current_nt_hash,
- previous_nt_hash);
- SAFE_FREE(previous_nt_hash);
+ creds);
+ TALLOC_FREE(creds);
if (!NT_STATUS_IS_OK(ntresult)) {
DEBUG(0, ("Could not initialise credentials for %s.\n",
cmd_entry->table->name));
--
1.9.1
From 1b6901c187e3005346a1919ad7e83fda14d978c6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 10:33:01 +0100
Subject: [PATCH 09/17] s3:auth_domain: fix talloc problem in
connect_to_domain_password_server()
return values of connect_to_domain_password_server() need to be exported
to the callers memory context.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/auth/auth_domain.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index 373b596..e29330d 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -53,6 +53,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
const char *dc_name,
const struct sockaddr_storage *dc_ss,
struct rpc_pipe_client **pipe_ret,
+ TALLOC_CTX *mem_ctx,
struct netlogon_creds_cli_context **creds_ret)
{
TALLOC_CTX *frame = talloc_stackframe();
@@ -209,7 +210,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
*cli_ret = cli;
*pipe_ret = netlogon_pipe;
- *creds_ret = netlogon_creds;
+ *creds_ret = talloc_move(mem_ctx, &netlogon_creds);
TALLOC_FREE(frame);
return NT_STATUS_OK;
@@ -230,6 +231,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
const struct sockaddr_storage *dc_ss)
{
+ TALLOC_CTX *frame = talloc_stackframe();
struct netr_SamInfo3 *info3 = NULL;
struct cli_state *cli = NULL;
struct rpc_pipe_client *netlogon_pipe = NULL;
@@ -255,11 +257,13 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
dc_name,
dc_ss,
&netlogon_pipe,
+ frame,
&netlogon_creds);
}
if ( !NT_STATUS_IS_OK(nt_status) ) {
DEBUG(0,("domain_client_validate: Domain password server not available.\n"));
+ TALLOC_FREE(frame);
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
}
@@ -324,6 +328,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
these pointers are no longer valid..... */
cli_shutdown(cli);
+ TALLOC_FREE(frame);
return nt_status;
}
--
1.9.1
From 92f45a34295cf0a3c966cf6a63ca8dae306f7eb9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 09:52:45 +0100
Subject: [PATCH 10/17] s3:auth_domain: make use of
cli_rpc_pipe_open_schannel()
This simplifies a lot and allows the previous password to be used.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/auth/auth_domain.c | 101 +++++----------------------------------------
1 file changed, 10 insertions(+), 91 deletions(-)
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index e29330d..0dc6657 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -62,17 +62,8 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
struct cli_state *cli = NULL;
struct rpc_pipe_client *netlogon_pipe = NULL;
struct netlogon_creds_cli_context *netlogon_creds = NULL;
- struct netlogon_creds_CredentialState *creds = NULL;
- uint32_t netlogon_flags = 0;
- enum netr_SchannelType sec_chan_type = 0;
- const char *_account_name = NULL;
- const char *account_name = NULL;
- struct samr_Password current_nt_hash;
- struct samr_Password *previous_nt_hash = NULL;
- bool ok;
*cli_ret = NULL;
-
*pipe_ret = NULL;
*creds_ret = NULL;
@@ -115,91 +106,19 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
* We now have an anonymous connection to IPC$ on the domain password server.
*/
- ok = get_trust_pw_hash(domain,
- current_nt_hash.hash,
- &_account_name,
- &sec_chan_type);
- if (!ok) {
- cli_shutdown(cli);
- TALLOC_FREE(mutex);
- TALLOC_FREE(frame);
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
-
- account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name);
- if (account_name == NULL) {
- cli_shutdown(cli);
- TALLOC_FREE(mutex);
- TALLOC_FREE(frame);
- return NT_STATUS_NO_MEMORY;
- }
-
- result = rpccli_create_netlogon_creds(dc_name,
- domain,
- account_name,
- sec_chan_type,
- msg_ctx,
- talloc_tos(),
- &netlogon_creds);
- if (!NT_STATUS_IS_OK(result)) {
- cli_shutdown(cli);
- TALLOC_FREE(mutex);
- TALLOC_FREE(frame);
- SAFE_FREE(previous_nt_hash);
- return result;
- }
-
- result = rpccli_setup_netlogon_creds(cli, NCACN_NP,
- netlogon_creds,
- false, /* force_reauth */
- current_nt_hash,
- previous_nt_hash);
- SAFE_FREE(previous_nt_hash);
- if (!NT_STATUS_IS_OK(result)) {
- cli_shutdown(cli);
- TALLOC_FREE(mutex);
- TALLOC_FREE(frame);
- return result;
- }
-
- result = netlogon_creds_cli_get(netlogon_creds,
- talloc_tos(),
- &creds);
- if (!NT_STATUS_IS_OK(result)) {
- cli_shutdown(cli);
- TALLOC_FREE(mutex);
- TALLOC_FREE(frame);
- return result;
- }
- netlogon_flags = creds->negotiate_flags;
- TALLOC_FREE(creds);
-
- if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
- result = cli_rpc_pipe_open_schannel_with_key(
- cli, &ndr_table_netlogon, NCACN_NP,
- domain, netlogon_creds, &netlogon_pipe);
- } else {
- result = cli_rpc_pipe_open_noauth(cli,
- &ndr_table_netlogon,
- &netlogon_pipe);
- }
-
+ result = cli_rpc_pipe_open_schannel(cli,
+ msg_ctx,
+ &ndr_table_netlogon,
+ NCACN_NP,
+ domain,
+ &netlogon_pipe,
+ frame,
+ &netlogon_creds);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(0,("connect_to_domain_password_server: "
"unable to open the domain client session to "
- "machine %s. Flags[0x%08X] Error was : %s.\n",
- dc_name, (unsigned)netlogon_flags,
- nt_errstr(result)));
- cli_shutdown(cli);
- TALLOC_FREE(mutex);
- TALLOC_FREE(frame);
- return result;
- }
-
- if(!netlogon_pipe) {
- DEBUG(0, ("connect_to_domain_password_server: unable to open "
- "the domain client session to machine %s. Error "
- "was : %s.\n", dc_name, nt_errstr(result)));
+ "machine %s. Error was : %s.\n",
+ dc_name, nt_errstr(result)));
cli_shutdown(cli);
TALLOC_FREE(mutex);
TALLOC_FREE(frame);
--
1.9.1
From 38258a271234b0aea62aa110aa5e6e850acb02b3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 11:29:49 +0100
Subject: [PATCH 11/17] s3:libnet: use cli_credentials based functions in
libnet_join_ok()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libnet/libnet_join.c | 65 +++++++++++++++++---------------------------
1 file changed, 25 insertions(+), 40 deletions(-)
diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c
index c5a61fe..66f302a 100644
--- a/source3/libnet/libnet_join.c
+++ b/source3/libnet/libnet_join.c
@@ -1366,18 +1366,15 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
TALLOC_CTX *frame = talloc_stackframe();
struct cli_state *cli = NULL;
struct rpc_pipe_client *netlogon_pipe = NULL;
+ struct cli_credentials *cli_creds = NULL;
struct netlogon_creds_cli_context *netlogon_creds = NULL;
struct netlogon_creds_CredentialState *creds = NULL;
uint32_t netlogon_flags = 0;
- enum netr_SchannelType sec_chan_type = 0;
NTSTATUS status;
- char *machine_password = NULL;
- const char *machine_name = NULL;
const char *machine_account = NULL;
+ const char *machine_domain = NULL;
+ const char *machine_password = NULL;
int flags = 0;
- struct samr_Password current_nt_hash;
- struct samr_Password *previous_nt_hash = NULL;
- bool ok;
if (!dc_name) {
TALLOC_FREE(frame);
@@ -1389,40 +1386,34 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- ok = get_trust_pw_clear(netbios_domain_name,
- &machine_password,
- &machine_name,
- &sec_chan_type);
- if (!ok) {
+ status = pdb_get_trust_credentials(netbios_domain_name, NULL,
+ frame, &cli_creds);
+ if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ return status;
}
- machine_account = talloc_asprintf(frame, "%s$", machine_name);
- if (machine_account == NULL) {
- SAFE_FREE(machine_password);
- SAFE_FREE(previous_nt_hash);
- TALLOC_FREE(frame);
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
+ /* we don't want any old password */
+ cli_credentials_set_old_password(cli_creds, NULL, CRED_SPECIFIED);
if (use_kerberos) {
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
}
+ machine_account = cli_credentials_get_username(cli_creds);
+ machine_domain = cli_credentials_get_domain(cli_creds);
+ machine_password = cli_credentials_get_password(cli_creds);
+
status = cli_full_connection(&cli, NULL,
dc_name,
NULL, 0,
"IPC$", "IPC",
machine_account,
- netbios_domain_name,
+ machine_domain,
machine_password,
flags,
SMB_SIGNING_DEFAULT);
- E_md4hash(machine_password, current_nt_hash.hash);
- SAFE_FREE(machine_password);
-
if (!NT_STATUS_IS_OK(status)) {
status = cli_full_connection(&cli, NULL,
dc_name,
@@ -1436,31 +1427,25 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
}
if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(previous_nt_hash);
TALLOC_FREE(frame);
return status;
}
- status = rpccli_create_netlogon_creds(dc_name,
- netbios_domain_name,
- machine_account,
- sec_chan_type,
- msg_ctx,
- frame,
- &netlogon_creds);
+ status = rpccli_create_netlogon_creds_with_creds(cli_creds,
+ dc_name,
+ msg_ctx,
+ frame,
+ &netlogon_creds);
if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(previous_nt_hash);
cli_shutdown(cli);
TALLOC_FREE(frame);
return status;
}
- status = rpccli_setup_netlogon_creds(cli, NCACN_NP,
- netlogon_creds,
- true, /* force_reauth */
- current_nt_hash,
- previous_nt_hash);
- SAFE_FREE(previous_nt_hash);
+ status = rpccli_setup_netlogon_creds_with_creds(cli, NCACN_NP,
+ netlogon_creds,
+ true, /* force_reauth */
+ cli_creds);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("connect_to_domain_password_server: "
"unable to open the domain client session to "
@@ -1489,9 +1474,9 @@ NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
return NT_STATUS_OK;
}
- status = cli_rpc_pipe_open_schannel_with_key(
+ status = cli_rpc_pipe_open_schannel_with_creds(
cli, &ndr_table_netlogon, NCACN_NP,
- netbios_domain_name,
+ cli_creds,
netlogon_creds, &netlogon_pipe);
TALLOC_FREE(netlogon_pipe);
--
1.9.1
From dde6da2068930f70b37fe49013aa1571bbc0d789 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 9 Feb 2015 11:33:05 +0100
Subject: [PATCH 12/17] s3:rpc_client: remove unused
cli_rpc_pipe_open_schannel_with_key()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/rpc_client/cli_pipe.c | 96 -------------------------------------------
source3/rpc_client/cli_pipe.h | 7 ----
2 files changed, 103 deletions(-)
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index db28306..915fb78 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -3114,102 +3114,6 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
return status;
}
-/****************************************************************************
- External interface.
- Open a named pipe to an SMB server and bind using schannel (bind type 68)
- using session_key. sign and seal.
-
- The *pdc will be stolen onto this new pipe
- ****************************************************************************/
-
-NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
- const struct ndr_interface_table *table,
- enum dcerpc_transport_t transport,
- const char *domain,
- 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;
- enum dcerpc_AuthLevel auth_level;
- NTSTATUS status;
- 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;
- }
-
- auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
-
- status = rpccli_generic_bind_data(rpccli,
- DCERPC_AUTH_TYPE_SCHANNEL,
- auth_level,
- NULL,
- target_service,
- domain,
- creds->computer_name,
- NULL,
- CRED_AUTO_USE_KERBEROS,
- creds,
- &rpcauth);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
- nt_errstr(status)));
- TALLOC_FREE(rpccli);
- return status;
- }
-
- 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(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;
- }
-
- TALLOC_FREE(creds);
-
- 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, ("netlogon_creds_cli_check failed with %s\n",
- nt_errstr(status)));
- TALLOC_FREE(rpccli);
- return status;
- }
-
-
-done:
- DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
- "for domain %s and bound using schannel.\n",
- table->name,
- rpccli->desthost, domain));
-
- *_rpccli = rpccli;
- return NT_STATUS_OK;
-}
-
NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
const struct ndr_interface_table *table,
enum dcerpc_transport_t transport,
diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h
index 01edaa4..2290d62b 100644
--- a/source3/rpc_client/cli_pipe.h
+++ b/source3/rpc_client/cli_pipe.h
@@ -99,13 +99,6 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
const char *password,
struct rpc_pipe_client **presult);
-NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
- const struct ndr_interface_table *table,
- enum dcerpc_transport_t transport,
- const char *domain,
- struct netlogon_creds_cli_context *netlogon_creds,
- struct rpc_pipe_client **presult);
-
NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
const struct ndr_interface_table *table,
enum dcerpc_transport_t transport,
--
1.9.1
From d65b4253285ffab8507e7c2c17e77d52bf0536b7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 30 Jan 2015 16:53:40 +0000
Subject: [PATCH 13/17] s3:pdb_samba_dsdb: return the previous password and the
kvno in pdb_samba_dsdb_get_trusteddom_creds()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/passdb/pdb_samba_dsdb.c | 91 ++++++++++++++++++++++++++++++++---------
1 file changed, 72 insertions(+), 19 deletions(-)
diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c
index bbedd88..13be249 100644
--- a/source3/passdb/pdb_samba_dsdb.c
+++ b/source3/passdb/pdb_samba_dsdb.c
@@ -2286,9 +2286,11 @@ static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
int trust_type;
int i;
DATA_BLOB password_utf16 = {};
- DATA_BLOB password_nt = {};
+ struct samr_Password *password_nt = NULL;
+ uint32_t password_version = 0;
+ DATA_BLOB old_password_utf16 = {};
+ struct samr_Password *old_password_nt = NULL;
struct trustAuthInOutBlob password_blob;
- struct AuthenticationInformationArray *auth_array = NULL;
enum ndr_err_code ndr_err;
NTSTATUS status;
time_t last_set_time = 0;
@@ -2361,27 +2363,65 @@ static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- auth_array = &password_blob.current;
+ for (i=0; i < password_blob.current.count; i++) {
+ struct AuthenticationInformation *a =
+ &password_blob.current.array[i];
- for (i=0; i < auth_array->count; i++) {
- if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
- last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
+ switch (a->AuthType) {
+ case TRUST_AUTH_TYPE_NONE:
+ break;
+
+ case TRUST_AUTH_TYPE_VERSION:
+ password_version = a->AuthInfo.version.version;
+ break;
+
+ case TRUST_AUTH_TYPE_CLEAR:
+ last_set_time = nt_time_to_unix(a->LastUpdateTime);
+
+ password_utf16 = data_blob_const(a->AuthInfo.clear.password,
+ a->AuthInfo.clear.size);
+ password_nt = NULL;
+ break;
+
+ case TRUST_AUTH_TYPE_NT4OWF:
+ if (password_utf16.length != 0) {
+ break;
+ }
+
+ last_set_time = nt_time_to_unix(a->LastUpdateTime);
- password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
- auth_array->array[i].AuthInfo.clear.size);
- password_nt = data_blob_null;
+ password_nt = &a->AuthInfo.nt4owf.password;
break;
}
+ }
+
+ for (i=0; i < password_blob.previous.count; i++) {
+ struct AuthenticationInformation *a = &password_blob.previous.array[i];
+
+ switch (a->AuthType) {
+ case TRUST_AUTH_TYPE_NONE:
+ break;
- if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) {
- last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
+ case TRUST_AUTH_TYPE_VERSION:
+ break;
+
+ case TRUST_AUTH_TYPE_CLEAR:
+ old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
+ a->AuthInfo.clear.size);
+ old_password_nt = NULL;
+ break;
+
+ case TRUST_AUTH_TYPE_NT4OWF:
+ if (old_password_utf16.length != 0) {
+ break;
+ }
- password_nt = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
- auth_array->array[i].AuthInfo.clear.size);
+ old_password_nt = &a->AuthInfo.nt4owf.password;
+ break;
}
}
- if (password_utf16.length == 0 && password_nt.length == 0) {
+ if (password_utf16.length == 0 && password_nt == NULL) {
DEBUG(0, ("Trusted domain %s does not have a "
"clear-text nor nt password stored\n",
domain));
@@ -2454,14 +2494,26 @@ static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
}
}
- if (password_nt.length == 16) {
- struct samr_Password nt_hash;
+ if (old_password_nt != NULL) {
+ ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
+ if (!ok) {
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
- memcpy(nt_hash.hash, password_nt.data, 16);
+ if (old_password_utf16.length > 0) {
+ ok = cli_credentials_set_old_utf16_password(creds,
+ &old_password_utf16);
+ if (!ok) {
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
- ok = cli_credentials_set_nt_hash(creds, &nt_hash,
+ if (password_nt != NULL) {
+ ok = cli_credentials_set_nt_hash(creds, password_nt,
CRED_SPECIFIED);
- ZERO_STRUCT(nt_hash);
if (!ok) {
TALLOC_FREE(tmp_ctx);
return NT_STATUS_NO_MEMORY;
@@ -2479,6 +2531,7 @@ static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
}
cli_credentials_set_password_last_changed_time(creds, last_set_time);
+ cli_credentials_set_kvno(creds, password_version);
if (password_utf16.length > 0 && dns_domain != NULL) {
/*
--
1.9.1
From d5a7bec11ea07cb25133fe8003977a4a2b96a070 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 5 Feb 2015 10:07:46 +0000
Subject: [PATCH 14/17] s3:pdb_samba_dsdb: return the domain sid in
pdb_samba_dsdb_get_trusteddom_pw()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/passdb/pdb_samba_dsdb.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c
index 13be249..131ae2f 100644
--- a/source3/passdb/pdb_samba_dsdb.c
+++ b/source3/passdb/pdb_samba_dsdb.c
@@ -2155,6 +2155,7 @@ static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
enum ndr_err_code ndr_err;
NTSTATUS status;
const char *netbios_domain = NULL;
+ const struct dom_sid *domain_sid = NULL;
status = sam_get_results_trust(state->ldb, tmp_ctx, domain,
NULL, attrs, &msg);
@@ -2177,6 +2178,14 @@ static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
return false;
}
+ domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
+ if (domain_sid == NULL) {
+ DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
+ domain));
+ TALLOC_FREE(tmp_ctx);
+ return false;
+ }
+
trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
@@ -2256,6 +2265,10 @@ static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
*pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
}
+ if (sid != NULL) {
+ sid_copy(sid, domain_sid);
+ }
+
TALLOC_FREE(tmp_ctx);
return true;
}
--
1.9.1
From 17cfcc3b65d19c1b683d3beec84f1ec159e1bea6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 5 Feb 2015 09:26:23 +0000
Subject: [PATCH 15/17] s3:pdb_samba_dsdb: implement
pdb_samba_dsdb_set_trusteddom_pw()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/passdb/pdb_samba_dsdb.c | 279 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 278 insertions(+), 1 deletion(-)
diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c
index 131ae2f..a933b2a 100644
--- a/source3/passdb/pdb_samba_dsdb.c
+++ b/source3/passdb/pdb_samba_dsdb.c
@@ -2569,7 +2569,284 @@ static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
const char* domain, const char* pwd,
const struct dom_sid *sid)
{
- return false;
+ struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba_dsdb_state);
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ const char * const attrs[] = {
+ "trustAuthOutgoing",
+ "trustDirection",
+ "trustType",
+ NULL
+ };
+ struct ldb_message *msg = NULL;
+ int trust_direction_flags;
+ int trust_type;
+ int i;
+ const struct ldb_val *old_val = NULL;
+ struct trustAuthInOutBlob old_blob = {};
+ uint32_t old_version = 0;
+ uint32_t new_version = 0;
+ DATA_BLOB new_utf16 = {};
+ struct trustAuthInOutBlob new_blob = {};
+ struct ldb_val new_val = {};
+ struct timeval tv = timeval_current();
+ NTTIME now = timeval_to_nttime(&tv);
+ enum ndr_err_code ndr_err;
+ NTSTATUS status;
+ bool ok;
+ int ret;
+
+ ret = ldb_transaction_start(state->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(2, ("Failed to start transaction.\n"));
+ TALLOC_FREE(tmp_ctx);
+ return false;
+ }
+
+ ok = samdb_is_pdc(state->ldb);
+ if (!ok) {
+ DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
+ domain));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ status = sam_get_results_trust(state->ldb, tmp_ctx, domain,
+ NULL, attrs, &msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * This can be called to work out of a domain is
+ * trusted, rather than just to get the password
+ */
+ DEBUG(2, ("Failed to get trusted domain password for %s. "
+ "It may not be a trusted domain.\n", domain));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
+ if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
+ DEBUG(2, ("Trusted domain %s is is not an outbound trust, can't set a password.\n",
+ domain));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
+ switch (trust_type) {
+ case LSA_TRUST_TYPE_DOWNLEVEL:
+ case LSA_TRUST_TYPE_UPLEVEL:
+ break;
+ default:
+ DEBUG(0, ("Trusted domain %s is of type 0x%X - "
+ "password changes are not supported\n",
+ domain, (unsigned)trust_type));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
+ if (old_val != NULL) {
+ ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
+ (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0, ("Failed to get trusted domain password for %s, "
+ "attribute trustAuthOutgoing coult not be parsed %s.\n",
+ domain,
+ ndr_map_error2string(ndr_err)));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+ }
+
+ for (i=0; i < old_blob.current.count; i++) {
+ struct AuthenticationInformation *a =
+ &old_blob.current.array[i];
+
+ switch (a->AuthType) {
+ case TRUST_AUTH_TYPE_NONE:
+ break;
+
+ case TRUST_AUTH_TYPE_VERSION:
+ old_version = a->AuthInfo.version.version;
+ break;
+
+ case TRUST_AUTH_TYPE_CLEAR:
+ break;
+
+ case TRUST_AUTH_TYPE_NT4OWF:
+ break;
+ }
+ }
+
+ new_version = old_version + 1;
+ ok = convert_string_talloc(tmp_ctx,
+ CH_UNIX, CH_UTF16,
+ pwd, strlen(pwd),
+ (void *)&new_utf16.data,
+ &new_utf16.length);
+ if (!ok) {
+ DEBUG(0, ("Failed to generate new_utf16 password for domain %s\n",
+ domain));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ if (new_utf16.length < 28) {
+ DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
+ new_utf16.length,
+ (unsigned)new_version,
+ domain));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+ if (new_utf16.length > 498) {
+ DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
+ new_utf16.length,
+ (unsigned)new_version,
+ domain));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ new_blob.count = MAX(old_blob.current.count, 2);
+ new_blob.current.array = talloc_zero_array(tmp_ctx,
+ struct AuthenticationInformation,
+ new_blob.count);
+ if (new_blob.current.array == NULL) {
+ DEBUG(0, ("talloc_zero_array(%u) failed\n",
+ (unsigned)new_blob.count));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+ new_blob.previous.array = talloc_zero_array(tmp_ctx,
+ struct AuthenticationInformation,
+ new_blob.count);
+ if (new_blob.current.array == NULL) {
+ DEBUG(0, ("talloc_zero_array(%u) failed\n",
+ (unsigned)new_blob.count));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ for (i = 0; i < old_blob.current.count; i++) {
+ struct AuthenticationInformation *o =
+ &old_blob.current.array[i];
+ struct AuthenticationInformation *p =
+ &new_blob.previous.array[i];
+
+ *p = *o;
+ new_blob.previous.count++;
+ }
+ for (; i < new_blob.count; i++) {
+ struct AuthenticationInformation *pi =
+ &new_blob.previous.array[i];
+
+ if (i == 0) {
+ /*
+ * new_blob.previous is still empty so
+ * we'll do new_blob.previous = new_blob.current
+ * below.
+ */
+ break;
+ }
+
+ pi->LastUpdateTime = now;
+ pi->AuthType = TRUST_AUTH_TYPE_NONE;
+ new_blob.previous.count++;
+ }
+
+ for (i = 0; i < new_blob.count; i++) {
+ struct AuthenticationInformation *ci =
+ &new_blob.current.array[i];
+
+ ci->LastUpdateTime = now;
+ switch (i) {
+ case 0:
+ ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
+ ci->AuthInfo.clear.size = new_utf16.length;
+ ci->AuthInfo.clear.password = new_utf16.data;
+ break;
+ case 1:
+ ci->AuthType = TRUST_AUTH_TYPE_VERSION;
+ ci->AuthInfo.version.version = new_version;
+ break;
+ default:
+ ci->AuthType = TRUST_AUTH_TYPE_NONE;
+ break;
+ }
+
+ new_blob.current.count++;
+ }
+
+ if (new_blob.previous.count == 0) {
+ TALLOC_FREE(new_blob.previous.array);
+ new_blob.previous = new_blob.current;
+ }
+
+ ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
+ (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0, ("Failed to generate trustAuthOutgoing for "
+ "trusted domain password for %s: %s.\n",
+ domain, ndr_map_error2string(ndr_err)));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ msg->num_elements = 0;
+ ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
+ LDB_FLAG_MOD_REPLACE, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("ldb_msg_add_empty() failed\n"));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+ ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
+ &new_val, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("ldb_msg_add_value() failed\n"));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ ret = ldb_modify(state->ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to replace trustAuthOutgoing for "
+ "trusted domain password for %s: %s - %s\n",
+ domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
+ TALLOC_FREE(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return false;
+ }
+
+ ret = ldb_transaction_commit(state->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to commit trustAuthOutgoing for "
+ "trusted domain password for %s: %s - %s\n",
+ domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
+ TALLOC_FREE(tmp_ctx);
+ return false;
+ }
+
+ DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
+ "trusted domain password for %s.\n",
+ (unsigned)new_version, domain));
+ TALLOC_FREE(tmp_ctx);
+ return true;
}
static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
--
1.9.1
From 251b91906d8522272b7504b23251aa6671c2b663 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 31 Jan 2015 10:42:09 +0000
Subject: [PATCH 16/17] s4:trust_utils: store new trust/machine passwords
before trying it remotely.
If this fails we can still fallback to the old password...
Before trying the password change we verify the dc knows our current password.
This should make the password changes much more robust.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libsmb/trusts_util.c | 39 +++++++++++++++++++++++++++++----------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index 7503ef0..48db393 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -163,6 +163,19 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
return NT_STATUS_NO_MEMORY;
}
+ /*
+ * We could use cli_credentials_get_old_nt_hash(creds, frame) to
+ * set previous_nt_hash.
+ *
+ * But we want to check if the dc has our current password and only do
+ * a change if that's the case. So we keep previous_nt_hash = NULL.
+ *
+ * TODO:
+ * If the previous password is the only password in common with the dc,
+ * we better skip the password change, or use something like
+ * ServerTrustPasswordsGet() or netr_ServerGetTrustInfo() to fix our
+ * local secrets before doing the change.
+ */
status = netlogon_creds_cli_auth(context, b,
current_nt_hash,
previous_nt_hash);
@@ -171,16 +184,6 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
return status;
}
- status = netlogon_creds_cli_ServerPasswordSet(context, b,
- new_trust_passwd, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(frame);
- return status;
- }
-
- DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
- current_timestring(talloc_tos(), False)));
-
/*
* Return the result of trying to write the new password
* back into the trust account file.
@@ -212,6 +215,22 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
break;
}
+ DEBUG(1,("%s : %s(%s): Changed password locally\n",
+ current_timestring(talloc_tos(), false), __func__, domain));
+
+ status = netlogon_creds_cli_ServerPasswordSet(context, b,
+ new_trust_passwd, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("%s : %s(%s) remote password change set failed - %s\n",
+ current_timestring(talloc_tos(), false), __func__,
+ domain, nt_errstr(status)));
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ DEBUG(1,("%s : %s(%s): Changed password remotely.\n",
+ current_timestring(talloc_tos(), false), __func__, domain));
+
TALLOC_FREE(frame);
return NT_STATUS_OK;
}
--
1.9.1
From bbdcf68610c3eb3c1be1bd8d94856722445b6067 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 26 Jan 2015 16:02:20 +0100
Subject: [PATCH 17/17] s4:librpc: add auth_type=ncalrpc_as_system as binding
option
In future we may want another way to trigger this,
but our current rpc libraries need a lot of cleanup before.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/librpc/rpc/dcerpc_util.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index de960b2..ff3e60e 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -630,6 +630,22 @@ struct composite_context *dcerpc_pipe_auth_send(struct dcerpc_pipe *p,
conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
}
+ if (conn->transport.transport == NCALRPC) {
+ const char *v = dcerpc_binding_get_string_option(binding,
+ "auth_type");
+
+ if (v != NULL && strcmp(v, "ncalrpc_as_system") == 0) {
+ auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table,
+ s->credentials,
+ lpcfg_gensec_settings(c, s->lp_ctx),
+ DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
+ DCERPC_AUTH_LEVEL_CONNECT,
+ s->table->authservices->names[0]);
+ composite_continue(c, auth_req, continue_auth, c);
+ return c;
+ }
+ }
+
if (cli_credentials_is_anonymous(s->credentials)) {
auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe, s->table);
composite_continue(c, auth_none_req, continue_auth_none, c);
--
1.9.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20150210/81dc1edd/attachment.pgp>
More information about the samba-technical
mailing list