diff options
-rw-r--r-- | source3/include/rpc_samr.h | 3 | ||||
-rw-r--r-- | source3/rpc_parse/parse_samr.c | 4 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 52 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_util.c | 189 |
4 files changed, 246 insertions, 2 deletions
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 49ea36f364..910ccee113 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -260,8 +260,9 @@ typedef struct sam_user_info_25 uint32 group_rid; /* Primary Group ID */ uint32 acb_info; /* account info (ACB_xxxx bit-mask) */ + uint32 fields_present; - uint32 unknown_6[6]; + uint32 unknown_5[5]; uint8 pass[532]; diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 027d5fba85..d661b225e0 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -6041,8 +6041,10 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str return False; if(!prs_uint32("acb_info ", ps, depth, &usr->acb_info)) return False; + if(!prs_uint32("fields_present ", ps, depth, &usr->fields_present)) + return False; - if(!prs_uint32s(False, "unknown_6 ", ps, depth, usr->unknown_6, 6)) + if(!prs_uint32s(False, "unknown_5 ", ps, depth, usr->unknown_5, 5)) return False; if(!prs_uint8s(False, "password ", ps, depth, usr->pass, sizeof(usr->pass))) diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index c9e6b552c8..7a06e562ef 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -3299,6 +3299,52 @@ static BOOL set_user_info_pw(uint8 *pass, struct samu *pwd) } /******************************************************************* + set_user_info_25 + ********************************************************************/ + +static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25, + struct samu *pwd) +{ + NTSTATUS status; + + if (id25 == NULL) { + DEBUG(5, ("set_user_info_25: NULL id25\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + copy_id25_to_sam_passwd(pwd, id25); + + /* + * The funny part about the previous two calls is + * that pwd still has the password hashes from the + * passdb entry. These have not been updated from + * id21. I don't know if they need to be set. --jerry + */ + + if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) { + status = pdb_set_unix_primary_group(mem_ctx, pwd); + if ( !NT_STATUS_IS_OK(status) ) { + return status; + } + } + + /* Don't worry about writing out the user account since the + primary group SID is generated solely from the user's Unix + primary group. */ + + /* write the change out */ + if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) { + TALLOC_FREE(pwd); + return status; + } + + /* WARNING: No TALLOC_FREE(pwd), we are about to set the password + * hereafter! */ + + return NT_STATUS_OK; +} + +/******************************************************************* samr_reply_set_userinfo ********************************************************************/ @@ -3401,6 +3447,11 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE dump_data(100, (char *)ctr->info.id25->pass, 532); + r_u->status = set_user_info_25(p->mem_ctx, + ctr->info.id25, pwd); + if (!NT_STATUS_IS_OK(r_u->status)) { + goto done; + } if (!set_user_info_pw(ctr->info.id25->pass, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; @@ -3433,6 +3484,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE r_u->status = NT_STATUS_INVALID_INFO_CLASS; } + done: if ( has_enough_rights ) unbecome_root(); diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c index 03a726dd92..2b65eb210f 100644 --- a/source3/rpc_server/srv_samr_util.c +++ b/source3/rpc_server/srv_samr_util.c @@ -549,3 +549,192 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from) DEBUG(10,("INFO_23 PADDING_2: %02X\n",from->padding2)); } + +/************************************************************* + Copies a SAM_USER_INFO_25 to a struct samu +**************************************************************/ + +void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from) +{ + time_t unix_time, stored_time; + const char *old_string, *new_string; + DATA_BLOB mung; + + if (from == NULL || to == NULL) + return; + + if (from->fields_present & ACCT_LAST_LOGON) { + unix_time=nt_time_to_unix(&from->logon_time); + stored_time = pdb_get_logon_time(to); + DEBUG(10,("INFO_25 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); + if (stored_time != unix_time) + pdb_set_logon_time(to, unix_time, PDB_CHANGED); + } + + if (from->fields_present & ACCT_LAST_LOGOFF) { + unix_time=nt_time_to_unix(&from->logoff_time); + stored_time = pdb_get_logoff_time(to); + DEBUG(10,("INFO_25 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); + if (stored_time != unix_time) + pdb_set_logoff_time(to, unix_time, PDB_CHANGED); + } + + if (from->fields_present & ACCT_EXPIRY) { + unix_time=nt_time_to_unix(&from->kickoff_time); + stored_time = pdb_get_kickoff_time(to); + DEBUG(10,("INFO_25 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); + if (stored_time != unix_time) + pdb_set_kickoff_time(to, unix_time , PDB_CHANGED); + } + + if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) { + unix_time=nt_time_to_unix(&from->pass_can_change_time); + stored_time = pdb_get_pass_can_change_time(to); + DEBUG(10,("INFO_25 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); + if (stored_time != unix_time) + pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED); + } + + if (from->fields_present & ACCT_LAST_PWD_CHANGE) { + unix_time=nt_time_to_unix(&from->pass_last_set_time); + stored_time = pdb_get_pass_last_set_time(to); + DEBUG(10,("INFO_25 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); + if (stored_time != unix_time) + pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED); + } + + if (from->fields_present & ACCT_FORCE_PWD_CHANGE) { + unix_time=nt_time_to_unix(&from->pass_must_change_time); + stored_time=pdb_get_pass_must_change_time(to); + DEBUG(10,("INFO_25 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time)); + if (stored_time != unix_time) + pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_USERNAME) && + (from->hdr_user_name.buffer)) { + old_string = pdb_get_username(to); + new_string = unistr2_static(&from->uni_user_name); + DEBUG(10,("INFO_25 UNI_USER_NAME: %s -> %s\n", old_string, new_string)); + if (STRING_CHANGED) + pdb_set_username(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_FULL_NAME) && + (from->hdr_full_name.buffer)) { + old_string = pdb_get_fullname(to); + new_string = unistr2_static(&from->uni_full_name); + DEBUG(10,("INFO_25 UNI_FULL_NAME: %s -> %s\n",old_string, new_string)); + if (STRING_CHANGED) + pdb_set_fullname(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_HOME_DIR) && + (from->hdr_home_dir.buffer)) { + old_string = pdb_get_homedir(to); + new_string = unistr2_static(&from->uni_home_dir); + DEBUG(10,("INFO_25 UNI_HOME_DIR: %s -> %s\n",old_string,new_string)); + if (STRING_CHANGED) + pdb_set_homedir(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_HOME_DRIVE) && + (from->hdr_dir_drive.buffer)) { + old_string = pdb_get_dir_drive(to); + new_string = unistr2_static(&from->uni_dir_drive); + DEBUG(10,("INFO_25 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string)); + if (STRING_CHANGED) + pdb_set_dir_drive(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_LOGON_SCRIPT) && + (from->hdr_logon_script.buffer)) { + old_string = pdb_get_logon_script(to); + new_string = unistr2_static(&from->uni_logon_script); + DEBUG(10,("INFO_25 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string)); + if (STRING_CHANGED) + pdb_set_logon_script(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_PROFILE) && + (from->hdr_profile_path.buffer)) { + old_string = pdb_get_profile_path(to); + new_string = unistr2_static(&from->uni_profile_path); + DEBUG(10,("INFO_25 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string)); + if (STRING_CHANGED) + pdb_set_profile_path(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_DESCRIPTION) && + (from->hdr_acct_desc.buffer)) { + old_string = pdb_get_acct_desc(to); + new_string = unistr2_static(&from->uni_acct_desc); + DEBUG(10,("INFO_25 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string)); + if (STRING_CHANGED) + pdb_set_acct_desc(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_WORKSTATIONS) && + (from->hdr_workstations.buffer)) { + old_string = pdb_get_workstations(to); + new_string = unistr2_static(&from->uni_workstations); + DEBUG(10,("INFO_25 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string)); + if (STRING_CHANGED) + pdb_set_workstations(to , new_string, PDB_CHANGED); + } + + /* is this right? */ + if ((from->fields_present & ACCT_ADMIN_DESC) && + (from->hdr_unknown_str.buffer)) { + old_string = pdb_get_unknown_str(to); + new_string = unistr2_static(&from->uni_unknown_str); + DEBUG(10,("INFO_25 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); + if (STRING_CHANGED) + pdb_set_unknown_str(to , new_string, PDB_CHANGED); + } + + if ((from->fields_present & ACCT_CALLBACK) && + (from->hdr_munged_dial.buffer)) { + char *newstr; + old_string = pdb_get_munged_dial(to); + mung.length = from->hdr_munged_dial.uni_str_len; + mung.data = (uint8 *) from->uni_munged_dial.buffer; + newstr = (mung.length == 0) ? + NULL : base64_encode_data_blob(mung); + DEBUG(10,("INFO_25 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr)); + if (STRING_CHANGED_NC(old_string,newstr)) + pdb_set_munged_dial(to , newstr, PDB_CHANGED); + + SAFE_FREE(newstr); + } + + if (from->fields_present & ACCT_RID) { + if (from->user_rid == 0) { + DEBUG(10, ("INFO_25: Asked to set User RID to 0 !? Skipping change!\n")); + } else if (from->user_rid != pdb_get_user_rid(to)) { + DEBUG(10,("INFO_25 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid)); + } + } + + if (from->fields_present & ACCT_PRIMARY_GID) { + if (from->group_rid == 0) { + DEBUG(10, ("INFO_25: Asked to set Group RID to 0 !? Skipping change!\n")); + } else if (from->group_rid != pdb_get_group_rid(to)) { + DEBUG(10,("INFO_25 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid)); + pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED); + } + } + + if (from->fields_present & ACCT_FLAGS) { + DEBUG(10,("INFO_25 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info)); + if (from->acb_info != pdb_get_acct_ctrl(to)) { + if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) { + /* We're unlocking a previously locked user. Reset bad password counts. + Patch from Jianliang Lu. <Jianliang.Lu@getronics.com> */ + pdb_set_bad_password_count(to, 0, PDB_CHANGED); + pdb_set_bad_password_time(to, 0, PDB_CHANGED); + } + pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED); + } + } +} |