diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/rpc_samr.h | 16 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 16 | ||||
-rw-r--r-- | source3/rpc_client/cli_samr.c | 39 | ||||
-rw-r--r-- | source3/rpc_parse/parse_samr.c | 70 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr.c | 32 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 105 | ||||
-rw-r--r-- | source3/rpcclient/cmd_samr.c | 77 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 16 |
8 files changed, 295 insertions, 76 deletions
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index e0b179224d..3af7d5c720 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -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; diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 499f225d2c..5f84d138e6 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -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; diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index 79f27fe2bb..1910e3a25f 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -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; diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index a0108d9eb7..b419fbebc4 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -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; diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c index e8fd86ba46..015ed6c5ea 100644 --- a/source3/rpc_server/srv_samr.c +++ b/source3/rpc_server/srv_samr.c @@ -680,6 +680,37 @@ static BOOL api_samr_connect4(pipes_struct *p) } /******************************************************************* + 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 } }; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index bf0e2ba070..75a72fa028 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -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); @@ -1472,6 +1472,97 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_ } /******************************************************************* + _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(); diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index 93a3e39036..ff9674b9fe 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -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 } }; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 0798541cb5..501aba3336 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -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; } } |