diff options
-rw-r--r-- | source3/include/rpc_samr.h | 8 | ||||
-rw-r--r-- | source3/libsmb/smbencrypt.c | 19 | ||||
-rw-r--r-- | source3/rpc_parse/parse_samr.c | 38 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 50 |
4 files changed, 101 insertions, 14 deletions
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index e53bc1ede8..e0b179224d 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -277,6 +277,13 @@ typedef struct sam_user_info_25 UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */ } SAM_USER_INFO_25; +/* SAM_USER_INFO_26 */ +typedef struct sam_user_info_26 +{ + uint8 pass[532]; + uint8 pw_len; +} SAM_USER_INFO_26; + /* SAM_USER_INFO_21 */ typedef struct sam_user_info_21 @@ -1272,6 +1279,7 @@ typedef struct sam_userinfo_ctr_info SAM_USER_INFO_23 *id23; SAM_USER_INFO_24 *id24; SAM_USER_INFO_25 *id25; + SAM_USER_INFO_26 *id26; void* id; /* to make typecasting easy */ } info; diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 99f99f23f8..5bdd0acd3e 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -531,6 +531,25 @@ BOOL decode_pw_buffer(uint8 in_buffer[516], char *new_pwrd, } /*********************************************************** + Decode an arc4 encrypted password change buffer. +************************************************************/ + +void encode_or_decode_arc4_passwd_buffer(char pw_buf[532], const DATA_BLOB *psession_key) +{ + struct MD5Context tctx; + unsigned char key_out[16]; + + /* Confounder is last 16 bytes. */ + + MD5Init(&tctx); + MD5Update(&tctx, &pw_buf[516], 16); + MD5Update(&tctx, psession_key->data, psession_key->length); + MD5Final(key_out, &tctx); + /* arc4 with key_out. */ + SamOEMhash(pw_buf, key_out, 516); +} + +/*********************************************************** Encrypt/Decrypt used for LSA secrets and trusted domain passwords. ************************************************************/ diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index d13d3c9d4a..a0108d9eb7 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -5404,13 +5404,41 @@ static BOOL sam_io_user_info24(const char *desc, SAM_USER_INFO_24 * usr, if (MARSHALLING(ps) && (usr->pw_len != 0)) { if (!prs_uint16("pw_len", ps, depth, &usr->pw_len)) return False; + } else if (UNMARSHALLING(ps)) { + if (!prs_uint16("pw_len", ps, depth, &usr->pw_len)) + return False; } + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ + +static BOOL sam_io_user_info26(const char *desc, SAM_USER_INFO_26 * usr, + prs_struct *ps, int depth) +{ + if (usr == NULL) + return False; + + prs_debug(ps, depth, desc, "sam_io_user_info26"); + depth++; + if(!prs_align(ps)) return False; + if(!prs_uint8s(False, "password", ps, depth, usr->pass, + sizeof(usr->pass))) + return False; + + if (!prs_uint8("pw_len", ps, depth, &usr->pw_len)) + return False; + return True; } + /************************************************************************* init_sam_user_info23 @@ -6475,6 +6503,16 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr, } ret = sam_io_user_info25("", ctr->info.id25, ps, depth); break; + case 26: + if (UNMARSHALLING(ps)) + ctr->info.id26 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_26,1); + + if (ctr->info.id26 == NULL) { + DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n")); + return False; + } + ret = sam_io_user_info26("", ctr->info.id26, ps, depth); + break; default: DEBUG(2, ("samr_io_userinfo_ctr: unknown switch level 0x%x\n", ctr->switch_value)); ret = False; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 81344cdc1e..52f922b924 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -3316,27 +3316,27 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE break; case 25: -#if 0 - /* - * Currently we don't really know how to unmarshall - * the level 25 struct, and the password encryption - * is different. This is a placeholder for when we - * do understand it. In the meantime just return INVALID - * info level and W2K SP2 drops down to level 23... JRA. - */ - if (!p->session_key.length) { r_u->status = NT_STATUS_NO_USER_SESSION_KEY; } - SamOEMhashBlob(ctr->info.id25->pass, 532, &p->session_key); + encode_or_decode_arc4_passwd_buffer(ctr->info.id25->pass, &p->session_key); dump_data(100, (char *)ctr->info.id25->pass, 532); - if (!set_user_info_pw(ctr->info.id25->pass, &sid)) + if (!set_user_info_pw(ctr->info.id25->pass, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; -#endif - r_u->status = NT_STATUS_INVALID_INFO_CLASS; + + case 26: + if (!p->session_key.length) { + r_u->status = NT_STATUS_NO_USER_SESSION_KEY; + } + encode_or_decode_arc4_passwd_buffer(ctr->info.id26->pass, &p->session_key); + + dump_data(100, (char *)ctr->info.id26->pass, 516); + + if (!set_user_info_pw(ctr->info.id26->pass, pwd)) + r_u->status = NT_STATUS_ACCESS_DENIED; break; case 23: @@ -3432,7 +3432,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ); } - DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", + DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n", p->pipe_user_name, has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ @@ -3464,6 +3464,28 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ if (!set_user_info_21(ctr->info.id21, pwd)) return NT_STATUS_ACCESS_DENIED; break; + case 23: + if (!p->session_key.length) { + r_u->status = NT_STATUS_NO_USER_SESSION_KEY; + } + SamOEMhashBlob(ctr->info.id23->pass, 516, &p->session_key); + + dump_data(100, (char *)ctr->info.id23->pass, 516); + + if (!set_user_info_23(ctr->info.id23, pwd)) + r_u->status = NT_STATUS_ACCESS_DENIED; + break; + case 26: + if (!p->session_key.length) { + r_u->status = NT_STATUS_NO_USER_SESSION_KEY; + } + encode_or_decode_arc4_passwd_buffer(ctr->info.id26->pass, &p->session_key); + + dump_data(100, (char *)ctr->info.id26->pass, 516); + + if (!set_user_info_pw(ctr->info.id26->pass, pwd)) + r_u->status = NT_STATUS_ACCESS_DENIED; + break; default: r_u->status = NT_STATUS_INVALID_INFO_CLASS; } |