From f7c05a3992b70eacf014e46f64a7b96f22257bb7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 13 Jun 2017 11:18:37 +0200 Subject: [PATCH] libcli/auth: pass the cleartext blob to netlogon_creds_cli_ServerPasswordSet*() BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782 Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 0f5945a06df4bef501ca5085c621294057007225) --- libcli/auth/netlogon_creds_cli.c | 20 +++++++++++--------- libcli/auth/netlogon_creds_cli.h | 4 ++-- source3/libnet/libnet_join.c | 19 ++++++++++++++++++- source3/libsmb/trusts_util.c | 39 ++++++++++++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index ba8e063b6a8..29baae40524 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -36,6 +36,7 @@ #include "source3/include/messages.h" #include "source3/include/g_lock.h" #include "libds/common/roles.h" +#include "lib/crypto/crypto.h" struct netlogon_creds_cli_locked_state; @@ -1750,7 +1751,7 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx struct tevent_context *ev, struct netlogon_creds_cli_context *context, struct dcerpc_binding_handle *b, - const char *new_password, + const DATA_BLOB *new_password, const uint32_t *new_version) { struct tevent_req *req; @@ -1768,20 +1769,21 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx state->context = context; state->binding_handle = b; - /* - * netr_ServerPasswordSet - */ - ok = E_md4hash(new_password, state->samr_password.hash); - if (!ok) { + if (new_password->length < 14) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); return tevent_req_post(req, ev); } /* + * netr_ServerPasswordSet + */ + mdfour(state->samr_password.hash, new_password->data, new_password->length); + + /* * netr_ServerPasswordSet2 */ - ok = encode_pw_buffer(state->samr_crypt_password.data, - new_password, STR_UNICODE); + ok = set_pw_in_buffer(state->samr_crypt_password.data, + new_password); if (!ok) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); return tevent_req_post(req, ev); @@ -2051,7 +2053,7 @@ NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req) NTSTATUS netlogon_creds_cli_ServerPasswordSet( struct netlogon_creds_cli_context *context, struct dcerpc_binding_handle *b, - const char *new_password, + const DATA_BLOB *new_password, const uint32_t *new_version) { TALLOC_CTX *frame = talloc_stackframe(); diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h index 4cedb3ba62d..a7fd48c2252 100644 --- a/libcli/auth/netlogon_creds_cli.h +++ b/libcli/auth/netlogon_creds_cli.h @@ -106,13 +106,13 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx struct tevent_context *ev, struct netlogon_creds_cli_context *context, struct dcerpc_binding_handle *b, - const char *new_password, + const DATA_BLOB *new_password, const uint32_t *new_version); NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req); NTSTATUS netlogon_creds_cli_ServerPasswordSet( struct netlogon_creds_cli_context *context, struct dcerpc_binding_handle *b, - const char *new_password, + const DATA_BLOB *new_password, const uint32_t *new_version); struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx, diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index ecae4c5cd9a..99bba2ae349 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1140,6 +1140,9 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *netlogon_pipe = NULL; struct netlogon_creds_cli_context *netlogon_creds = NULL; struct samr_Password current_nt_hash; + size_t len = 0; + bool ok; + DATA_BLOB new_trust_blob = data_blob_null; NTSTATUS status; status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, @@ -1186,9 +1189,23 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, return status; } + len = strlen(r->in.machine_password); + ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16, + r->in.machine_password, len, + (void **)&new_trust_blob.data, + &new_trust_blob.length); + if (!ok) { + status = NT_STATUS_UNMAPPABLE_CHARACTER; + if (errno == ENOMEM) { + status = NT_STATUS_NO_MEMORY; + } + TALLOC_FREE(frame); + return status; + } + status = netlogon_creds_cli_ServerPasswordSet(netlogon_creds, netlogon_pipe->binding_handle, - r->in.machine_password, + &new_trust_blob, NULL); /* new_version */ if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 128beb73cc1..5bc8005e596 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -125,7 +125,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, struct timeval g_timeout = { 0, }; int timeout = 0; struct timeval tv = { 0, }; - char *new_trust_passwd = NULL; + char *new_trust_pw_str = NULL; + size_t len = 0; + DATA_BLOB new_trust_pw_blob = data_blob_null; uint32_t new_version = 0; uint32_t *new_trust_version = NULL; NTSTATUS status; @@ -239,14 +241,31 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, * We create a random buffer and convert that to utf8. * This is similar to what windows is doing. */ - new_trust_passwd = trust_pw_new_value(frame, sec_channel_type, + new_trust_pw_str = trust_pw_new_value(frame, sec_channel_type, lp_security()); - if (new_trust_passwd == NULL) { + if (new_trust_pw_str == NULL) { DEBUG(0, ("trust_pw_new_value() failed\n")); TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } + len = strlen(new_trust_pw_str); + ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16, + new_trust_pw_str, len, + (void **)&new_trust_pw_blob.data, + &new_trust_pw_blob.length); + if (!ok) { + status = NT_STATUS_UNMAPPABLE_CHARACTER; + if (errno == ENOMEM) { + status = NT_STATUS_NO_MEMORY; + } + DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) " + "failed for of %s - %s\n", + domain, nt_errstr(status)); + TALLOC_FREE(frame); + return status; + } + nt_hashes[0] = current_nt_hash; num_nt_hashes = 1; @@ -287,13 +306,16 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, case SEC_CHAN_WKSTA: case SEC_CHAN_BDC: - ok = secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type); + ok = secrets_store_machine_password(new_trust_pw_str, + domain, + sec_channel_type); if (!ok) { DEBUG(0, ("secrets_store_machine_password failed for domain %s!\n", domain)); TALLOC_FREE(frame); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + TALLOC_FREE(new_trust_pw_str); break; case SEC_CHAN_DNS_DOMAIN: @@ -302,7 +324,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, * we need to get the sid first for the * pdb_set_trusteddom_pw call */ - ok = pdb_set_trusteddom_pw(domain, new_trust_passwd, + ok = pdb_set_trusteddom_pw(domain, new_trust_pw_str, &td->security_identifier); if (!ok) { DEBUG(0, ("pdb_set_trusteddom_pw() failed for domain %s!\n", @@ -310,6 +332,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, TALLOC_FREE(frame); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + TALLOC_FREE(new_trust_pw_str); break; default: @@ -321,7 +344,7 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, current_timestring(talloc_tos(), false), __func__, domain)); status = netlogon_creds_cli_ServerPasswordSet(context, b, - new_trust_passwd, + &new_trust_pw_blob, new_trust_version); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("%s : %s(%s) remote password change set with %s failed - %s\n", @@ -336,7 +359,9 @@ NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, current_timestring(talloc_tos(), false), __func__, domain, context_name)); - ok = cli_credentials_set_password(creds, new_trust_passwd, CRED_SPECIFIED); + ok = cli_credentials_set_utf16_password(creds, + &new_trust_pw_blob, + CRED_SPECIFIED); if (!ok) { DEBUG(0, ("cli_credentials_set_password failed for domain %s!\n", domain)); -- 2.11.4.GIT