libcli/auth: pass the cleartext blob to netlogon_creds_cli_ServerPasswordSet*()
authorStefan Metzmacher <metze@samba.org>
Tue, 13 Jun 2017 09:18:37 +0000 (11:18 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 27 Jun 2017 14:57:46 +0000 (16:57 +0200)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12782

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
libcli/auth/netlogon_creds_cli.c
libcli/auth/netlogon_creds_cli.h
source3/libnet/libnet_join.c
source3/libsmb/trusts_util.c

index fabb265..367bf6c 100644 (file)
@@ -37,6 +37,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;
 
@@ -1751,7 +1752,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;
@@ -1769,20 +1770,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);
@@ -2052,7 +2054,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();
index dc27420..cecb0e6 100644 (file)
@@ -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,
index ecae4c5..99bba2a 100644 (file)
@@ -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);
index 128beb7..5bc8005 100644 (file)
@@ -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));