summaryrefslogtreecommitdiff
path: root/source3
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
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')
-rw-r--r--source3/include/proto.h19
-rw-r--r--source3/rpc_server/srv_lsa_hnd.c73
-rw-r--r--source3/rpc_server/srv_samr_nt.c63
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;
}