summaryrefslogtreecommitdiff
path: root/source3/rpc_server/srv_lsa_hnd.c
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2009-04-18 16:46:53 +0200
committerVolker Lendecke <vl@samba.org>2009-04-19 09:27:15 +0200
commit35e6a0e618db99287d12092cd8048276ffdb2356 (patch)
tree338ea009134ef536912b6ed4e43a59ad4266593a /source3/rpc_server/srv_lsa_hnd.c
parent9b3f2e69f772a12c661879109e0edcda6c365be4 (diff)
downloadsamba-35e6a0e618db99287d12092cd8048276ffdb2356.tar.gz
samba-35e6a0e618db99287d12092cd8048276ffdb2356.tar.bz2
samba-35e6a0e618db99287d12092cd8048276ffdb2356.zip
Add "uint32_t access_granted" to policy handles
All policy handles have a mask of allowed operations attached that were calculated at creation time, so they should carry this mask. This is the basis for consolidating all our policy handle access checks. If you want to do your own more complicated access checks further down, just pass "0" to policy_handle_find.
Diffstat (limited to 'source3/rpc_server/srv_lsa_hnd.c')
-rw-r--r--source3/rpc_server/srv_lsa_hnd.c73
1 files changed, 58 insertions, 15 deletions
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;
}