summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}