diff options
-rw-r--r-- | source3/include/proto.h | 19 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_hnd.c | 73 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 63 |
3 files changed, 97 insertions, 58 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index b99588f717..fa60e6de09 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -5885,16 +5885,21 @@ bool close_policy_hnd(pipes_struct *p, struct policy_handle *hnd); void close_policy_by_pipe(pipes_struct *p); bool pipe_access_check(pipes_struct *p); -NTSTATUS _policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, - void *pdata, size_t size, const char *name); -#define policy_handle_create(_p, _hnd, _ptr, _type) \ - _policy_handle_create((_p), (_hnd), (_ptr), sizeof(_type), #_type) +void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, + uint32_t access_granted, size_t data_size, + const char *type, NTSTATUS *pstatus); +#define policy_handle_create(_p, _hnd, _access, _type, _pstatus) \ + (_type *)_policy_handle_create((_p), (_hnd), (_access), sizeof(_type), #_type, \ + (_pstatus)) void *_policy_handle_find(struct pipes_struct *p, const struct policy_handle *hnd, - const char *type); -#define policy_handle_find(_p, _hnd, _type) \ - (_type *)_policy_handle_find((_p), (_hnd), #_type) + 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)) /* The following definitions come from rpc_server/srv_pipe.c */ diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c index 9891ff3964..2490ca30db 100644 --- a/source3/rpc_server/srv_lsa_hnd.c +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -33,6 +33,8 @@ struct policy { struct policy_handle pol_hnd; + uint32_t access_granted; + void *data_ptr; }; @@ -138,7 +140,9 @@ bool init_pipe_handle_list(pipes_struct *p, const struct ndr_syntax_id *syntax) data_ptr is TALLOC_FREE()'ed ****************************************************************************/ -bool create_policy_hnd(pipes_struct *p, struct policy_handle *hnd, void *data_ptr) +static struct policy *create_policy_hnd_internal(pipes_struct *p, + struct policy_handle *hnd, + void *data_ptr) { static uint32 pol_hnd_low = 0; static uint32 pol_hnd_high = 0; @@ -149,13 +153,13 @@ bool create_policy_hnd(pipes_struct *p, struct policy_handle *hnd, void *data_pt if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n", (int)p->pipe_handles->count)); - return False; + return NULL; } pol = TALLOC_ZERO_P(NULL, struct policy); if (!pol) { DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n")); - return False; + return NULL; } if (data_ptr != NULL) { @@ -186,7 +190,13 @@ bool create_policy_hnd(pipes_struct *p, struct policy_handle *hnd, void *data_pt DEBUG(4,("Opened policy hnd[%d] ", (int)p->pipe_handles->count)); dump_data(4, (uint8 *)hnd, sizeof(*hnd)); - return True; + return pol; +} + +bool create_policy_hnd(pipes_struct *p, struct policy_handle *hnd, + void *data_ptr) +{ + return create_policy_hnd_internal(p, hnd, data_ptr) != NULL; } /**************************************************************************** @@ -307,47 +317,80 @@ bool pipe_access_check(pipes_struct *p) return True; } -NTSTATUS _policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, - void *pdata, size_t data_size, const char *type) +void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, + uint32_t access_granted, size_t data_size, + const char *type, NTSTATUS *pstatus) { - void **ppdata = (void **)pdata; + struct policy *pol; void *data; if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0, ("policy_handle_create: ERROR: too many handles (%d) " "on pipe %s.\n", (int)p->pipe_handles->count, get_pipe_name_from_iface(&p->syntax))); - return NT_STATUS_INSUFFICIENT_RESOURCES; + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; + return NULL; } data = talloc_size(talloc_tos(), data_size); if (data == NULL) { - return NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; + return NULL; } talloc_set_name(data, type); - if (!create_policy_hnd(p, hnd, data)) { + pol = create_policy_hnd_internal(p, hnd, data); + if (pol == NULL) { TALLOC_FREE(data); - return NT_STATUS_NO_MEMORY; + *pstatus = NT_STATUS_NO_MEMORY; + return NULL; } - *ppdata = data; - return NT_STATUS_OK; + pol->access_granted = access_granted; + *pstatus = NT_STATUS_OK; + return data; } void *_policy_handle_find(struct pipes_struct *p, const struct policy_handle *hnd, - const char *name) + uint32_t access_required, + uint32_t *paccess_granted, + const char *name, const char *location, + NTSTATUS *pstatus) { + struct policy *pol; void *data; - if (find_policy_by_hnd_internal(p, hnd, &data) == NULL) { + pol = find_policy_by_hnd_internal(p, hnd, &data); + if (pol == NULL) { + *pstatus = NT_STATUS_INVALID_HANDLE; return NULL; } if (strcmp(name, talloc_get_name(data)) != 0) { DEBUG(10, ("expected %s, got %s\n", name, talloc_get_name(data))); + *pstatus = NT_STATUS_INVALID_HANDLE; return NULL; } + if ((access_required & pol->access_granted) != access_required) { + if (geteuid() == sec_initial_uid()) { + DEBUG(4, ("%s: ACCESS should be DENIED (granted: " + "%#010x; required: %#010x)\n", location, + pol->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, pol->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 = pol->access_granted; + } + *pstatus = NT_STATUS_OK; return data; } diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 159760c4c8..b18011c1f9 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -49,7 +49,7 @@ #define MAX_SAM_ENTRIES_W95 50 struct samr_connect_info { - uint32_t acc_granted; + uint8_t dummy; }; typedef struct disp_info { @@ -613,10 +613,10 @@ NTSTATUS _samr_OpenDomain(pipes_struct *p, /* find the connection policy handle. */ - cinfo = policy_handle_find(p, r->in.connect_handle, - struct samr_connect_info); - if (cinfo == NULL) { - return NT_STATUS_INVALID_HANDLE; + cinfo = policy_handle_find(p, r->in.connect_handle, 0, NULL, + struct samr_connect_info, &status); + if (!NT_STATUS_IS_OK(status)) { + return status; } /*check if access can be granted as requested by client. */ @@ -3198,6 +3198,7 @@ NTSTATUS _samr_Connect(pipes_struct *p, struct samr_Connect *r) { struct samr_connect_info *info; + uint32_t acc_granted; struct policy_handle hnd; uint32 des_access = r->in.access_mask; NTSTATUS status; @@ -3209,14 +3210,6 @@ NTSTATUS _samr_Connect(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } - /* set up the SAMR connect_anon response */ - - status = policy_handle_create(p, &hnd, &info, - struct samr_connect_info); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* don't give away the farm but this is probably ok. The SAMR_ACCESS_ENUM_DOMAINS was observed from a win98 client trying to enumerate users (when configured user level access control on shares) --jerry */ @@ -3224,7 +3217,18 @@ NTSTATUS _samr_Connect(pipes_struct *p, map_max_allowed_access(p->server_info->ptok, &des_access); se_map_generic( &des_access, &sam_generic_mapping ); - info->acc_granted = des_access & (SAMR_ACCESS_ENUM_DOMAINS|SAMR_ACCESS_LOOKUP_DOMAIN); + + acc_granted = des_access & (SAMR_ACCESS_ENUM_DOMAINS + |SAMR_ACCESS_LOOKUP_DOMAIN); + + /* set up the SAMR connect_anon response */ + + info = policy_handle_create(p, &hnd, acc_granted, + struct samr_connect_info, + &status); + if (!NT_STATUS_IS_OK(status)) { + return status; + } *r->out.connect_handle = hnd; return NT_STATUS_OK; @@ -3281,14 +3285,12 @@ NTSTATUS _samr_Connect2(pipes_struct *p, if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - nt_status = policy_handle_create(p, &hnd, &info, - struct samr_connect_info); + info = policy_handle_create(p, &hnd, acc_granted, + struct samr_connect_info, &nt_status); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } - info->acc_granted = acc_granted; - DEBUG(5,("%s: %d\n", fn, __LINE__)); *r->out.connect_handle = hnd; @@ -3363,23 +3365,18 @@ NTSTATUS _samr_Connect5(pipes_struct *p, NTSTATUS _samr_LookupDomain(pipes_struct *p, struct samr_LookupDomain *r) { - NTSTATUS status = NT_STATUS_OK; + NTSTATUS status; struct samr_connect_info *info; const char *domain_name; DOM_SID *sid = NULL; - info = policy_handle_find(p, r->in.connect_handle, - struct samr_connect_info); - if (info == NULL) { - return NT_STATUS_INVALID_HANDLE; - } - /* win9x user manager likes to use SAMR_ACCESS_ENUM_DOMAINS here. Reverted that change so we will work with RAS servers again */ - status = access_check_samr_function(info->acc_granted, - SAMR_ACCESS_LOOKUP_DOMAIN, - "_samr_LookupDomain"); + info = policy_handle_find(p, r->in.connect_handle, + SAMR_ACCESS_LOOKUP_DOMAIN, NULL, + struct samr_connect_info, + &status); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3424,14 +3421,8 @@ NTSTATUS _samr_EnumDomains(pipes_struct *p, struct samr_SamArray *sam; info = policy_handle_find(p, r->in.connect_handle, - struct samr_connect_info); - if (info == NULL) { - return NT_STATUS_INVALID_HANDLE; - } - - status = access_check_samr_function(info->acc_granted, - SAMR_ACCESS_ENUM_DOMAINS, - "_samr_EnumDomains"); + SAMR_ACCESS_ENUM_DOMAINS, NULL, + struct samr_connect_info, &status); if (!NT_STATUS_IS_OK(status)) { return status; } |