diff options
Diffstat (limited to 'source3/rpc_server/srv_lsa_hnd.c')
-rw-r--r-- | source3/rpc_server/srv_lsa_hnd.c | 129 |
1 files changed, 123 insertions, 6 deletions
diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c index e853bb2047..21b297af2d 100644 --- a/source3/rpc_server/srv_lsa_hnd.c +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -24,6 +24,26 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV +/* + * Handle database - stored per pipe. + */ + +struct policy { + struct policy *next, *prev; + + struct policy_handle pol_hnd; + + uint32_t access_granted; + + void *data_ptr; +}; + +struct handle_list { + struct policy *Policy; /* List of policies. */ + size_t count; /* Current number of handles. */ + size_t pipe_ref_count; /* Number of pipe handles referring to this list. */ +}; + /* This is the max handles across all instances of a pipe name. */ #ifndef MAX_OPEN_POLS #define MAX_OPEN_POLS 1024 @@ -40,6 +60,14 @@ static bool is_samr_lsa_pipe(const struct ndr_syntax_id *syntax) || ndr_syntax_id_equal(syntax, &ndr_table_lsarpc.syntax_id)); } +size_t num_pipe_handles(struct handle_list *list) +{ + if (list == NULL) { + return 0; + } + return list->count; +} + /**************************************************************************** Initialise a policy handle list on a pipe. Handle list is shared between all pipes of the same name. @@ -112,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; @@ -123,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) { @@ -160,14 +190,22 @@ 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; } /**************************************************************************** find policy by handle - internal version. ****************************************************************************/ -static struct policy *find_policy_by_hnd_internal(pipes_struct *p, struct policy_handle *hnd, void **data_p) +static struct policy *find_policy_by_hnd_internal(pipes_struct *p, + const struct policy_handle *hnd, + void **data_p) { struct policy *pol; size_t i; @@ -197,7 +235,8 @@ static struct policy *find_policy_by_hnd_internal(pipes_struct *p, struct policy find policy by handle ****************************************************************************/ -bool find_policy_by_hnd(pipes_struct *p, struct policy_handle *hnd, void **data_p) +bool find_policy_by_hnd(pipes_struct *p, const struct policy_handle *hnd, + void **data_p) { return find_policy_by_hnd_internal(p, hnd, data_p) == NULL ? False : True; } @@ -277,3 +316,81 @@ bool pipe_access_check(pipes_struct *p) return True; } + +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) +{ + 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))); + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; + return NULL; + } + + data = talloc_size(talloc_tos(), data_size); + if (data == NULL) { + *pstatus = NT_STATUS_NO_MEMORY; + return NULL; + } + talloc_set_name(data, "%s", type); + + pol = create_policy_hnd_internal(p, hnd, data); + if (pol == NULL) { + TALLOC_FREE(data); + *pstatus = NT_STATUS_NO_MEMORY; + return NULL; + } + pol->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) +{ + struct policy *pol; + void *data; + + 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; +} |