summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/rpc_samr.h43
-rw-r--r--source3/rpc_client/cli_samr.c89
-rw-r--r--source3/rpc_parse/parse_samr.c168
3 files changed, 299 insertions, 1 deletions
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h
index ac56e2dcc6..236c37a17e 100644
--- a/source3/include/rpc_samr.h
+++ b/source3/include/rpc_samr.h
@@ -143,6 +143,7 @@ SamrTestPrivateFunctionsUser
#define SAMR_CONNECT 0x39
#define SAMR_SET_USERINFO 0x3A
#define SAMR_CONNECT4 0x3E
+#define SAMR_CHGPASSWD3 0x3F
#define SAMR_CONNECT5 0x40
typedef struct logon_hours_info
@@ -1810,6 +1811,48 @@ typedef struct r_samr_chgpasswd_user_info
} SAMR_R_CHGPASSWD_USER;
+/* SAMR_Q_CHGPASSWD3 */
+typedef struct q_samr_chgpasswd3
+{
+ uint32 ptr_0;
+
+ UNIHDR hdr_dest_host; /* server name unicode header */
+ UNISTR2 uni_dest_host; /* server name unicode string */
+
+ UNIHDR hdr_user_name; /* username unicode string header */
+ UNISTR2 uni_user_name; /* username unicode string */
+
+ SAMR_ENC_PASSWD nt_newpass;
+ SAMR_ENC_HASH nt_oldhash;
+
+ uint32 lm_change; /* 0x0000 0001 */
+
+ SAMR_ENC_PASSWD lm_newpass;
+ SAMR_ENC_HASH lm_oldhash;
+
+ SAMR_ENC_PASSWD password3;
+
+} SAMR_Q_CHGPASSWD3;
+
+/* SAMR_CHANGE_REJECT */
+typedef struct samr_change_reject
+{
+ uint32 reject_reason;
+ uint32 unknown1;
+ uint32 unknown2;
+
+} SAMR_CHANGE_REJECT;
+
+/* SAMR_R_CHGPASSWD3 */
+typedef struct r_samr_chgpasswd3
+{
+ SAM_UNK_INFO_1 info;
+ SAMR_CHANGE_REJECT reject;
+ NTSTATUS status; /* 0 == OK, C000006A (NT_STATUS_WRONG_PASSWORD) */
+
+} SAMR_R_CHGPASSWD3;
+
+
/* SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN */
typedef struct q_samr_remove_sid_foreign_domain_info
diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c
index 047d0a1f95..fb95da97ae 100644
--- a/source3/rpc_client/cli_samr.c
+++ b/source3/rpc_client/cli_samr.c
@@ -1205,6 +1205,95 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
return result;
}
+/* change password 3 */
+
+NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const char *username,
+ const char *newpassword,
+ const char *oldpassword,
+ SAM_UNK_INFO_1 **info,
+ SAMR_CHANGE_REJECT **reject)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_CHGPASSWD3 q;
+ SAMR_R_CHGPASSWD3 r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ uchar new_nt_password[516];
+ uchar new_lm_password[516];
+ uchar old_nt_hash[16];
+ uchar old_lanman_hash[16];
+ uchar old_nt_hash_enc[16];
+ uchar old_lanman_hash_enc[16];
+
+ uchar new_nt_hash[16];
+ uchar new_lanman_hash[16];
+
+ char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
+
+ DEBUG(10,("rpccli_samr_chgpasswd3\n"));
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ *info = NULL;
+ *reject = NULL;
+
+ /* Calculate the MD4 hash (NT compatible) of the password */
+ E_md4hash(oldpassword, old_nt_hash);
+ E_md4hash(newpassword, new_nt_hash);
+
+ if (lp_client_lanman_auth()
+ && E_deshash(newpassword, new_lanman_hash)
+ && E_deshash(oldpassword, old_lanman_hash)) {
+ /* E_deshash returns false for 'long' passwords (> 14
+ DOS chars). This allows us to match Win2k, which
+ does not store a LM hash for these passwords (which
+ would reduce the effective password length to 14) */
+
+ encode_pw_buffer(new_lm_password, newpassword, STR_UNICODE);
+
+ SamOEMhash( new_lm_password, old_nt_hash, 516);
+ E_old_pw_hash( new_nt_hash, old_lanman_hash, old_lanman_hash_enc);
+ } else {
+ ZERO_STRUCT(new_lm_password);
+ ZERO_STRUCT(old_lanman_hash_enc);
+ }
+
+ encode_pw_buffer(new_nt_password, newpassword, STR_UNICODE);
+
+ SamOEMhash( new_nt_password, old_nt_hash, 516);
+ E_old_pw_hash( new_nt_hash, old_nt_hash, old_nt_hash_enc);
+
+ /* Marshall data and send request */
+
+ init_samr_q_chgpasswd3(&q, srv_name_slash, username,
+ new_nt_password,
+ old_nt_hash_enc,
+ new_lm_password,
+ old_lanman_hash_enc);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD3,
+ q, r,
+ qbuf, rbuf,
+ samr_io_q_chgpasswd3,
+ samr_io_r_chgpasswd3,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ if (!NT_STATUS_IS_OK(result = r.status)) {
+ *info = &r.info;
+ *reject = &r.reject;
+ goto done;
+ }
+
+ done:
+
+ return result;
+}
+
/* This function returns the bizzare set of (max_entries, max_size) required
for the QueryDisplayInfo RPC to actually work against a domain controller
with large (10k and higher) numbers of users. These values were
diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c
index ed6abc398b..b5aa2cd831 100644
--- a/source3/rpc_parse/parse_samr.c
+++ b/source3/rpc_parse/parse_samr.c
@@ -7137,7 +7137,7 @@ BOOL samr_io_enc_hash(const char *desc, SAMR_ENC_HASH * hsh,
}
/*******************************************************************
-inits a SAMR_R_GET_DOM_PWINFO structure.
+inits a SAMR_Q_CHGPASSWD_USER structure.
********************************************************************/
void init_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER * q_u,
@@ -7246,6 +7246,172 @@ BOOL samr_io_r_chgpasswd_user(const char *desc, SAMR_R_CHGPASSWD_USER * r_u,
}
/*******************************************************************
+inits a SAMR_Q_CHGPASSWD3 structure.
+********************************************************************/
+
+void init_samr_q_chgpasswd3(SAMR_Q_CHGPASSWD3 * q_u,
+ const char *dest_host, const char *user_name,
+ const uchar nt_newpass[516],
+ const uchar nt_oldhash[16],
+ const uchar lm_newpass[516],
+ const uchar lm_oldhash[16])
+{
+ DEBUG(5, ("init_samr_q_chgpasswd3\n"));
+
+ q_u->ptr_0 = 1;
+ init_unistr2(&q_u->uni_dest_host, dest_host, UNI_FLAGS_NONE);
+ init_uni_hdr(&q_u->hdr_dest_host, &q_u->uni_dest_host);
+
+ init_unistr2(&q_u->uni_user_name, user_name, UNI_FLAGS_NONE);
+ init_uni_hdr(&q_u->hdr_user_name, &q_u->uni_user_name);
+
+ init_enc_passwd(&q_u->nt_newpass, (const char *)nt_newpass);
+ init_enc_hash(&q_u->nt_oldhash, nt_oldhash);
+
+ q_u->lm_change = 0x01;
+
+ init_enc_passwd(&q_u->lm_newpass, (const char *)lm_newpass);
+ init_enc_hash(&q_u->lm_oldhash, lm_oldhash);
+
+ init_enc_passwd(&q_u->password3, NULL);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_q_chgpasswd3(const char *desc, SAMR_Q_CHGPASSWD3 * q_u,
+ prs_struct *ps, int depth)
+{
+ if (q_u == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_q_chgpasswd3");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_0", ps, depth, &q_u->ptr_0))
+ return False;
+
+ if(!smb_io_unihdr("", &q_u->hdr_dest_host, ps, depth))
+ return False;
+ if(!smb_io_unistr2("", &q_u->uni_dest_host, q_u->hdr_dest_host.buffer, ps, depth))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unihdr("", &q_u->hdr_user_name, ps, depth))
+ return False;
+ if(!smb_io_unistr2("", &q_u->uni_user_name, q_u->hdr_user_name.buffer,ps, depth))
+ return False;
+
+ if(!samr_io_enc_passwd("nt_newpass", &q_u->nt_newpass, ps, depth))
+ return False;
+ if(!samr_io_enc_hash("nt_oldhash", &q_u->nt_oldhash, ps, depth))
+ return False;
+
+ if(!prs_uint32("lm_change", ps, depth, &q_u->lm_change))
+ return False;
+
+ if(!samr_io_enc_passwd("lm_newpass", &q_u->lm_newpass, ps, depth))
+ return False;
+ if(!samr_io_enc_hash("lm_oldhash", &q_u->lm_oldhash, ps, depth))
+ return False;
+
+ if(!samr_io_enc_passwd("password3", &q_u->password3, ps, depth))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+inits a SAMR_R_CHGPASSWD3 structure.
+********************************************************************/
+
+void init_samr_r_chgpasswd3(SAMR_R_CHGPASSWD3 * r_u, NTSTATUS status)
+{
+ DEBUG(5, ("init_r_chgpasswd3\n"));
+
+ r_u->status = status;
+}
+
+/*******************************************************************
+ Reads or writes an SAMR_CHANGE_REJECT structure.
+********************************************************************/
+
+BOOL samr_io_change_reject(const char *desc, SAMR_CHANGE_REJECT *reject, prs_struct *ps, int depth)
+{
+ if (reject == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_change_reject");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(UNMARSHALLING(ps))
+ ZERO_STRUCTP(reject);
+
+ if (!prs_uint32("reject_reason", ps, depth, &reject->reject_reason))
+ return False;
+
+ if (!prs_uint32("unknown1", ps, depth, &reject->unknown1))
+ return False;
+
+ if (!prs_uint32("unknown2", ps, depth, &reject->unknown2))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_r_chgpasswd3(const char *desc, SAMR_R_CHGPASSWD3 * r_u,
+ prs_struct *ps, int depth)
+{
+ uint32 ptr_info, ptr_reject;
+
+ if (r_u == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_r_chgpasswd3");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_info", ps, depth, &ptr_info))
+ return False;
+
+ if (ptr_info) {
+
+ /* SAM_UNK_INFO_1 */
+ if(!sam_io_unk_info1("info", &r_u->info, ps, depth))
+ return False;
+ }
+
+ if(!prs_uint32("ptr_reject", ps, depth, &ptr_reject))
+ return False;
+
+ if (ptr_reject) {
+
+ /* SAMR_CHANGE_REJECT */
+ if(!samr_io_change_reject("reject", &r_u->reject, ps, depth))
+ return False;
+ }
+
+ if(!prs_ntstatus("status", ps, depth, &r_u->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
reads or writes a structure.
********************************************************************/