diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index dea1a8f..7f434bd 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -2207,6 +2207,7 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, SEC_DESC *psd = NULL; uint32 acc_granted; uint32 des_access = r->in.access_mask; + uint32_t extra_access = 0; size_t sd_size; bool ret; NTSTATUS nt_status; @@ -2236,8 +2237,67 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); se_map_generic(&des_access, &usr_generic_mapping); - se_priv_copy( &se_rights, &se_machine_account ); - se_priv_add( &se_rights, &se_add_users ); + /* + * Get the sampass first as we need to check privilages + * based on what kind of user object this is. + * But don't reveal info too early if it didn't exist. + */ + + become_root(); + ret=pdb_getsampwsid(sampass, &sid); + unbecome_root(); + + ZERO_STRUCT(se_rights); + + /* + * We do the override access checks on *open*, not at + * SetUserInfo time. + */ + if (ret) { + SE_PRIV tmp_rights; + uint32_t acb_info = pdb_get_acct_ctrl(sampass); + + se_priv_copy(&tmp_rights, &se_machine_account); + if ((acb_info & ACB_WSTRUST) && + user_has_any_privilege(p->server_info->ptok, + &tmp_rights)) { + /* + * SeMachineAccount is needed to add + * GENERIC_RIGHTS_USER_WRITE to a machine + * account. + */ + se_priv_add(&se_rights, &se_machine_account); + } + se_priv_copy(&tmp_rights, &se_add_users); + if ((acb_info & ACB_NORMAL) && + user_has_any_privilege(p->server_info->ptok, + &tmp_rights)) { + /* + * SeAddUsers is needed to add + * GENERIC_RIGHTS_USER_WRITE to a normal + * account. + */ + se_priv_add(&se_rights, &se_add_users ); + } + /* + * Cheat - allow GENERIC_RIGHTS_USER_WRITE if pipe user is + * in DOMAIN_GROUP_RID_ADMINS. This is almost certainly not + * what Windows does but is a hack for people who haven't + * set up privilages on groups in Samba. + */ + if (acb_info & (ACB_SVRTRUST|ACB_DOMTRUST)) { + if (lp_enable_privileges() && nt_token_check_domain_rid(p->server_info->ptok, + DOMAIN_GROUP_RID_ADMINS)) { + des_access &= ~GENERIC_RIGHTS_USER_WRITE; + extra_access = GENERIC_RIGHTS_USER_WRITE; + DEBUG(4,("_samr_OpenUser: Allowing " + "GENERIC_RIGHTS_USER_WRITE for " + "rid admins\n")); + } + } + } + + TALLOC_FREE(sampass); nt_status = access_check_samr_object(psd, p->server_info->ptok, &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access, @@ -2246,16 +2306,13 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - become_root(); - ret=pdb_getsampwsid(sampass, &sid); - unbecome_root(); - /* check that the SID exists in our domain. */ if (ret == False) { return NT_STATUS_NO_SUCH_USER; } - TALLOC_FREE(sampass); + /* If we did the rid admins hack above, allow access. */ + acc_granted |= extra_access; uinfo = policy_handle_create(p, r->out.user_handle, acc_granted, struct samr_user_info, &nt_status); @@ -4660,8 +4717,6 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, uint16_t switch_value = r->in.level; uint32_t acc_required; bool ret; - bool has_enough_rights = False; - uint32_t acb_info; DEBUG(5,("_samr_SetUserInfo: %d\n", __LINE__)); @@ -4716,32 +4771,9 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, return NT_STATUS_NO_SUCH_USER; } - /* deal with machine password changes differently from userinfo changes */ - /* check to see if we have the sufficient rights */ - - acb_info = pdb_get_acct_ctrl(pwd); - if (acb_info & ACB_WSTRUST) - has_enough_rights = user_has_privileges(p->server_info->ptok, - &se_machine_account); - else if (acb_info & ACB_NORMAL) - has_enough_rights = user_has_privileges(p->server_info->ptok, - &se_add_users); - else if (acb_info & (ACB_SVRTRUST|ACB_DOMTRUST)) { - if (lp_enable_privileges()) { - has_enough_rights = nt_token_check_domain_rid(p->server_info->ptok, - DOMAIN_GROUP_RID_ADMINS); - } - } + /* ================ BEGIN Privilege BLOCK ================ */ - DEBUG(5, ("_samr_SetUserInfo: %s does%s possess sufficient rights\n", - uidtoname(p->server_info->utok.uid), - has_enough_rights ? "" : " not")); - - /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ - - if (has_enough_rights) { - become_root(); - } + become_root(); /* ok! user info levels (lots: see MSDEV help), off we go... */ @@ -4888,11 +4920,9 @@ NTSTATUS _samr_SetUserInfo(pipes_struct *p, TALLOC_FREE(pwd); - if (has_enough_rights) { - unbecome_root(); - } + unbecome_root(); - /* ================ END SeMachineAccountPrivilege BLOCK ================ */ + /* ================ END Privilege BLOCK ================ */ if (NT_STATUS_IS_OK(status)) { force_flush_samr_cache(&uinfo->sid);