r13442: Implement samr_chgpasswd_user3 server-side.
authorGünther Deschner <gd@samba.org>
Fri, 10 Feb 2006 23:09:00 +0000 (23:09 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:10:03 +0000 (11:10 -0500)
Guenther
(This used to be commit f60eddc0a4dfe623e5f115533a62c03810fd5f38)

source3/include/rpc_samr.h
source3/nsswitch/winbindd_pam.c
source3/rpc_client/cli_samr.c
source3/rpc_parse/parse_samr.c
source3/rpc_server/srv_samr.c
source3/rpc_server/srv_samr_nt.c
source3/rpcclient/cmd_samr.c
source3/smbd/chgpasswd.c

index e0b179224d82425ffc8f38f0b27f3837ae9fc521..3af7d5c7203e0dbe6c0eee54090c761a99c4b29e 100644 (file)
@@ -143,7 +143,7 @@ SamrTestPrivateFunctionsUser
 #define SAMR_CONNECT           0x39
 #define SAMR_SET_USERINFO      0x3A
 #define SAMR_CONNECT4          0x3E
-#define SAMR_CHGPASSWD3        0x3F
+#define SAMR_CHGPASSWD_USER3   0x3F
 #define SAMR_CONNECT5          0x40
 
 typedef struct logon_hours_info
@@ -1826,7 +1826,7 @@ typedef struct r_samr_chgpasswd_user_info
 } SAMR_R_CHGPASSWD_USER;
 
 /* SAMR_Q_CHGPASSWD3 */
-typedef struct q_samr_chgpasswd3
+typedef struct q_samr_chgpasswd_user3
 {
        uint32 ptr_0;
 
@@ -1846,7 +1846,7 @@ typedef struct q_samr_chgpasswd3
 
        SAMR_ENC_PASSWD password3;
 
-} SAMR_Q_CHGPASSWD3;
+} SAMR_Q_CHGPASSWD_USER3;
 
 #define REJECT_REASON_TOO_SHORT                0x00000001
 #define REJECT_REASON_IN_HISTORY       0x00000002
@@ -1862,13 +1862,15 @@ typedef struct samr_change_reject
 } SAMR_CHANGE_REJECT;
 
 /* SAMR_R_CHGPASSWD3 */
-typedef struct r_samr_chgpasswd3
+typedef struct r_samr_chgpasswd_user3
 {
-       SAM_UNK_INFO_1 info;
-       SAMR_CHANGE_REJECT reject;
+       uint32 ptr_info;
+       uint32 ptr_reject;
+       SAM_UNK_INFO_1 *info;
+       SAMR_CHANGE_REJECT *reject;
        NTSTATUS status; /* 0 == OK, C000006A (NT_STATUS_WRONG_PASSWORD) */
 
-} SAMR_R_CHGPASSWD3;
+} SAMR_R_CHGPASSWD_USER3;
 
 
 
index 499f225d2cb7c0422fb98101f90aee745c8d4cdd..5f84d138e6d86fcedde3885d37d9c43d0449a5c7 100644 (file)
@@ -1557,8 +1557,8 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
        struct winbindd_domain *contact_domain;
        struct rpc_pipe_client *cli;
        BOOL got_info = False;
-       SAM_UNK_INFO_1 *info;
-       SAMR_CHANGE_REJECT *reject;
+       SAM_UNK_INFO_1 info;
+       SAMR_CHANGE_REJECT reject;
 
        DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
                state->request.data.chauthtok.user));
@@ -1594,18 +1594,18 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
        if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
 
                state->response.data.auth.policy.min_length_password = 
-                       info->min_length_password;
+                       info.min_length_password;
                state->response.data.auth.policy.password_history = 
-                       info->password_history;
+                       info.password_history;
                state->response.data.auth.policy.password_properties = 
-                       info->password_properties;
+                       info.password_properties;
                state->response.data.auth.policy.expire = 
-                       nt_time_to_unix_abs(&info->expire);
+                       nt_time_to_unix_abs(&info.expire);
                state->response.data.auth.policy.min_passwordage = 
-                       nt_time_to_unix_abs(&info->min_passwordage);
+                       nt_time_to_unix_abs(&info.min_passwordage);
 
                state->response.data.auth.reject_reason = 
-                       reject->reject_reason;
+                       reject.reject_reason;
 
                got_info = True;
                
index 79f27fe2bb9bad98f69742cb665bf04406476d0b..1910e3a25f15f1857c6f53c00a8bba3dc7e1442c 100644 (file)
@@ -1253,12 +1253,12 @@ NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
                                const char *username, 
                                const char *newpassword, 
                                const char *oldpassword,
-                               SAM_UNK_INFO_1 **info,
-                               SAMR_CHANGE_REJECT **reject)
+                               SAM_UNK_INFO_1 *info,
+                               SAMR_CHANGE_REJECT *reject)
 {
        prs_struct qbuf, rbuf;
-       SAMR_Q_CHGPASSWD3 q;
-       SAMR_R_CHGPASSWD3 r;
+       SAMR_Q_CHGPASSWD_USER3 q;
+       SAMR_R_CHGPASSWD_USER3 r;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
        uchar new_nt_password[516];
@@ -1273,14 +1273,11 @@ NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
 
        char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
 
-       DEBUG(10,("rpccli_samr_chgpasswd3\n"));
+       DEBUG(10,("rpccli_samr_chgpasswd_user3\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);
@@ -1309,27 +1306,25 @@ NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
 
        /* 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);
+       init_samr_q_chgpasswd_user3(&q, srv_name_slash, username, 
+                                   new_nt_password, 
+                                   old_nt_hash_enc, 
+                                   new_lm_password,
+                                   old_lanman_hash_enc);
+       r.info = info;
+       r.reject = reject;
 
-       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD3,
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD_USER3,
                q, r,
                qbuf, rbuf,
-               samr_io_q_chgpasswd3,
-               samr_io_r_chgpasswd3,
+               samr_io_q_chgpasswd_user3,
+               samr_io_r_chgpasswd_user3,
                NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
-       if (!NT_STATUS_IS_OK(result = r.status)) {
-               *info = &r.info;
-               *reject = &r.reject;
-               goto done;
-       }
-
+       result = r.status;
+       
  done:
 
        return result;
index a0108d9eb7b75f024487bc23662118d52a4655b3..b419fbebc41d4119053ad02dc1bec37903fb8952 100644 (file)
@@ -7299,7 +7299,7 @@ inits a SAMR_R_CHGPASSWD_USER structure.
 
 void init_samr_r_chgpasswd_user(SAMR_R_CHGPASSWD_USER * r_u, NTSTATUS status)
 {
-       DEBUG(5, ("init_r_chgpasswd_user\n"));
+       DEBUG(5, ("init_samr_r_chgpasswd_user\n"));
 
        r_u->status = status;
 }
@@ -7330,14 +7330,14 @@ 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])
+void init_samr_q_chgpasswd_user3(SAMR_Q_CHGPASSWD_USER3 * 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"));
+       DEBUG(5, ("init_samr_q_chgpasswd_user3\n"));
 
        q_u->ptr_0 = 1;
        init_unistr2(&q_u->uni_dest_host, dest_host, UNI_FLAGS_NONE);
@@ -7361,13 +7361,13 @@ void init_samr_q_chgpasswd3(SAMR_Q_CHGPASSWD3 * q_u,
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_q_chgpasswd3(const char *desc, SAMR_Q_CHGPASSWD3 * q_u,
-                         prs_struct *ps, int depth)
+BOOL samr_io_q_chgpasswd_user3(const char *desc, SAMR_Q_CHGPASSWD_USER3 * q_u,
+                              prs_struct *ps, int depth)
 {
        if (q_u == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "samr_io_q_chgpasswd3");
+       prs_debug(ps, depth, desc, "samr_io_q_chgpasswd_user3");
        depth++;
 
        if(!prs_align(ps))
@@ -7408,14 +7408,30 @@ BOOL samr_io_q_chgpasswd3(const char *desc, SAMR_Q_CHGPASSWD3 * q_u,
 }
 
 /*******************************************************************
-inits a SAMR_R_CHGPASSWD3 structure.
+inits a SAMR_R_CHGPASSWD_USER3 structure.
 ********************************************************************/
 
-void init_samr_r_chgpasswd3(SAMR_R_CHGPASSWD3 * r_u, NTSTATUS status)
+void init_samr_r_chgpasswd_user3(SAMR_R_CHGPASSWD_USER3 *r_u, NTSTATUS status, 
+                                SAMR_CHANGE_REJECT *reject, SAM_UNK_INFO_1 *info)
 {
-       DEBUG(5, ("init_r_chgpasswd3\n"));
+       DEBUG(5, ("init_samr_r_chgpasswd_user3\n"));
 
        r_u->status = status;
+       r_u->info = 0;
+       r_u->ptr_info = 0;
+       r_u->reject = 0;
+       r_u->ptr_reject = 0;
+
+       if (NT_STATUS_EQUAL(r_u->status, NT_STATUS_PASSWORD_RESTRICTION)) {
+               if (info) {
+                       r_u->info = info;
+                       r_u->ptr_info = 1;
+               }
+               if (reject) {
+                       r_u->reject = reject;
+                       r_u->ptr_reject = 1;
+               }
+       }
 }
 
 /*******************************************************************
@@ -7452,41 +7468,37 @@ BOOL samr_io_change_reject(const char *desc, SAMR_CHANGE_REJECT *reject, prs_str
 reads or writes a structure.
 ********************************************************************/
 
-BOOL samr_io_r_chgpasswd3(const char *desc, SAMR_R_CHGPASSWD3 * r_u,
-                         prs_struct *ps, int depth)
+BOOL samr_io_r_chgpasswd_user3(const char *desc, SAMR_R_CHGPASSWD_USER3 *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");
+       prs_debug(ps, depth, desc, "samr_io_r_chgpasswd_user3");
        depth++;
 
-       if(!prs_align(ps))
+       if (!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_info", ps, depth, &ptr_info))
+       if (!prs_uint32("ptr_info", ps, depth, &r_u->ptr_info))
                return False;
 
-       if (ptr_info) {
-
+       if (r_u->ptr_info && r_u->info != NULL) {
                /* SAM_UNK_INFO_1 */
-               if(!sam_io_unk_info1("info", &r_u->info, ps, depth))
+               if (!sam_io_unk_info1("info", r_u->info, ps, depth))
                        return False;
        }
 
-       if(!prs_uint32("ptr_reject", ps, depth, &ptr_reject))
+       if (!prs_uint32("ptr_reject", ps, depth, &r_u->ptr_reject))
                return False;
                             
-       if (ptr_reject) {
-
+       if (r_u->ptr_reject && r_u->reject != NULL) {
                /* SAMR_CHANGE_REJECT */
-               if(!samr_io_change_reject("reject", &r_u->reject, ps, depth))
+               if (!samr_io_change_reject("reject", r_u->reject, ps, depth))
                        return False;
        }
 
-       if(!prs_ntstatus("status", ps, depth, &r_u->status))
+       if (!prs_ntstatus("status", ps, depth, &r_u->status))
                return False;
 
        return True;
index e8fd86ba467f7899c6a3dabd9698f98df384edf5..015ed6c5ea9b10d41d5998799b8563b856f801f4 100644 (file)
@@ -679,6 +679,37 @@ static BOOL api_samr_connect4(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+ api_samr_chgpasswd_user3
+ ********************************************************************/
+
+static BOOL api_samr_chgpasswd_user3(pipes_struct *p)
+{
+       SAMR_Q_CHGPASSWD_USER3 q_u;
+       SAMR_R_CHGPASSWD_USER3 r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* change password request */
+       if (!samr_io_q_chgpasswd_user3("", &q_u, data, 0)) {
+               DEBUG(0,("api_samr_chgpasswd_user3: Failed to unmarshall SAMR_Q_CHGPASSWD_USER3.\n"));
+               return False;
+       }
+
+       r_u.status = _samr_chgpasswd_user3(p, &q_u, &r_u);
+
+       /* store the response in the SMB stream */
+       if(!samr_io_r_chgpasswd_user3("", &r_u, rdata, 0)) {
+               DEBUG(0,("api_samr_chgpasswd_user3: Failed to marshall SAMR_R_CHGPASSWD_USER3.\n" ));
+               return False;
+       }
+
+       return True;
+}
+
 /*******************************************************************
  api_samr_connect5
  ********************************************************************/
@@ -1524,6 +1555,7 @@ static struct api_struct api_samr_cmds [] =
       {"SAMR_QUERY_DOMAIN_INFO2", SAMR_QUERY_DOMAIN_INFO2, api_samr_query_domain_info2},
       {"SAMR_SET_DOMAIN_INFO"   , SAMR_SET_DOMAIN_INFO  , api_samr_set_dom_info     },
       {"SAMR_CONNECT4"          , SAMR_CONNECT4         , api_samr_connect4         },
+      {"SAMR_CHGPASSWD_USER3"   , SAMR_CHGPASSWD_USER3  , api_samr_chgpasswd_user3  },
       {"SAMR_CONNECT5"          , SAMR_CONNECT5         , api_samr_connect5         }
 };
 
index bf0e2ba070c8639ae87eacb0c1090667578a1158..75a72fa0280a50c58bfecab6e94b27fe363ee216 100644 (file)
@@ -1462,7 +1462,7 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_
         */
 
        r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
-                               q_u->nt_newpass.pass, q_u->nt_oldhash.hash);
+                               q_u->nt_newpass.pass, q_u->nt_oldhash.hash, NULL);
 
        init_samr_r_chgpasswd_user(r_u, r_u->status);
 
@@ -1471,6 +1471,97 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_
        return r_u->status;
 }
 
+/*******************************************************************
+ _samr_chgpasswd_user3
+ ********************************************************************/
+
+NTSTATUS _samr_chgpasswd_user3(pipes_struct *p, SAMR_Q_CHGPASSWD_USER3 *q_u, SAMR_R_CHGPASSWD_USER3 *r_u)
+{
+       fstring user_name;
+       fstring wks;
+       uint32 reject_reason;
+       SAM_UNK_INFO_1 *info = NULL;
+       SAMR_CHANGE_REJECT *reject = NULL;
+
+       DEBUG(5,("_samr_chgpasswd_user3: %d\n", __LINE__));
+
+       rpcstr_pull(user_name, q_u->uni_user_name.buffer, sizeof(user_name), q_u->uni_user_name.uni_str_len*2, 0);
+       rpcstr_pull(wks, q_u->uni_dest_host.buffer, sizeof(wks), q_u->uni_dest_host.uni_str_len*2,0);
+
+       DEBUG(5,("_samr_chgpasswd_user3: user: %s wks: %s\n", user_name, wks));
+
+       /*
+        * Pass the user through the NT -> unix user mapping
+        * function.
+        */
+       (void)map_username(user_name);
+       /*
+        * UNIX username case mangling not required, pass_oem_change 
+        * is case insensitive.
+        */
+
+       r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
+                                     q_u->nt_newpass.pass, q_u->nt_oldhash.hash, &reject_reason);
+
+       if (NT_STATUS_EQUAL(r_u->status, NT_STATUS_PASSWORD_RESTRICTION)) {
+
+               uint32 min_pass_len,pass_hist,password_properties;
+               time_t u_expire, u_min_age;
+               NTTIME nt_expire, nt_min_age;
+               uint32 account_policy_temp;
+
+               if ((info = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_INFO_1)) == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if ((reject = TALLOC_ZERO_P(p->mem_ctx, SAMR_CHANGE_REJECT)) == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               ZERO_STRUCTP(info);
+               ZERO_STRUCTP(reject);
+
+               become_root();
+
+               /* AS ROOT !!! */
+
+               pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp);
+               min_pass_len = account_policy_temp;
+
+               pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp);
+               pass_hist = account_policy_temp;
+
+               pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
+               password_properties = account_policy_temp;
+
+               pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
+               u_expire = account_policy_temp;
+
+               pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp);
+               u_min_age = account_policy_temp;
+
+               /* !AS ROOT */
+               
+               unbecome_root();
+
+               unix_to_nt_time_abs(&nt_expire, u_expire);
+               unix_to_nt_time_abs(&nt_min_age, u_min_age);
+
+               init_unk_info1(info, (uint16)min_pass_len, (uint16)pass_hist, 
+                              password_properties, nt_expire, nt_min_age);
+
+               reject->reject_reason = reject_reason;
+       }
+       
+       init_samr_r_chgpasswd_user3(r_u, r_u->status, reject, info);
+
+       DEBUG(5,("_samr_chgpasswd_user3: %d\n", __LINE__));
+
+       return r_u->status;
+}
+
 /*******************************************************************
 makes a SAMR_R_LOOKUP_RIDS structure.
 ********************************************************************/
@@ -2090,7 +2181,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
 {
        struct samr_info *info = NULL;
        SAM_UNK_CTR *ctr;
-       uint32 min_pass_len,pass_hist,flag;
+       uint32 min_pass_len,pass_hist,password_properties;
        time_t u_expire, u_min_age;
        NTTIME nt_expire, nt_min_age;
 
@@ -2136,7 +2227,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
                        pass_hist = account_policy_temp;
 
                        pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
-                       flag = account_policy_temp;
+                       password_properties = account_policy_temp;
 
                        pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
                        u_expire = account_policy_temp;
@@ -2152,7 +2243,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
                        unix_to_nt_time_abs(&nt_min_age, u_min_age);
 
                        init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist, 
-                                      flag, nt_expire, nt_min_age);
+                                      password_properties, nt_expire, nt_min_age);
                        break;
                case 0x02:
 
@@ -4815,7 +4906,7 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p,
 {
        struct samr_info *info = NULL;
        SAM_UNK_CTR *ctr;
-       uint32 min_pass_len,pass_hist,flag;
+       uint32 min_pass_len,pass_hist,password_properties;
        time_t u_expire, u_min_age;
        NTTIME nt_expire, nt_min_age;
 
@@ -4855,7 +4946,7 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p,
                        pass_hist = account_policy_temp;
 
                        pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
-                       flag = account_policy_temp;
+                       password_properties = account_policy_temp;
 
                        pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
                        u_expire = account_policy_temp;
@@ -4867,7 +4958,7 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p,
                        unix_to_nt_time_abs(&nt_min_age, u_min_age);
 
                        init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist, 
-                                      flag, nt_expire, nt_min_age);
+                                      password_properties, nt_expire, nt_min_age);
                        break;
                case 0x02:
                        become_root();          
index 93a3e39036323f9aff1cf234cd79b63d9249d79a..ff9674b9fe07bcc43da092c2a053e08e2315f202 100644 (file)
@@ -1915,6 +1915,82 @@ done:
        return result;
 }
 
+/* Change user password */
+
+static NTSTATUS cmd_samr_chgpasswd3(struct rpc_pipe_client *cli, 
+                                   TALLOC_CTX *mem_ctx,
+                                   int argc, const char **argv) 
+{
+       POLICY_HND connect_pol, domain_pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       const char *user, *oldpass, *newpass;
+       uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+       SAM_UNK_INFO_1 info;
+       SAMR_CHANGE_REJECT reject;
+
+       if (argc < 3) {
+               printf("Usage: %s username oldpass newpass\n", argv[0]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       user = argv[1];
+       oldpass = argv[2];
+       newpass = argv[3];
+       
+       /* Get sam policy handle */
+
+       result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+                                  &connect_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Get domain policy handle */
+
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+                                     access_mask,
+                                     &domain_sid, &domain_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Change user password */
+       result = rpccli_samr_chgpasswd3(cli, mem_ctx, user, newpass, oldpass, &info, &reject);
+
+       if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
+       
+               display_sam_unk_info_1(&info);
+
+               switch (reject.reject_reason) {
+                       case REJECT_REASON_TOO_SHORT:
+                               d_printf("REJECT_REASON_TOO_SHORT\n");
+                               break;
+                       case REJECT_REASON_IN_HISTORY:
+                               d_printf("REJECT_REASON_IN_HISTORY\n");
+                               break;
+                       case REJECT_REASON_NOT_COMPLEX:
+                               d_printf("REJECT_REASON_NOT_COMPLEX\n");
+                               break;
+                       case 0:
+                               break;
+                       default:
+                               d_printf("unknown reject reason: %d\n", reject.reject_reason);
+                               break;
+               }
+       }
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       if (!NT_STATUS_IS_OK(result)) goto done;
+
+       result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
+       if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+       return result;
+}
 
 /* List of commands exported by this module */
 
@@ -1945,5 +2021,6 @@ struct cmd_set samr_commands[] = {
        { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
 
        { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
+       { "chgpasswd3",         RPC_RTYPE_NTSTATUS, cmd_samr_chgpasswd,             NULL, PI_SAMR, NULL, "Change user password", "" },
        { NULL }
 };
index 0798541cb502c3f87c51056c28c0638a10dc7dfc..501aba3336f0d8a9278b234e88617fee0c8aaf28 100644 (file)
@@ -703,7 +703,8 @@ NTSTATUS pass_oem_change(char *user,
                         uchar password_encrypted_with_lm_hash[516], 
                         const uchar old_lm_hash_encrypted[16],
                         uchar password_encrypted_with_nt_hash[516], 
-                        const uchar old_nt_hash_encrypted[16])
+                        const uchar old_nt_hash_encrypted[16],
+                        uint32 *reject_reason)
 {
        pstring new_passwd;
        SAM_ACCOUNT *sampass = NULL;
@@ -718,7 +719,7 @@ NTSTATUS pass_oem_change(char *user,
 
        /* We've already checked the old password here.... */
        become_root();
-       nt_status = change_oem_password(sampass, NULL, new_passwd, True);
+       nt_status = change_oem_password(sampass, NULL, new_passwd, True, reject_reason);
        unbecome_root();
 
        memset(new_passwd, 0, sizeof(new_passwd));
@@ -1007,7 +1008,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext)
  is correct before calling. JRA.
 ************************************************************/
 
-NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root)
+NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason)
 {
        uint32 min_len, min_age;
        struct passwd *pass = NULL;
@@ -1040,11 +1041,17 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
                DEBUG(1, ("user %s cannot change password - password too short\n", 
                          username));
                DEBUGADD(1, (" account policy min password len = %d\n", min_len));
+               if (samr_reject_reason) {
+                       *samr_reject_reason = REJECT_REASON_TOO_SHORT;
+               }
                return NT_STATUS_PASSWORD_RESTRICTION;
 /*             return NT_STATUS_PWD_TOO_SHORT; */
        }
 
        if (check_passwd_history(hnd,new_passwd)) {
+               if (samr_reject_reason) {
+                       *samr_reject_reason = REJECT_REASON_IN_HISTORY;
+               }
                return NT_STATUS_PASSWORD_RESTRICTION;
        }
 
@@ -1063,6 +1070,9 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
 
                if (check_ret != 0) {
                        DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n"));
+                       if (samr_reject_reason) {
+                               *samr_reject_reason = REJECT_REASON_NOT_COMPLEX;
+                       }
                        return NT_STATUS_PASSWORD_RESTRICTION;
                }
        }