r11963: add rpccli_samr_chgpasswd3 from samba4.
authorGünther Deschner <gd@samba.org>
Tue, 29 Nov 2005 23:23:02 +0000 (23:23 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:05:40 +0000 (11:05 -0500)
Guenther
(This used to be commit 0705fed566efdeab05d605dd239afe67ca5e9811)

source3/include/rpc_samr.h
source3/rpc_client/cli_samr.c
source3/rpc_parse/parse_samr.c

index ac56e2dcc62de15392640c0b66ebf75f57969c71..236c37a17e2a4ade49f0931cb41800cd69edc1d3 100644 (file)
@@ -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
index 047d0a1f956e068f898e8b91daa7fe7175032a5c..fb95da97aefe23f2073339e743c4e772ed5c31bc 100644 (file)
@@ -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 
index ed6abc398b6c07dbb2ce4ed7adf5c8aaa3aaf4c2..b5aa2cd831a9d4b03aaf10d28623fc7cd4bf3219 100644 (file)
@@ -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,
@@ -7245,6 +7245,172 @@ BOOL samr_io_r_chgpasswd_user(const char *desc, SAMR_R_CHGPASSWD_USER * r_u,
        return True;
 }
 
+/*******************************************************************
+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.
 ********************************************************************/