Fixed a bug in object specific 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   perform a SEC_FLAG_MAXIMUM_ALLOWED access check
27 */
28 static uint32_t access_check_max_allowed(const struct security_descriptor *sd, 
29                                          const struct security_token *token)
30 {
31         uint32_t denied = 0, granted = 0;
32         unsigned i;
33         
34         if (security_token_has_sid(token, sd->owner_sid)) {
35                 granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE;
36         } else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
37                 granted |= SEC_STD_DELETE;
38         }
39
40         if (sd->dacl == NULL) {
41                 return granted & ~denied;
42         }
43         
44         for (i = 0;i<sd->dacl->num_aces; i++) {
45                 struct security_ace *ace = &sd->dacl->aces[i];
46
47                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
48                         continue;
49                 }
50
51                 if (!security_token_has_sid(token, &ace->trustee)) {
52                         continue;
53                 }
54
55                 switch (ace->type) {
56                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
57                         granted |= ace->access_mask;
58                         break;
59                 case SEC_ACE_TYPE_ACCESS_DENIED:
60                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
61                         denied |= ace->access_mask;
62                         break;
63                 default:        /* Other ACE types not handled/supported */
64                         break;
65                 }
66         }
67
68         return granted & ~denied;
69 }
70
71 static const struct GUID *get_ace_object_type(struct security_ace *ace)
72 {
73         struct GUID *type;
74
75         if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT)
76                 type = &ace->object.object.type.type;
77         else if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)
78                 type = &ace->object.object.inherited_type.inherited_type; /* This doesn't look right. Is something wrong with the IDL? */
79         else
80                 type = NULL;
81
82         return type;
83
84 }
85
86 /*
87   the main entry point for access checking. 
88 */
89 NTSTATUS sec_access_check(const struct security_descriptor *sd, 
90                           const struct security_token *token,
91                           uint32_t access_desired,
92                           uint32_t *access_granted)
93 {
94         int i;
95         uint32_t bits_remaining;
96
97         *access_granted = access_desired;
98         bits_remaining = access_desired;
99
100         /* handle the maximum allowed flag */
101         if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
102                 access_desired |= access_check_max_allowed(sd, token);
103                 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
104                 *access_granted = access_desired;
105                 bits_remaining = access_desired & ~SEC_STD_DELETE;
106         }
107
108         if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
109                 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
110                         bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
111                 } else {
112                         return NT_STATUS_PRIVILEGE_NOT_HELD;
113                 }
114         }
115
116         /* a NULL dacl allows access */
117         if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
118                 *access_granted = access_desired;
119                 return NT_STATUS_OK;
120         }
121
122         /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
123         if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
124             security_token_has_sid(token, sd->owner_sid)) {
125                 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
126         }
127         if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) &&
128             security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
129                 bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
130         }
131         if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
132             security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
133                 bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
134         }
135
136         if (sd->dacl == NULL) {
137                 goto done;
138         }
139
140         /* check each ace in turn. */
141         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
142                 struct security_ace *ace = &sd->dacl->aces[i];
143
144                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
145                         continue;
146                 }
147
148                 if (!security_token_has_sid(token, &ace->trustee)) {
149                         continue;
150                 }
151
152                 switch (ace->type) {
153                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
154                         bits_remaining &= ~ace->access_mask;
155                         break;
156                 case SEC_ACE_TYPE_ACCESS_DENIED:
157                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
158                         if (bits_remaining & ace->access_mask) {
159                                 return NT_STATUS_ACCESS_DENIED;
160                         }
161                         break;
162                 default:        /* Other ACE types not handled/supported */
163                         break;
164                 }
165         }
166
167 done:
168         if (bits_remaining != 0) {
169                 return NT_STATUS_ACCESS_DENIED;
170         }
171
172         return NT_STATUS_OK;
173 }
174
175 /* modified access check for the purposes of DS security
176  * Lots of code duplication, it will ve united in just one
177  * function eventually */
178
179 NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
180                              const struct security_token *token,
181                              uint32_t access_desired,
182                              uint32_t *access_granted,
183                              struct object_tree *tree)
184 {
185         int i;
186         uint32_t bits_remaining;
187         struct object_tree *node;
188         const struct GUID *type;
189
190         *access_granted = access_desired;
191         bits_remaining = access_desired;
192
193         /* handle the maximum allowed flag */
194         if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
195                 access_desired |= access_check_max_allowed(sd, token);
196                 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
197                 *access_granted = access_desired;
198                 bits_remaining = access_desired & ~SEC_STD_DELETE;
199         }
200
201         if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
202                 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
203                         bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
204                 } else {
205                         return NT_STATUS_PRIVILEGE_NOT_HELD;
206                 }
207         }
208
209         /* a NULL dacl allows access */
210         if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
211                 *access_granted = access_desired;
212                 return NT_STATUS_OK;
213         }
214
215         /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
216         if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
217             security_token_has_sid(token, sd->owner_sid)) {
218                 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
219         }
220         if ((bits_remaining & SEC_STD_DELETE) &&
221             security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
222                 bits_remaining &= ~SEC_STD_DELETE;
223         }
224
225         if (sd->dacl == NULL) {
226                 goto done;
227         }
228
229         /* check each ace in turn. */
230         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
231                 struct security_ace *ace = &sd->dacl->aces[i];
232
233                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
234                         continue;
235                 }
236
237                 if (!security_token_has_sid(token, &ace->trustee)) {
238                         continue;
239                 }
240
241                 switch (ace->type) {
242                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
243                         if (tree)
244                                 object_tree_modify_access(tree, ace->access_mask);
245
246                         bits_remaining &= ~ace->access_mask;
247                         break;
248                 case SEC_ACE_TYPE_ACCESS_DENIED:
249                         if (bits_remaining & ace->access_mask) {
250                                 return NT_STATUS_ACCESS_DENIED;
251                         }
252                         break;
253                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
254                 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
255                         /* check only in case we have provided a tree,
256                          * the ACE has an object type and that type
257                          * is in the tree                           */
258                         type = get_ace_object_type(ace);
259
260                         if (!tree)
261                                 continue;
262
263                         if (!type)
264                                 node = tree;
265                         else
266                                 if (!(node = get_object_tree_by_GUID(tree, type)))
267                                         continue;
268
269                         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) {
270                                 object_tree_modify_access(node, ace->access_mask);
271                                 if (node->remaining_access == 0) {
272                                         return NT_STATUS_OK;
273                                 }
274                         }
275                         else {
276                                 if (node->remaining_access & ace->access_mask){
277                                         return NT_STATUS_ACCESS_DENIED;
278                                 }
279                         }
280                         break;
281                 default:        /* Other ACE types not handled/supported */
282                         break;
283                 }
284         }
285
286 done:
287         if (bits_remaining != 0) {
288                 return NT_STATUS_ACCESS_DENIED;
289         }
290
291         return NT_STATUS_OK;
292 }
293
294
295
296