From: Samuel Cabrero Date: Tue, 29 Oct 2019 11:39:10 +0000 (+0100) Subject: s3: rpc_server: Strip out access check field from s3 handles implementation X-Git-Tag: ldb-2.2.0~346 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=711ca4fab59b97cb26006ce845a211bbe5c479f6;p=thirdparty%2Fsamba.git s3: rpc_server: Strip out access check field from s3 handles implementation The handle based security model is a SAMR specific feature. The access granted is stored in the handle's associated data after creating it and the access is verified after searching the handle. Signed-off-by: Samuel Cabrero Reviewed-by: Andrew Bartlett --- diff --git a/source3/rpc_server/rpc_handles.c b/source3/rpc_server/rpc_handles.c index 8ae9d970ced..6f1245cd10e 100644 --- a/source3/rpc_server/rpc_handles.c +++ b/source3/rpc_server/rpc_handles.c @@ -130,7 +130,6 @@ int close_internal_rpc_pipe_hnd(struct pipes_struct *p) struct dcesrv_handle_old { struct dcesrv_handle_old *prev, *next; struct policy_handle wire_handle; - uint32_t access_granted; void *data; }; @@ -456,7 +455,6 @@ bool pipe_access_check(struct pipes_struct *p) void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, uint8_t handle_type, - uint32_t access_granted, size_t data_size, const char *type, NTSTATUS *pstatus) @@ -487,15 +485,12 @@ void *_policy_handle_create(struct pipes_struct *p, *pstatus = NT_STATUS_NO_MEMORY; return NULL; } - rpc_hnd->access_granted = access_granted; *pstatus = NT_STATUS_OK; return data; } void *_policy_handle_find(struct pipes_struct *p, const struct policy_handle *hnd, - uint32_t access_required, - uint32_t *paccess_granted, const char *name, const char *location, NTSTATUS *pstatus) { @@ -513,26 +508,8 @@ void *_policy_handle_find(struct pipes_struct *p, *pstatus = NT_STATUS_INVALID_HANDLE; return NULL; } - if ((access_required & rpc_hnd->access_granted) != access_required) { - if (root_mode()) { - DEBUG(4, ("%s: ACCESS should be DENIED (granted: " - "%#010x; required: %#010x)\n", location, - rpc_hnd->access_granted, access_required)); - DEBUGADD(4,("but overwritten by euid == 0\n")); - goto okay; - } - DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: " - "%#010x)\n", location, rpc_hnd->access_granted, - access_required)); - *pstatus = NT_STATUS_ACCESS_DENIED; - return NULL; - } - okay: DEBUG(10, ("found handle of type %s\n", talloc_get_name(data))); - if (paccess_granted != NULL) { - *paccess_granted = rpc_hnd->access_granted; - } *pstatus = NT_STATUS_OK; return data; } diff --git a/source3/rpc_server/rpc_pipes.h b/source3/rpc_server/rpc_pipes.h index 5c4ded2c6c4..0bdd15ac5e2 100644 --- a/source3/rpc_server/rpc_pipes.h +++ b/source3/rpc_server/rpc_pipes.h @@ -134,21 +134,19 @@ bool pipe_access_check(struct pipes_struct *p); void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, uint8_t handle_type, - uint32_t access_granted, size_t data_size, const char *type, NTSTATUS *pstatus); -#define policy_handle_create(_p, _hnd, _hnd_type, _access, _type, _pstatus) \ - (_type *)_policy_handle_create((_p), (_hnd), (_hnd_type), (_access), sizeof(_type), #_type, \ +#define policy_handle_create(_p, _hnd, _hnd_type, _type, _pstatus) \ + (_type *)_policy_handle_create((_p), (_hnd), (_hnd_type), sizeof(_type), #_type, \ (_pstatus)) void *_policy_handle_find(struct pipes_struct *p, const struct policy_handle *hnd, - uint32_t access_required, uint32_t *paccess_granted, const char *name, const char *location, NTSTATUS *pstatus); -#define policy_handle_find(_p, _hnd, _access_required, _access_granted, _type, _pstatus) \ - (_type *)_policy_handle_find((_p), (_hnd), (_access_required), \ - (_access_granted), #_type, __location__, (_pstatus)) +#define policy_handle_find(_p, _hnd, _type, _pstatus) \ + (_type *)_policy_handle_find((_p), (_hnd), \ + #_type, __location__, (_pstatus)) #endif /* _RPC_PIPES_H_ */ diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c index 62796dbe540..a3f6ad1a408 100644 --- a/source3/rpc_server/samr/srv_samr_nt.c +++ b/source3/rpc_server/samr/srv_samr_nt.c @@ -75,24 +75,28 @@ enum samr_handle { }; struct samr_connect_info { - uint8_t dummy; + uint32_t access_granted; }; struct samr_domain_info { struct dom_sid sid; struct disp_info *disp_info; + uint32_t access_granted; }; struct samr_user_info { struct dom_sid sid; + uint32_t access_granted; }; struct samr_group_info { struct dom_sid sid; + uint32_t access_granted; }; struct samr_alias_info { struct dom_sid sid; + uint32_t access_granted; }; typedef struct disp_info { @@ -142,6 +146,29 @@ static const struct generic_mapping ali_generic_mapping = { /******************************************************************* *******************************************************************/ +static NTSTATUS samr_handle_access_check(uint32_t access_granted, + uint32_t access_required, + uint32_t *paccess_granted) +{ + if ((access_required & access_granted) != access_required) { + if (root_mode()) { + DBG_INFO("ACCESS should be DENIED (granted: " + "%#010x; required: %#010x) but overwritten " + "by euid == 0\n", access_granted, + access_required); + goto okay; + } + DBG_NOTICE("ACCESS DENIED (granted: %#010x; required: " + "%#010x)\n", access_granted, access_required); + return NT_STATUS_ACCESS_DENIED; + } + +okay: + if (paccess_granted != NULL) { + *paccess_granted = access_granted; + } + return NT_STATUS_OK; +} static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, struct security_descriptor **psd, size_t *sd_size, const struct generic_mapping *map, @@ -454,6 +481,7 @@ NTSTATUS _samr_OpenDomain(struct pipes_struct *p, struct samr_OpenDomain *r) { struct samr_domain_info *dinfo; + struct samr_connect_info *cinfo = NULL; struct security_descriptor *psd = NULL; uint32_t acc_granted; uint32_t des_access = r->in.access_mask; @@ -463,12 +491,17 @@ NTSTATUS _samr_OpenDomain(struct pipes_struct *p, /* find the connection policy handle. */ - (void)policy_handle_find(p, r->in.connect_handle, 0, NULL, + cinfo = policy_handle_find(p, r->in.connect_handle, struct samr_connect_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(cinfo->access_granted, 0, NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /*check if access can be granted as requested by client. */ map_max_allowed_access(p->session_info->security_token, p->session_info->unix_token, @@ -510,7 +543,6 @@ NTSTATUS _samr_OpenDomain(struct pipes_struct *p, dinfo = policy_handle_create(p, r->out.domain_handle, SAMR_HANDLE_DOMAIN, - acc_granted, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { @@ -518,6 +550,7 @@ NTSTATUS _samr_OpenDomain(struct pipes_struct *p, } dinfo->sid = *r->in.sid; dinfo->disp_info = get_samr_dispinfo_by_sid(r->in.sid); + dinfo->access_granted = acc_granted; DEBUG(5,("_samr_OpenDomain: %d\n", __LINE__)); @@ -543,12 +576,18 @@ NTSTATUS _samr_GetUserPwInfo(struct pipes_struct *p, DEBUG(5,("_samr_GetUserPwInfo: %d\n", __LINE__)); uinfo = policy_handle_find(p, r->in.user_handle, - SAMR_USER_ACCESS_GET_ATTRIBUTES, NULL, struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(uinfo->access_granted, + SAMR_USER_ACCESS_GET_ATTRIBUTES, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!sid_check_is_in_our_sam(&uinfo->sid)) { return NT_STATUS_OBJECT_TYPE_MISMATCH; } @@ -602,12 +641,18 @@ NTSTATUS _samr_SetSecurity(struct pipes_struct *p, NTSTATUS status; uinfo = policy_handle_find(p, r->in.handle, - SAMR_USER_ACCESS_SET_ATTRIBUTES, NULL, struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(uinfo->access_granted, + SAMR_USER_ACCESS_SET_ATTRIBUTES, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!(sampass = samu_new( p->mem_ctx))) { DEBUG(0,("No memory!\n")); return NT_STATUS_NO_MEMORY; @@ -702,11 +747,19 @@ NTSTATUS _samr_QuerySecurity(struct pipes_struct *p, struct security_descriptor * psd = NULL; size_t sd_size = 0; struct dom_sid_buf buf; + struct samr_connect_info *cinfo = NULL; + NTSTATUS acc_status; - (void)policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, + cinfo = policy_handle_find(p, r->in.handle, struct samr_connect_info, &status); - if (NT_STATUS_IS_OK(status)) { + if (cinfo != NULL) { + acc_status = samr_handle_access_check(cinfo->access_granted, + SEC_STD_READ_CONTROL, + NULL); + } else { + acc_status = NT_STATUS_INVALID_HANDLE; + } + if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(acc_status)) { DEBUG(5,("_samr_QuerySecurity: querying security on SAM\n")); status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); @@ -714,9 +767,15 @@ NTSTATUS _samr_QuerySecurity(struct pipes_struct *p, } dinfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, struct samr_domain_info, &status); - if (NT_STATUS_IS_OK(status)) { + if (dinfo != NULL) { + acc_status = samr_handle_access_check(dinfo->access_granted, + SEC_STD_READ_CONTROL, + NULL); + } else { + acc_status = NT_STATUS_INVALID_HANDLE; + } + if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(acc_status)) { DEBUG(5,("_samr_QuerySecurity: querying security on Domain " "with SID: %s\n", dom_sid_str_buf(&dinfo->sid, &buf))); @@ -730,9 +789,15 @@ NTSTATUS _samr_QuerySecurity(struct pipes_struct *p, } uinfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, struct samr_user_info, &status); - if (NT_STATUS_IS_OK(status)) { + if (uinfo != NULL) { + acc_status = samr_handle_access_check(uinfo->access_granted, + SEC_STD_READ_CONTROL, + NULL); + } else { + acc_status = NT_STATUS_INVALID_HANDLE; + } + if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(acc_status)) { DEBUG(10,("_samr_QuerySecurity: querying security on user " "Object with SID: %s\n", dom_sid_str_buf(&uinfo->sid, &buf))); @@ -751,9 +816,15 @@ NTSTATUS _samr_QuerySecurity(struct pipes_struct *p, } ginfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, struct samr_group_info, &status); - if (NT_STATUS_IS_OK(status)) { + if (ginfo != NULL) { + acc_status = samr_handle_access_check(ginfo->access_granted, + SEC_STD_READ_CONTROL, + NULL); + } else { + acc_status = NT_STATUS_INVALID_HANDLE; + } + if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(acc_status)) { /* * TODO: different SDs have to be generated for aliases groups * and users. Currently all three get a default user SD @@ -769,9 +840,16 @@ NTSTATUS _samr_QuerySecurity(struct pipes_struct *p, } ainfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, struct samr_alias_info, &status); - if (NT_STATUS_IS_OK(status)) { + if (ainfo != NULL) { + acc_status = samr_handle_access_check(ainfo->access_granted, + SEC_STD_READ_CONTROL, + NULL); + } else { + acc_status = NT_STATUS_INVALID_HANDLE; + } + + if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(acc_status)) { /* * TODO: different SDs have to be generated for aliases groups * and users. Currently all three get a default user SD @@ -865,12 +943,18 @@ NTSTATUS _samr_EnumDomainUsers(struct pipes_struct *p, DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__)); dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + samr_array = talloc_zero(p->mem_ctx, struct samr_SamArray); if (!samr_array) { return NT_STATUS_NO_MEMORY; @@ -998,12 +1082,18 @@ NTSTATUS _samr_EnumDomainGroups(struct pipes_struct *p, struct samr_SamEntry *samr_entries = NULL; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__)); samr_array = talloc_zero(p->mem_ctx, struct samr_SamArray); @@ -1076,12 +1166,18 @@ NTSTATUS _samr_EnumDomainAliases(struct pipes_struct *p, struct dom_sid_buf buf; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(5,("_samr_EnumDomainAliases: sid %s\n", dom_sid_str_buf(&dinfo->sid, &buf))); @@ -1353,12 +1449,18 @@ NTSTATUS _samr_QueryDisplayInfo(struct pipes_struct *p, DEBUG(5,("_samr_QueryDisplayInfo: %d\n", __LINE__)); dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (sid_check_is_builtin(&dinfo->sid)) { DEBUG(5,("_samr_QueryDisplayInfo: no users in BUILTIN\n")); return NT_STATUS_OK; @@ -1602,12 +1704,18 @@ NTSTATUS _samr_QueryAliasInfo(struct pipes_struct *p, DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__)); ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_LOOKUP_INFO, NULL, struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ainfo->access_granted, + SAMR_ALIAS_ACCESS_LOOKUP_INFO, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + alias_info = talloc_zero(p->mem_ctx, union samr_AliasInfo); if (!alias_info) { return NT_STATUS_NO_MEMORY; @@ -1674,12 +1782,18 @@ NTSTATUS _samr_LookupNames(struct pipes_struct *p, DEBUG(5,("_samr_LookupNames: %d\n", __LINE__)); dinfo = policy_handle_find(p, r->in.domain_handle, - 0 /* Don't know the acc_bits yet */, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + 0 /* Don't know the acc_bits yet */, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (num_rids > MAX_SAM_ENTRIES) { num_rids = MAX_SAM_ENTRIES; DEBUG(5,("_samr_LookupNames: truncating entries to %d\n", num_rids)); @@ -2056,12 +2170,18 @@ NTSTATUS _samr_LookupRids(struct pipes_struct *p, DEBUG(5,("_samr_LookupRids: %d\n", __LINE__)); dinfo = policy_handle_find(p, r->in.domain_handle, - 0 /* Don't know the acc_bits yet */, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + 0 /* Don't know the acc_bits yet */, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (num_rids > 1000) { DEBUG(0, ("Got asked for %d rids (more than 1000) -- according " "to samba4 idl this is not possible\n", num_rids)); @@ -2140,12 +2260,18 @@ NTSTATUS _samr_OpenUser(struct pipes_struct *p, NTSTATUS status; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if ( !(sampass = samu_new( p->mem_ctx )) ) { return NT_STATUS_NO_MEMORY; } @@ -2237,13 +2363,13 @@ NTSTATUS _samr_OpenUser(struct pipes_struct *p, uinfo = policy_handle_create(p, r->out.user_handle, SAMR_HANDLE_USER, - acc_granted, struct samr_user_info, &nt_status); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } uinfo->sid = sid; + uinfo->access_granted = acc_granted; return NT_STATUS_OK; } @@ -2952,12 +3078,18 @@ NTSTATUS _samr_QueryUserInfo(struct pipes_struct *p, } uinfo = policy_handle_find(p, r->in.user_handle, - acc_required, &acc_granted, struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(uinfo->access_granted, + acc_required, + &acc_granted); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + domain_sid = uinfo->sid; sid_split_rid(&domain_sid, &rid); @@ -3126,12 +3258,18 @@ NTSTATUS _samr_GetGroupsForUser(struct pipes_struct *p, DEBUG(5,("_samr_GetGroupsForUser: %d\n", __LINE__)); uinfo = policy_handle_find(p, r->in.user_handle, - SAMR_USER_ACCESS_GET_GROUPS, NULL, struct samr_user_info, &result); if (!NT_STATUS_IS_OK(result)) { return result; } + result = samr_handle_access_check(uinfo->access_granted, + SAMR_USER_ACCESS_GET_GROUPS, + NULL); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + rids = talloc_zero(p->mem_ctx, struct samr_RidWithAttributeArray); if (!rids) { return NT_STATUS_NO_MEMORY; @@ -3582,12 +3720,18 @@ NTSTATUS _samr_QueryDomainInfo(struct pipes_struct *p, } dinfo = policy_handle_find(p, r->in.domain_handle, - acc_required, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + acc_required, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + dom_info = talloc_zero(p->mem_ctx, union samr_DomainInfo); if (!dom_info) { return NT_STATUS_NO_MEMORY; @@ -3707,12 +3851,18 @@ NTSTATUS _samr_CreateUser2(struct pipes_struct *p, enum sec_privilege needed_priv = SEC_PRIV_INVALID; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_CREATE_USER, NULL, struct samr_domain_info, &nt_status); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } + nt_status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_CREATE_USER, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + if (sid_check_is_builtin(&dinfo->sid)) { DEBUG(5,("_samr_CreateUser2: Refusing user create in BUILTIN\n")); return NT_STATUS_ACCESS_DENIED; @@ -3810,13 +3960,13 @@ NTSTATUS _samr_CreateUser2(struct pipes_struct *p, uinfo = policy_handle_create(p, r->out.user_handle, SAMR_HANDLE_USER, - acc_granted, struct samr_user_info, &nt_status); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } uinfo->sid = sid; + uinfo->access_granted = acc_granted; /* After a "set" ensure we have no cached display info. */ force_flush_samr_cache(&sid); @@ -3857,6 +4007,7 @@ NTSTATUS _samr_Connect(struct pipes_struct *p, struct policy_handle hnd; uint32_t des_access = r->in.access_mask; NTSTATUS status; + struct samr_connect_info *cinfo = NULL; /* Access check */ @@ -3880,16 +4031,17 @@ NTSTATUS _samr_Connect(struct pipes_struct *p, /* set up the SAMR connect_anon response */ - (void)policy_handle_create(p, - &hnd, - SAMR_HANDLE_CONNECT, - acc_granted, - struct samr_connect_info, - &status); + cinfo = policy_handle_create(p, + &hnd, + SAMR_HANDLE_CONNECT, + struct samr_connect_info, + &status); if (!NT_STATUS_IS_OK(status)) { return status; } + cinfo->access_granted = acc_granted; + *r->out.connect_handle = hnd; return NT_STATUS_OK; } @@ -3908,6 +4060,7 @@ NTSTATUS _samr_Connect2(struct pipes_struct *p, NTSTATUS nt_status; size_t sd_size; const char *fn = "_samr_Connect2"; + struct samr_connect_info *cinfo = NULL; switch (p->opnum) { case NDR_SAMR_CONNECT2: @@ -3947,16 +4100,17 @@ NTSTATUS _samr_Connect2(struct pipes_struct *p, if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - (void)policy_handle_create(p, - &hnd, - SAMR_HANDLE_CONNECT, - acc_granted, - struct samr_connect_info, - &nt_status); + cinfo = policy_handle_create(p, + &hnd, + SAMR_HANDLE_CONNECT, + struct samr_connect_info, + &nt_status); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } + cinfo->access_granted = acc_granted; + DEBUG(5,("%s: %d\n", fn, __LINE__)); *r->out.connect_handle = hnd; @@ -4036,18 +4190,25 @@ NTSTATUS _samr_LookupDomain(struct pipes_struct *p, const char *domain_name; struct dom_sid *sid = NULL; struct dom_sid_buf buf; + struct samr_connect_info *cinfo = NULL; /* win9x user manager likes to use SAMR_ACCESS_ENUM_DOMAINS here. Reverted that change so we will work with RAS servers again */ - (void)policy_handle_find(p, r->in.connect_handle, - SAMR_ACCESS_LOOKUP_DOMAIN, NULL, + cinfo = policy_handle_find(p, r->in.connect_handle, struct samr_connect_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(cinfo->access_granted, + SAMR_ACCESS_LOOKUP_DOMAIN, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + domain_name = r->in.domain_name->string; if (!domain_name) { return NT_STATUS_INVALID_PARAMETER; @@ -4085,10 +4246,17 @@ NTSTATUS _samr_EnumDomains(struct pipes_struct *p, uint32_t num_entries = 2; struct samr_SamEntry *entry_array = NULL; struct samr_SamArray *sam; + struct samr_connect_info *cinfo = NULL; - (void)policy_handle_find(p, r->in.connect_handle, - SAMR_ACCESS_ENUM_DOMAINS, NULL, - struct samr_connect_info, &status); + cinfo = policy_handle_find(p, r->in.connect_handle, + struct samr_connect_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = samr_handle_access_check(cinfo->access_granted, + SAMR_ACCESS_ENUM_DOMAINS, + NULL); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -4138,12 +4306,18 @@ NTSTATUS _samr_OpenAlias(struct pipes_struct *p, NTSTATUS status; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* append the alias' RID to it */ if (!sid_compose(&sid, &dinfo->sid, alias_rid)) @@ -4191,13 +4365,13 @@ NTSTATUS _samr_OpenAlias(struct pipes_struct *p, ainfo = policy_handle_create(p, r->out.alias_handle, SAMR_HANDLE_ALIAS, - acc_granted, struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } ainfo->sid = sid; + ainfo->access_granted = acc_granted; return NT_STATUS_OK; } @@ -5118,12 +5292,19 @@ NTSTATUS _samr_SetUserInfo(struct pipes_struct *p, return NT_STATUS_INVALID_INFO_CLASS; } - uinfo = policy_handle_find(p, r->in.user_handle, acc_required, NULL, + uinfo = policy_handle_find(p, r->in.user_handle, struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(uinfo->access_granted, + acc_required, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(5, ("_samr_SetUserInfo: sid:%s, level:%d\n", dom_sid_str_buf(&uinfo->sid, &buf), r->in.level)); @@ -5384,13 +5565,19 @@ NTSTATUS _samr_GetAliasMembership(struct pipes_struct *p, DEBUG(5,("_samr_GetAliasMembership: %d\n", __LINE__)); dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS - | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS + | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!sid_check_is_our_sam(&dinfo->sid) && !sid_check_is_builtin(&dinfo->sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; @@ -5450,12 +5637,18 @@ NTSTATUS _samr_GetMembersInAlias(struct pipes_struct *p, struct dom_sid_buf buf; ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_GET_MEMBERS, NULL, struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ainfo->access_granted, + SAMR_ALIAS_ACCESS_GET_MEMBERS, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(10, ("sid is %s\n", dom_sid_str_buf(&ainfo->sid, &buf))); become_root(); @@ -5509,12 +5702,18 @@ NTSTATUS _samr_QueryGroupMember(struct pipes_struct *p, struct dom_sid_buf buf; ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_GET_MEMBERS, NULL, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ginfo->access_granted, + SAMR_GROUP_ACCESS_GET_MEMBERS, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + rids = talloc_zero(p->mem_ctx, struct samr_RidAttrArray); if (!rids) { return NT_STATUS_NO_MEMORY; @@ -5574,12 +5773,18 @@ NTSTATUS _samr_AddAliasMember(struct pipes_struct *p, NTSTATUS status; ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_ADD_MEMBER, NULL, struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ainfo->access_granted, + SAMR_ALIAS_ACCESS_ADD_MEMBER, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(10, ("sid is %s\n", dom_sid_str_buf(&ainfo->sid, &buf))); /******** BEGIN SeAddUsers BLOCK *********/ @@ -5609,12 +5814,18 @@ NTSTATUS _samr_DeleteAliasMember(struct pipes_struct *p, NTSTATUS status; ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_REMOVE_MEMBER, NULL, struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ainfo->access_granted, + SAMR_ALIAS_ACCESS_REMOVE_MEMBER, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", dom_sid_str_buf(&ainfo->sid, &buf))); @@ -5646,12 +5857,18 @@ NTSTATUS _samr_AddGroupMember(struct pipes_struct *p, uint32_t group_rid; ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_ADD_MEMBER, NULL, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ginfo->access_granted, + SAMR_GROUP_ACCESS_ADD_MEMBER, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(10, ("sid is %s\n", dom_sid_str_buf(&ginfo->sid, &buf))); if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, @@ -5691,12 +5908,18 @@ NTSTATUS _samr_DeleteGroupMember(struct pipes_struct *p, */ ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_REMOVE_MEMBER, NULL, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ginfo->access_granted, + SAMR_GROUP_ACCESS_REMOVE_MEMBER, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, &group_rid)) { return NT_STATUS_INVALID_HANDLE; @@ -5730,12 +5953,18 @@ NTSTATUS _samr_DeleteUser(struct pipes_struct *p, DEBUG(5, ("_samr_DeleteUser: %d\n", __LINE__)); uinfo = policy_handle_find(p, r->in.user_handle, - SEC_STD_DELETE, NULL, struct samr_user_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(uinfo->access_granted, + SEC_STD_DELETE, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!sid_check_is_in_our_sam(&uinfo->sid)) return NT_STATUS_CANNOT_DELETE; @@ -5800,12 +6029,18 @@ NTSTATUS _samr_DeleteDomainGroup(struct pipes_struct *p, DEBUG(5, ("samr_DeleteDomainGroup: %d\n", __LINE__)); ginfo = policy_handle_find(p, r->in.group_handle, - SEC_STD_DELETE, NULL, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ginfo->access_granted, + SEC_STD_DELETE, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(10, ("sid is %s\n", dom_sid_str_buf(&ginfo->sid, &buf))); if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, @@ -5851,12 +6086,18 @@ NTSTATUS _samr_DeleteDomAlias(struct pipes_struct *p, DEBUG(5, ("_samr_DeleteDomAlias: %d\n", __LINE__)); ainfo = policy_handle_find(p, r->in.alias_handle, - SEC_STD_DELETE, NULL, struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ainfo->access_granted, + SEC_STD_DELETE, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(10, ("sid is %s\n", dom_sid_str_buf(&ainfo->sid, &buf))); /* Don't let Windows delete builtin groups */ @@ -5904,12 +6145,18 @@ NTSTATUS _samr_CreateDomainGroup(struct pipes_struct *p, struct samr_group_info *ginfo; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_CREATE_GROUP, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_CREATE_GROUP, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!sid_check_is_our_sam(&dinfo->sid)) { return NT_STATUS_ACCESS_DENIED; } @@ -5941,13 +6188,13 @@ NTSTATUS _samr_CreateDomainGroup(struct pipes_struct *p, ginfo = policy_handle_create(p, r->out.group_handle, SAMR_HANDLE_GROUP, - GENERIC_RIGHTS_GROUP_ALL_ACCESS, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } sid_compose(&ginfo->sid, &dinfo->sid, *r->out.rid); + ginfo->access_granted = GENERIC_RIGHTS_GROUP_ALL_ACCESS; force_flush_samr_cache(&dinfo->sid); @@ -5969,12 +6216,18 @@ NTSTATUS _samr_CreateDomAlias(struct pipes_struct *p, NTSTATUS result; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_CREATE_ALIAS, NULL, struct samr_domain_info, &result); if (!NT_STATUS_IS_OK(result)) { return result; } + result = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_CREATE_ALIAS, + NULL); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + if (!sid_check_is_our_sam(&dinfo->sid)) { return NT_STATUS_ACCESS_DENIED; } @@ -6018,13 +6271,13 @@ NTSTATUS _samr_CreateDomAlias(struct pipes_struct *p, ainfo = policy_handle_create(p, r->out.alias_handle, SAMR_HANDLE_ALIAS, - GENERIC_RIGHTS_ALIAS_ALL_ACCESS, struct samr_alias_info, &result); if (!NT_STATUS_IS_OK(result)) { return result; } ainfo->sid = info_sid; + ainfo->access_granted = GENERIC_RIGHTS_ALIAS_ALL_ACCESS; force_flush_samr_cache(&info_sid); @@ -6050,12 +6303,18 @@ NTSTATUS _samr_QueryGroupInfo(struct pipes_struct *p, const char *group_description = NULL; ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_LOOKUP_INFO, NULL, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ginfo->access_granted, + SAMR_GROUP_ACCESS_LOOKUP_INFO, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + map = talloc_zero(p->mem_ctx, GROUP_MAP); if (!map) { return NT_STATUS_NO_MEMORY; @@ -6153,12 +6412,18 @@ NTSTATUS _samr_SetGroupInfo(struct pipes_struct *p, bool ret; ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_SET_INFO, NULL, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ginfo->access_granted, + SAMR_GROUP_ACCESS_SET_INFO, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + map = talloc_zero(p->mem_ctx, GROUP_MAP); if (!map) { return NT_STATUS_NO_MEMORY; @@ -6220,12 +6485,18 @@ NTSTATUS _samr_SetAliasInfo(struct pipes_struct *p, NTSTATUS status; ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_SET_INFO, NULL, struct samr_alias_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(ainfo->access_granted, + SAMR_ALIAS_ACCESS_SET_INFO, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + info = talloc_zero(p->mem_ctx, struct acct_info); if (!info) { return NT_STATUS_NO_MEMORY; @@ -6378,12 +6649,18 @@ NTSTATUS _samr_OpenGroup(struct pipes_struct *p, bool ret; dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /*check if access can be granted as requested by client. */ map_max_allowed_access(p->session_info->security_token, p->session_info->unix_token, @@ -6427,13 +6704,13 @@ NTSTATUS _samr_OpenGroup(struct pipes_struct *p, ginfo = policy_handle_create(p, r->out.group_handle, SAMR_HANDLE_GROUP, - acc_granted, struct samr_group_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } ginfo->sid = info_sid; + ginfo->access_granted = acc_granted; return NT_STATUS_OK; } @@ -6455,12 +6732,18 @@ NTSTATUS _samr_RemoveMemberFromForeignDomain(struct pipes_struct *p, /* Find the policy handle. Open a policy on it. */ dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, struct samr_domain_info, &result); if (!NT_STATUS_IS_OK(result)) { return result; } + result = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, + NULL); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + DEBUG(8, ("_samr_RemoveMemberFromForeignDomain: sid is %s\n", dom_sid_str_buf(&dinfo->sid, &buf))); @@ -6599,6 +6882,7 @@ NTSTATUS _samr_SetDomainInfo(struct pipes_struct *p, { NTSTATUS status; uint32_t acc_required = 0; + struct samr_domain_info *dinfo = NULL; DEBUG(5,("_samr_SetDomainInfo: %d\n", __LINE__)); @@ -6623,13 +6907,19 @@ NTSTATUS _samr_SetDomainInfo(struct pipes_struct *p, return NT_STATUS_INVALID_INFO_CLASS; } - (void)policy_handle_find(p, r->in.domain_handle, - acc_required, NULL, + dinfo = policy_handle_find(p, r->in.domain_handle, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + acc_required, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + DEBUG(5,("_samr_SetDomainInfo: level: %d\n", r->in.level)); switch (r->in.level) { @@ -6681,12 +6971,18 @@ NTSTATUS _samr_GetDisplayEnumerationIndex(struct pipes_struct *p, DEBUG(5,("_samr_GetDisplayEnumerationIndex: %d\n", __LINE__)); dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if ((r->in.level < 1) || (r->in.level > 3)) { DEBUG(0,("_samr_GetDisplayEnumerationIndex: " "Unknown info level (%u)\n", @@ -6819,12 +7115,18 @@ NTSTATUS _samr_RidToSid(struct pipes_struct *p, struct dom_sid sid; dinfo = policy_handle_find(p, r->in.domain_handle, - 0, NULL, struct samr_domain_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } + status = samr_handle_access_check(dinfo->access_granted, + 0, + NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!sid_compose(&sid, &dinfo->sid, r->in.rid)) { return NT_STATUS_NO_MEMORY; }