diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/rpc_samr.h | 43 | ||||
-rw-r--r-- | source3/rpc_client/cli_samr.c | 89 | ||||
-rw-r--r-- | source3/rpc_parse/parse_samr.c | 168 |
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. ********************************************************************/ |