/src/samba/libcli/security/secace.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Unix SMB/Netbios implementation. |
3 | | * struct security_ace handling functions |
4 | | * Copyright (C) Andrew Tridgell 1992-1998, |
5 | | * Copyright (C) Jeremy R. Allison 1995-2003. |
6 | | * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, |
7 | | * Copyright (C) Paul Ashton 1997-1998. |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify |
10 | | * it under the terms of the GNU General Public License as published by |
11 | | * the Free Software Foundation; either version 3 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU General Public License |
20 | | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
21 | | */ |
22 | | |
23 | | #include "replace.h" |
24 | | #include "librpc/gen_ndr/ndr_security.h" |
25 | | #include "libcli/security/security.h" |
26 | | #include "lib/util/tsort.h" |
27 | | |
28 | | /** |
29 | | * Check if ACE has OBJECT type. |
30 | | */ |
31 | | bool sec_ace_object(uint8_t type) |
32 | 4.23M | { |
33 | 4.23M | if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || |
34 | 4.23M | type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || |
35 | 4.23M | type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || |
36 | 4.23M | type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT || |
37 | 4.23M | type == SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT || |
38 | 4.23M | type == SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT || |
39 | 4.23M | type == SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT) { |
40 | | /* |
41 | | * MS-DTYP has a reserved value for |
42 | | * SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT, but we |
43 | | * don't assume that it will be an object ACE just |
44 | | * because it sounds like one. |
45 | | */ |
46 | 883k | return true; |
47 | 883k | } |
48 | 3.35M | return false; |
49 | 4.23M | } |
50 | | |
51 | | /** |
52 | | * Check if ACE is a CALLBACK type, which means it will have a blob of data at |
53 | | * the end. |
54 | | */ |
55 | | bool sec_ace_callback(uint8_t type) |
56 | 2.42M | { |
57 | 2.42M | if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK || |
58 | 2.42M | type == SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK || |
59 | 2.42M | type == SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK_OBJECT || |
60 | 2.42M | type == SEC_ACE_TYPE_ACCESS_DENIED_CALLBACK_OBJECT || |
61 | 2.42M | type == SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK || |
62 | 2.42M | type == SEC_ACE_TYPE_SYSTEM_AUDIT_CALLBACK_OBJECT) { |
63 | | /* |
64 | | * While SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK and |
65 | | * SEC_ACE_TYPE_SYSTEM_ALARM_CALLBACK_OBJECT sound like |
66 | | * callback types, they are reserved values in MS-DTYP, |
67 | | * and their eventual use is not defined. |
68 | | */ |
69 | 413k | return true; |
70 | 413k | } |
71 | 2.00M | return false; |
72 | 2.42M | } |
73 | | |
74 | | /** |
75 | | * Check if an ACE type is resource attribute, which means it will |
76 | | * have a blob of data at the end defining an attribute on the object. |
77 | | * Resource attribute ACEs should only occur in SACLs. |
78 | | */ |
79 | | bool sec_ace_resource(uint8_t type) |
80 | 1.22M | { |
81 | 1.22M | return type == SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE; |
82 | 1.22M | } |
83 | | |
84 | | bool sec_ace_has_extra_blob(uint8_t type) |
85 | 1.10M | { |
86 | 1.10M | return sec_ace_callback(type) || sec_ace_resource(type); |
87 | 1.10M | } |
88 | | |
89 | | |
90 | | /******************************************************************* |
91 | | Sets up a struct security_ace structure. |
92 | | ********************************************************************/ |
93 | | |
94 | | void init_sec_ace(struct security_ace *t, const struct dom_sid *sid, enum security_ace_type type, |
95 | | uint32_t mask, uint8_t flag) |
96 | 0 | { |
97 | 0 | t->type = type; |
98 | 0 | t->flags = flag; |
99 | 0 | t->size = ndr_size_dom_sid(sid, 0) + 8; |
100 | 0 | t->access_mask = mask; |
101 | |
|
102 | 0 | t->trustee = *sid; |
103 | 0 | t->coda.ignored.data = NULL; |
104 | 0 | t->coda.ignored.length = 0; |
105 | 0 | } |
106 | | |
107 | | int nt_ace_inherit_comp(const struct security_ace *a1, const struct security_ace *a2) |
108 | 0 | { |
109 | 0 | int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE; |
110 | 0 | int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE; |
111 | |
|
112 | 0 | if (a1_inh == a2_inh) |
113 | 0 | return 0; |
114 | | |
115 | 0 | if (!a1_inh && a2_inh) |
116 | 0 | return -1; |
117 | 0 | return 1; |
118 | 0 | } |
119 | | |
120 | | /******************************************************************* |
121 | | Comparison function to apply the order explained below in a group. |
122 | | *******************************************************************/ |
123 | | |
124 | | int nt_ace_canon_comp( const struct security_ace *a1, const struct security_ace *a2) |
125 | 0 | { |
126 | 0 | if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) && |
127 | 0 | (a2->type != SEC_ACE_TYPE_ACCESS_DENIED)) |
128 | 0 | return -1; |
129 | | |
130 | 0 | if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) && |
131 | 0 | (a1->type != SEC_ACE_TYPE_ACCESS_DENIED)) |
132 | 0 | return 1; |
133 | | |
134 | | /* Both access denied or access allowed. */ |
135 | | |
136 | | /* 1. ACEs that apply to the object itself */ |
137 | | |
138 | 0 | if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) && |
139 | 0 | (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY)) |
140 | 0 | return -1; |
141 | 0 | else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) && |
142 | 0 | (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY)) |
143 | 0 | return 1; |
144 | | |
145 | | /* 2. ACEs that apply to a subobject of the object, such as |
146 | | * a property set or property. */ |
147 | | |
148 | 0 | if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && |
149 | 0 | !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) |
150 | 0 | return -1; |
151 | 0 | else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && |
152 | 0 | !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) |
153 | 0 | return 1; |
154 | | |
155 | 0 | return 0; |
156 | 0 | } |
157 | | |
158 | | /******************************************************************* |
159 | | Functions to convert a SEC_DESC ACE DACL list into canonical order. |
160 | | JRA. |
161 | | |
162 | | --- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp |
163 | | |
164 | | The following describes the preferred order: |
165 | | |
166 | | To ensure that noninherited ACEs have precedence over inherited ACEs, |
167 | | place all noninherited ACEs in a group before any inherited ACEs. |
168 | | This ordering ensures, for example, that a noninherited access-denied ACE |
169 | | is enforced regardless of any inherited ACE that allows access. |
170 | | |
171 | | Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows: |
172 | | 1. Access-denied ACEs that apply to the object itself |
173 | | 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property |
174 | | 3. Access-allowed ACEs that apply to the object itself |
175 | | 4. Access-allowed ACEs that apply to a subobject of the object" |
176 | | |
177 | | ********************************************************************/ |
178 | | |
179 | | void dacl_sort_into_canonical_order(struct security_ace *srclist, unsigned int num_aces) |
180 | 0 | { |
181 | 0 | unsigned int i; |
182 | |
|
183 | 0 | if (!srclist || num_aces == 0) |
184 | 0 | return; |
185 | | |
186 | | /* Sort so that non-inherited ACE's come first. */ |
187 | 0 | TYPESAFE_QSORT(srclist, num_aces, nt_ace_inherit_comp); |
188 | | |
189 | | /* Find the boundary between non-inherited ACEs. */ |
190 | 0 | for (i = 0; i < num_aces; i++ ) { |
191 | 0 | struct security_ace *curr_ace = &srclist[i]; |
192 | |
|
193 | 0 | if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE) |
194 | 0 | break; |
195 | 0 | } |
196 | | |
197 | | /* i now points at entry number of the first inherited ACE. */ |
198 | | |
199 | | /* Sort the non-inherited ACEs. */ |
200 | 0 | TYPESAFE_QSORT(srclist, i, nt_ace_canon_comp); |
201 | | |
202 | | /* Now sort the inherited ACEs. */ |
203 | 0 | TYPESAFE_QSORT(&srclist[i], num_aces - i, nt_ace_canon_comp); |
204 | 0 | } |