Initial Implementation of the DS objects access checks.
[ira/wip.git] / source4 / libcli / security / access_check.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    security access checking routines
5
6    Copyright (C) Andrew Tridgell 2004
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/security/security.h"
24
25
26 /*
27   perform a SEC_FLAG_MAXIMUM_ALLOWED access check
28 */
29 static uint32_t access_check_max_allowed(const struct security_descriptor *sd, 
30                                          const struct security_token *token)
31 {
32         uint32_t denied = 0, granted = 0;
33         unsigned i;
34         
35         if (security_token_has_sid(token, sd->owner_sid)) {
36                 granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE;
37         } else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
38                 granted |= SEC_STD_DELETE;
39         }
40
41         if (sd->dacl == NULL) {
42                 return granted & ~denied;
43         }
44         
45         for (i = 0;i<sd->dacl->num_aces; i++) {
46                 struct security_ace *ace = &sd->dacl->aces[i];
47
48                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
49                         continue;
50                 }
51
52                 if (!security_token_has_sid(token, &ace->trustee)) {
53                         continue;
54                 }
55
56                 switch (ace->type) {
57                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
58                         granted |= ace->access_mask;
59                         break;
60                 case SEC_ACE_TYPE_ACCESS_DENIED:
61                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
62                         denied |= ace->access_mask;
63                         break;
64                 default:        /* Other ACE types not handled/supported */
65                         break;
66                 }
67         }
68
69         return granted & ~denied;
70 }
71
72 static const struct GUID *get_ace_object_type(struct security_ace *ace)
73 {
74         struct GUID *type;
75
76         if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT)
77                 type = &ace->object.object.type.type;
78         else if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)
79                 type = &ace->object.object.inherited_type.inherited_type; /* This doesn't look right. Is something wrong with the IDL? */
80         else
81                 type = NULL;
82
83         return type;
84
85 }
86
87 /*
88   the main entry point for access checking. 
89 */
90 NTSTATUS sec_access_check(const struct security_descriptor *sd, 
91                           const struct security_token *token,
92                           uint32_t access_desired,
93                           uint32_t *access_granted)
94 {
95         int i;
96         uint32_t bits_remaining;
97
98         *access_granted = access_desired;
99         bits_remaining = access_desired;
100
101         /* handle the maximum allowed flag */
102         if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
103                 access_desired |= access_check_max_allowed(sd, token);
104                 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
105                 *access_granted = access_desired;
106                 bits_remaining = access_desired & ~SEC_STD_DELETE;
107         }
108
109         if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
110                 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
111                         bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
112                 } else {
113                         return NT_STATUS_PRIVILEGE_NOT_HELD;
114                 }
115         }
116
117         /* a NULL dacl allows access */
118         if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
119                 *access_granted = access_desired;
120                 return NT_STATUS_OK;
121         }
122
123         /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
124         if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
125             security_token_has_sid(token, sd->owner_sid)) {
126                 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
127         }
128         if ((bits_remaining & SEC_STD_DELETE) &&
129             security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
130                 bits_remaining &= ~SEC_STD_DELETE;
131         }
132
133         if (sd->dacl == NULL) {
134                 goto done;
135         }
136
137         /* check each ace in turn. */
138         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
139                 struct security_ace *ace = &sd->dacl->aces[i];
140
141                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
142                         continue;
143                 }
144
145                 if (!security_token_has_sid(token, &ace->trustee)) {
146                         continue;
147                 }
148
149                 switch (ace->type) {
150                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
151                         bits_remaining &= ~ace->access_mask;
152                         break;
153                 case SEC_ACE_TYPE_ACCESS_DENIED:
154                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
155                         if (bits_remaining & ace->access_mask) {
156                                 return NT_STATUS_ACCESS_DENIED;
157                         }
158                         break;
159                 default:        /* Other ACE types not handled/supported */
160                         break;
161                 }
162         }
163
164 done:
165         if (bits_remaining != 0) {
166                 return NT_STATUS_ACCESS_DENIED;
167         }
168
169         return NT_STATUS_OK;
170 }
171
172 /* modified access check for the purposes of DS security
173  * Lots of code duplication, it will ve united in just one
174  * function eventually */
175
176 NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
177                              const struct security_token *token,
178                              uint32_t access_desired,
179                              uint32_t *access_granted,
180                              struct object_tree *tree)
181 {
182         int i;
183         uint32_t bits_remaining;
184         struct object_tree *node;
185         struct GUID *type;
186
187         *access_granted = access_desired;
188         bits_remaining = access_desired;
189
190         /* handle the maximum allowed flag */
191         if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
192                 access_desired |= access_check_max_allowed(sd, token);
193                 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
194                 *access_granted = access_desired;
195                 bits_remaining = access_desired & ~SEC_STD_DELETE;
196         }
197
198         if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
199                 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
200                         bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
201                 } else {
202                         return NT_STATUS_PRIVILEGE_NOT_HELD;
203                 }
204         }
205
206         /* a NULL dacl allows access */
207         if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
208                 *access_granted = access_desired;
209                 return NT_STATUS_OK;
210         }
211
212         /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
213         if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
214             security_token_has_sid(token, sd->owner_sid)) {
215                 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
216         }
217         if ((bits_remaining & SEC_STD_DELETE) &&
218             security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
219                 bits_remaining &= ~SEC_STD_DELETE;
220         }
221
222         if (sd->dacl == NULL) {
223                 goto done;
224         }
225
226         /* check each ace in turn. */
227         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
228                 struct security_ace *ace = &sd->dacl->aces[i];
229
230                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
231                         continue;
232                 }
233
234                 if (!security_token_has_sid(token, &ace->trustee)) {
235                         continue;
236                 }
237
238                 switch (ace->type) {
239                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
240                         if (tree)
241                                 object_tree_modify_access(tree, ace->access_mask);
242
243                         bits_remaining &= ~ace->access_mask;
244                         break;
245                 case SEC_ACE_TYPE_ACCESS_DENIED:
246                         if (bits_remaining & ace->access_mask) {
247                                 return NT_STATUS_ACCESS_DENIED;
248                         }
249                         break;
250                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
251                 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
252                         /* check only in case we have provided a tree,
253                          * the ACE has an object type and that type
254                          * is in the tree                           */
255                         type = get_ace_object_type(ace);
256
257                         if (!tree)
258                                 continue;
259
260                         if (!type)
261                                 node = tree;
262                         else
263                                 if (!(node = get_object_tree_by_GUID(tree, type)))
264                                         continue;
265
266                         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT){
267                                 object_tree_modify_access(node, ace->access_mask);
268                         }
269                         else {
270                                 if (node->remaining_access & ace->access_mask){
271                                         return NT_STATUS_ACCESS_DENIED;
272                                 }
273                         }
274                         break;
275                 default:        /* Other ACE types not handled/supported */
276                         break;
277                 }
278         }
279
280 done:
281         if (bits_remaining != 0) {
282                 return NT_STATUS_ACCESS_DENIED;
283         }
284
285         return NT_STATUS_OK;
286 }
287
288
289
290