summaryrefslogtreecommitdiffstats
path: root/libcli/security/secace.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /libcli/security/secace.c
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libcli/security/secace.c')
-rw-r--r--libcli/security/secace.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/libcli/security/secace.c b/libcli/security/secace.c
new file mode 100644
index 0000000..22bf217
--- /dev/null
+++ b/libcli/security/secace.c
@@ -0,0 +1,204 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * struct security_ace handling functions
+ * Copyright (C) Andrew Tridgell 1992-1998,
+ * Copyright (C) Jeremy R. Allison 1995-2003.
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
+ * Copyright (C) Paul Ashton 1997-1998.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "replace.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "libcli/security/security.h"
+#include "lib/util/tsort.h"
+
+/**
+ * Check if ACE has OBJECT type.
+ */
+bool sec_ace_object(uint8_t type)
+{
+ if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
+ type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
+ type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
+ type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT ||
+ type == SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT ||
+ type == SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT ||
+ type == SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT) {
+ /*
+ * MS-DTYP has a reserved value for
+ * SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT, but we
+ * don't assume that it will be an object ACE just
+ * because it sounds like one.
+ */
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Check if ACE is a CALLBACK type, which means it will have a blob of data at
+ * the end.
+ */
+bool sec_ace_callback(uint8_t type)
+{
+ if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK ||
+ type == SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK ||
+ type == SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT ||
+ type == SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT ||
+ type == SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK ||
+ type == SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT) {
+ /*
+ * While SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK and
+ * SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT sound like
+ * callback types, they are reserved values in MS-DTYP,
+ * and their eventual use is not defined.
+ */
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Check if an ACE type is resource attribute, which means it will
+ * have a blob of data at the end defining an attribute on the object.
+ * Resource attribute ACEs should only occur in SACLs.
+ */
+bool sec_ace_resource(uint8_t type)
+{
+ return type == SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE;
+}
+
+bool sec_ace_has_extra_blob(uint8_t type)
+{
+ return sec_ace_callback(type) || sec_ace_resource(type);
+}
+
+
+/*******************************************************************
+ Sets up a struct security_ace structure.
+********************************************************************/
+
+void init_sec_ace(struct security_ace *t, const struct dom_sid *sid, enum security_ace_type type,
+ uint32_t mask, uint8_t flag)
+{
+ t->type = type;
+ t->flags = flag;
+ t->size = ndr_size_dom_sid(sid, 0) + 8;
+ t->access_mask = mask;
+
+ t->trustee = *sid;
+ t->coda.ignored.data = NULL;
+ t->coda.ignored.length = 0;
+}
+
+int nt_ace_inherit_comp(const struct security_ace *a1, const struct security_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.
+*******************************************************************/
+
+int nt_ace_canon_comp( const struct security_ace *a1, const struct security_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(struct security_ace *srclist, unsigned int num_aces)
+{
+ unsigned int i;
+
+ if (!srclist || num_aces == 0)
+ return;
+
+ /* Sort so that non-inherited ACE's come first. */
+ TYPESAFE_QSORT(srclist, num_aces, nt_ace_inherit_comp);
+
+ /* Find the boundary between non-inherited ACEs. */
+ for (i = 0; i < num_aces; i++ ) {
+ struct security_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. */
+ TYPESAFE_QSORT(srclist, i, nt_ace_canon_comp);
+
+ /* Now sort the inherited ACEs. */
+ TYPESAFE_QSORT(&srclist[i], num_aces - i, nt_ace_canon_comp);
+}