1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
From 12f97f9f69d3ace751c9b49f739aecc4e452dd35 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale@catalyst.net.nz>
Date: Thu, 19 Jul 2018 16:03:36 +1200
Subject: [PATCH] CVE-2018-10919 security: Move object-specific access checks
into separate function
Object-specific access checks refer to a specific section of the
MS-ADTS, and the code closely matches the spec. We need to extend this
logic to properly handle the Control-Access Right (CR), so it makes
sense to split the logic out into its own function.
This patch just moves the code, and should not alter the logic (apart
from ading in the boolean grant_access return variable.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13434
Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
---
libcli/security/access_check.c | 86 +++++++++++++++++++++++-----------
1 file changed, 59 insertions(+), 27 deletions(-)
diff --git a/libcli/security/access_check.c b/libcli/security/access_check.c
index b4c850b613e..b4e62441542 100644
--- a/libcli/security/access_check.c
+++ b/libcli/security/access_check.c
@@ -374,6 +374,57 @@ static const struct GUID *get_ace_object_type(struct security_ace *ace)
return NULL;
}
+/**
+ * Evaluates access rights specified in a object-specific ACE for an AD object.
+ * This logic corresponds to MS-ADTS 5.1.3.3.3 Checking Object-Specific Access.
+ * @param[in] ace - the ACE being processed
+ * @param[in/out] tree - remaining_access gets updated for the tree
+ * @param[out] grant_access - set to true if the ACE grants sufficient access
+ * rights to the object/attribute
+ * @returns NT_STATUS_OK, unless access was denied
+ */
+static NTSTATUS check_object_specific_access(struct security_ace *ace,
+ struct object_tree *tree,
+ bool *grant_access)
+{
+ struct object_tree *node = NULL;
+ const struct GUID *type = NULL;
+
+ *grant_access = false;
+
+ /*
+ * check only in case we have provided a tree,
+ * the ACE has an object type and that type
+ * is in the tree
+ */
+ type = get_ace_object_type(ace);
+
+ if (!tree) {
+ return NT_STATUS_OK;
+ }
+
+ if (!type) {
+ node = tree;
+ } else {
+ if (!(node = get_object_tree_by_GUID(tree, type))) {
+ return NT_STATUS_OK;
+ }
+ }
+
+ if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) {
+ object_tree_modify_access(node, ace->access_mask);
+ if (node->remaining_access == 0) {
+ *grant_access = true;
+ return NT_STATUS_OK;
+ }
+ } else {
+ if (node->remaining_access & ace->access_mask){
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
/**
* @brief Perform directoryservice (DS) related access checks for a given user
*
@@ -405,8 +456,6 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
{
uint32_t i;
uint32_t bits_remaining;
- struct object_tree *node;
- const struct GUID *type;
struct dom_sid self_sid;
dom_sid_parse(SID_NT_SELF, &self_sid);
@@ -456,6 +505,8 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
struct dom_sid *trustee;
struct security_ace *ace = &sd->dacl->aces[i];
+ NTSTATUS status;
+ bool grant_access = false;
if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
continue;
@@ -486,34 +537,15 @@ NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
break;
case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
- /*
- * check only in case we have provided a tree,
- * the ACE has an object type and that type
- * is in the tree
- */
- type = get_ace_object_type(ace);
-
- if (!tree) {
- continue;
- }
+ status = check_object_specific_access(ace, tree,
+ &grant_access);
- if (!type) {
- node = tree;
- } else {
- if (!(node = get_object_tree_by_GUID(tree, type))) {
- continue;
- }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) {
- object_tree_modify_access(node, ace->access_mask);
- if (node->remaining_access == 0) {
- return NT_STATUS_OK;
- }
- } else {
- if (node->remaining_access & ace->access_mask){
- return NT_STATUS_ACCESS_DENIED;
- }
+ if (grant_access) {
+ return NT_STATUS_OK;
}
break;
default: /* Other ACE types not handled/supported */
--
2.18.0
|