diff options
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 181e1140eb..9f0ce9b05d 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -57,6 +57,34 @@ static void free_samr_info(void *ptr) } /******************************************************************* + Ensure password info is never given out. Paranioa... JRA. + ********************************************************************/ + +static void samr_clear_passwd_fields( SAM_USER_INFO_21 *pass, int num_entries) +{ + int i; + + if (!pass) + return; + + for (i = 0; i < num_entries; i++) { + memset(&pass[i].lm_pwd, '\0', sizeof(pass[i].lm_pwd)); + memset(&pass[i].nt_pwd, '\0', sizeof(pass[i].nt_pwd)); + } +} + +static void samr_clear_sam_passwd( SAM_ACCOUNT *sam_pass) +{ + if (!sam_pass) + return; + + if (sam_pass->lm_pw) + memset(sam_pass->lm_pw, '\0', 16); + if (sam_pass->nt_pw) + memset(sam_pass->nt_pw, '\0', 16); +} + +/******************************************************************* This next function should be replaced with something that dynamically returns the correct user info..... JRA. ********************************************************************/ @@ -660,6 +688,8 @@ uint32 _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, SAMR_R_ if (!ret) return NT_STATUS_ACCESS_DENIED; + samr_clear_passwd_fields(pass, num_entries); + /* * Note from JRA. total_entries is not being used here. Currently if there is a * large user base then it looks like NT will enumerate until get_sampwd_entries @@ -979,6 +1009,9 @@ uint32 _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_ DEBUG(5, ("limiting number of entries to %d\n", num_entries)); } + /* Ensure password info is never given out here. PARANOIA... JRA */ + samr_clear_passwd_fields(pass, num_entries); + data_size = q_u->max_size; orig_num_entries = num_entries; @@ -1308,7 +1341,7 @@ uint32 _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP } /******************************************************************* - _api_samr_open_user + _api_samr_open_user. Safe - gives out no passwd info. ********************************************************************/ uint32 _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USER *r_u) @@ -1334,6 +1367,8 @@ uint32 _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_U if (sampass == NULL) return NT_STATUS_NO_SUCH_USER; + samr_clear_sam_passwd(sampass); + /* Get the domain SID stored in the domain policy */ if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid)) return NT_STATUS_INVALID_HANDLE; @@ -1357,7 +1392,7 @@ uint32 _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_U } /************************************************************************* - get_user_info_10 + get_user_info_10. Safe. Only gives out acb bits. *************************************************************************/ static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid) @@ -1386,30 +1421,40 @@ static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid) } /************************************************************************* - get_user_info_12 + get_user_info_12. OK - this is the killer as it gives out password info. + Ensure that this is only allowed on an encrypted connection with a root + user. JRA. *************************************************************************/ -static BOOL get_user_info_12(SAM_USER_INFO_12 * id12, uint32 user_rid) +static uint32 get_user_info_12(pipes_struct *p, SAM_USER_INFO_12 * id12, uint32 user_rid) { SAM_ACCOUNT *smbpass; - become_root(); + if (!p->ntlmssp_auth_validated) + return NT_STATUS_ACCESS_DENIED; + + if (!(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) || !(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL)) + return NT_STATUS_ACCESS_DENIED; + + /* + * Do *NOT* do become_root()/unbecome_root() here ! JRA. + */ + smbpass = pdb_getsampwrid(user_rid); - unbecome_root(); if (smbpass == NULL) { DEBUG(4, ("User 0x%x not found\n", user_rid)); - return False; + return (geteuid() == (uid_t)0) ? NT_STATUS_NO_SUCH_USER : NT_STATUS_ACCESS_DENIED; } DEBUG(3,("User:[%s] 0x%x\n", pdb_get_username(smbpass), pdb_get_acct_ctrl(smbpass) )); if ( pdb_get_acct_ctrl(smbpass) & ACB_DISABLED) - return False; + return NT_STATUS_ACCOUNT_DISABLED; init_sam_user_info12(id12, pdb_get_lanman_passwd(smbpass), pdb_get_nt_passwd(smbpass)); - return True; + return NT_STATUS_NOPROBLEMO; } /************************************************************************* @@ -1434,6 +1479,8 @@ static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid) return False; } + samr_clear_sam_passwd(sampass); + DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) )); init_sam_user_info21A(id21, sampass); @@ -1512,8 +1559,8 @@ uint32 _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_R_ if (ctr->info.id12 == NULL) return NT_STATUS_NO_MEMORY; - if (!get_user_info_12(ctr->info.id12, rid)) - return NT_STATUS_NO_SUCH_USER; + if ((r_u->status = get_user_info_12(p, ctr->info.id12, rid)) != NT_STATUS_NOPROBLEMO) + return r_u->status; break; case 21: @@ -1567,6 +1614,8 @@ uint32 _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAM if (sam_pass == NULL) return NT_STATUS_NO_SUCH_USER; + samr_clear_sam_passwd(sam_pass); + get_domain_user_groups(groups, pdb_get_username(sam_pass)); gids = NULL; num_groups = make_dom_gids(p->mem_ctx, groups, &gids); @@ -2392,8 +2441,8 @@ uint32 _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_SE uint32 _samr_get_dom_pwinfo(pipes_struct *p, SAMR_Q_GET_DOM_PWINFO *q_u, SAMR_R_GET_DOM_PWINFO *r_u) { - DEBUG(0,("_samr_get_dom_pwinfo: Not yet implemented.\n")); - return False; + /* Actually, returning zeros here works quite well :-). */ + return NT_STATUS_NOPROBLEMO; } /********************************************************************* |