summaryrefslogtreecommitdiff
path: root/source3/rpc_parse/parse_sec.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpc_parse/parse_sec.c')
-rw-r--r--source3/rpc_parse/parse_sec.c179
1 files changed, 130 insertions, 49 deletions
diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c
index 081173cf8d..3848bd7051 100644
--- a/source3/rpc_parse/parse_sec.c
+++ b/source3/rpc_parse/parse_sec.c
@@ -3,7 +3,7 @@
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1998,
- * Copyright (C) Jeremy R. Allison 1995-1998
+ * Copyright (C) Jeremy R. Allison 1995-2003.
* Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
* Copyright (C) Paul Ashton 1997-1998.
*
@@ -48,7 +48,7 @@ BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
prs_debug(ps, depth, desc, "sec_io_access");
depth++;
- if(!prs_uint32("mask", ps, depth, &(t->mask)))
+ if(!prs_uint32("mask", ps, depth, &t->mask))
return False;
return True;
@@ -579,8 +579,6 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
{
SEC_DESC *dst;
uint32 offset = 0;
- uint32 offset_sid = SEC_DESC_HEADER_SIZE;
- uint32 offset_acl = 0;
*sd_size = 0;
@@ -610,58 +608,33 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
goto error_exit;
- offset = 0;
+ offset = SEC_DESC_HEADER_SIZE;
/*
* Work out the linearization sizes.
*/
- if (dst->owner_sid != NULL) {
-
- if (offset == 0)
- offset = SEC_DESC_HEADER_SIZE;
-
- offset += sid_size(dst->owner_sid);
- }
-
- if (dst->grp_sid != NULL) {
-
- if (offset == 0)
- offset = SEC_DESC_HEADER_SIZE;
-
- offset += sid_size(dst->grp_sid);
- }
if (dst->sacl != NULL) {
-
- offset_acl = SEC_DESC_HEADER_SIZE;
-
- dst->off_sacl = offset_acl;
- offset_acl += dst->sacl->size;
- offset += dst->sacl->size;
- offset_sid += dst->sacl->size;
+ dst->off_sacl = offset;
+ offset += dst->sacl->size;
}
if (dst->dacl != NULL) {
-
- if (offset_acl == 0)
- offset_acl = SEC_DESC_HEADER_SIZE;
-
- dst->off_dacl = offset_acl;
- offset_acl += dst->dacl->size;
- offset += dst->dacl->size;
- offset_sid += dst->dacl->size;
+ dst->off_dacl = offset;
+ offset += dst->dacl->size;
}
- *sd_size = (size_t)((offset == 0) ? SEC_DESC_HEADER_SIZE : offset);
+ if (dst->owner_sid != NULL) {
+ dst->off_owner_sid = offset;
+ offset += sid_size(dst->owner_sid);
+ }
- if (dst->owner_sid != NULL)
- dst->off_owner_sid = offset_sid;
-
- /* sid_size() returns 0 if the sid is NULL so this is ok */
-
- if (dst->grp_sid != NULL)
- dst->off_grp_sid = offset_sid + sid_size(dst->owner_sid);
+ if (dst->grp_sid != NULL) {
+ dst->off_grp_sid = offset;
+ offset += sid_size(dst->grp_sid);
+ }
+ *sd_size = (size_t)offset;
return dst;
error_exit:
@@ -928,7 +901,7 @@ BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int
}
/*******************************************************************
- adds new SID with its permissions to SEC_DESC
+ Add a new SID with its permissions to SEC_DESC.
********************************************************************/
NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
@@ -940,7 +913,8 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32
*sd_size = 0;
- if (!ctx || !psd || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER;
+ if (!ctx || !psd || !sid || !sd_size)
+ return NT_STATUS_INVALID_PARAMETER;
status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
@@ -960,14 +934,15 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32
}
/*******************************************************************
- modify SID's permissions at SEC_DESC
+ Modify a SID's permissions in a SEC_DESC.
********************************************************************/
NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
{
NTSTATUS status;
- if (!sd || !sid) return NT_STATUS_INVALID_PARAMETER;
+ if (!sd || !sid)
+ return NT_STATUS_INVALID_PARAMETER;
status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask);
@@ -978,7 +953,7 @@ NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
}
/*******************************************************************
- delete SID from SEC_DESC
+ Delete a SID from a SEC_DESC.
********************************************************************/
NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
@@ -990,7 +965,8 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
*sd_size = 0;
- if (!ctx || !psd[0] || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER;
+ if (!ctx || !psd[0] || !sid || !sd_size)
+ return NT_STATUS_INVALID_PARAMETER;
status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
@@ -1008,3 +984,108 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
sd = 0;
return NT_STATUS_OK;
}
+
+/*******************************************************************
+ Comparison function to sort non-inherited first.
+*******************************************************************/
+
+static int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2)
+{
+ int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE;
+ int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE;
+
+ if (a1_inh == a2_inh)
+ return 0;
+
+ if (!a1_inh && a2_inh)
+ return -1;
+ return 1;
+}
+
+/*******************************************************************
+ Comparison function to apply the order explained below in a group.
+*******************************************************************/
+
+static int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2)
+{
+ if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
+ (a2->type != SEC_ACE_TYPE_ACCESS_DENIED))
+ return -1;
+
+ if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
+ (a1->type != SEC_ACE_TYPE_ACCESS_DENIED))
+ return 1;
+
+ /* Both access denied or access allowed. */
+
+ /* 1. ACEs that apply to the object itself */
+
+ if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
+ (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY))
+ return -1;
+ else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
+ (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY))
+ return 1;
+
+ /* 2. ACEs that apply to a subobject of the object, such as
+ * a property set or property. */
+
+ if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
+ !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
+ return -1;
+ else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
+ !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
+ return 1;
+
+ return 0;
+}
+
+/*******************************************************************
+ Functions to convert a SEC_DESC ACE DACL list into canonical order.
+ JRA.
+
+--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
+
+The following describes the preferred order:
+
+ To ensure that noninherited ACEs have precedence over inherited ACEs,
+ place all noninherited ACEs in a group before any inherited ACEs.
+ This ordering ensures, for example, that a noninherited access-denied ACE
+ is enforced regardless of any inherited ACE that allows access.
+
+ Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows:
+ 1. Access-denied ACEs that apply to the object itself
+ 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property
+ 3. Access-allowed ACEs that apply to the object itself
+ 4. Access-allowed ACEs that apply to a subobject of the object"
+
+********************************************************************/
+
+void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces)
+{
+ unsigned int i;
+
+ if (!srclist || num_aces == 0)
+ return;
+
+ /* Sort so that non-inherited ACE's come first. */
+ qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp);
+
+ /* Find the boundary between non-inherited ACEs. */
+ for (i = 0; i < num_aces; i++ ) {
+ SEC_ACE *curr_ace = &srclist[i];
+
+ if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
+ break;
+ }
+
+ /* i now points at entry number of the first inherited ACE. */
+
+ /* Sort the non-inherited ACEs. */
+ if (i)
+ qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
+
+ /* Now sort the inherited ACEs. */
+ if (num_aces - i)
+ qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
+}