c974a39e29c8c47f1e78d247b1d671df85bb6088
[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_RIGHTS_PRIV_RESTORE) &&
129             security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
130                 bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
131         }
132         if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
133             security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
134                 bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
135         }
136
137         if (sd->dacl == NULL) {
138                 goto done;
139         }
140
141         /* check each ace in turn. */
142         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
143                 struct security_ace *ace = &sd->dacl->aces[i];
144
145                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
146                         continue;
147                 }
148
149                 if (!security_token_has_sid(token, &ace->trustee)) {
150                         continue;
151                 }
152
153                 switch (ace->type) {
154                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
155                         bits_remaining &= ~ace->access_mask;
156                         break;
157                 case SEC_ACE_TYPE_ACCESS_DENIED:
158                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
159                         if (bits_remaining & ace->access_mask) {
160                                 return NT_STATUS_ACCESS_DENIED;
161                         }
162                         break;
163                 default:        /* Other ACE types not handled/supported */
164                         break;
165                 }
166         }
167
168 done:
169         if (bits_remaining != 0) {
170                 return NT_STATUS_ACCESS_DENIED;
171         }
172
173         return NT_STATUS_OK;
174 }
175
176 /* modified access check for the purposes of DS security
177  * Lots of code duplication, it will ve united in just one
178  * function eventually */
179
180 NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
181                              const struct security_token *token,
182                              uint32_t access_desired,
183                              uint32_t *access_granted,
184                              struct object_tree *tree)
185 {
186         int i;
187         uint32_t bits_remaining;
188         struct object_tree *node;
189         const struct GUID *type;
190
191         *access_granted = access_desired;
192         bits_remaining = access_desired;
193
194         /* handle the maximum allowed flag */
195         if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
196                 access_desired |= access_check_max_allowed(sd, token);
197                 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
198                 *access_granted = access_desired;
199                 bits_remaining = access_desired & ~SEC_STD_DELETE;
200         }
201
202         if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
203                 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
204                         bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
205                 } else {
206                         return NT_STATUS_PRIVILEGE_NOT_HELD;
207                 }
208         }
209
210         /* a NULL dacl allows access */
211         if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
212                 *access_granted = access_desired;
213                 return NT_STATUS_OK;
214         }
215
216         /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
217         if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
218             security_token_has_sid(token, sd->owner_sid)) {
219                 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
220         }
221         if ((bits_remaining & SEC_STD_DELETE) &&
222             security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
223                 bits_remaining &= ~SEC_STD_DELETE;
224         }
225
226         if (sd->dacl == NULL) {
227                 goto done;
228         }
229
230         /* check each ace in turn. */
231         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
232                 struct security_ace *ace = &sd->dacl->aces[i];
233
234                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
235                         continue;
236                 }
237
238                 if (!security_token_has_sid(token, &ace->trustee)) {
239                         continue;
240                 }
241
242                 switch (ace->type) {
243                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
244                         if (tree)
245                                 object_tree_modify_access(tree, ace->access_mask);
246
247                         bits_remaining &= ~ace->access_mask;
248                         break;
249                 case SEC_ACE_TYPE_ACCESS_DENIED:
250                         if (bits_remaining & ace->access_mask) {
251                                 return NT_STATUS_ACCESS_DENIED;
252                         }
253                         break;
254                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
255                 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
256                         /* check only in case we have provided a tree,
257                          * the ACE has an object type and that type
258                          * is in the tree                           */
259                         type = get_ace_object_type(ace);
260
261                         if (!tree)
262                                 continue;
263
264                         if (!type)
265                                 node = tree;
266                         else
267                                 if (!(node = get_object_tree_by_GUID(tree, type)))
268                                         continue;
269
270                         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT){
271                                 object_tree_modify_access(node, ace->access_mask);
272                         }
273                         else {
274                                 if (node->remaining_access & ace->access_mask){
275                                         return NT_STATUS_ACCESS_DENIED;
276                                 }
277                         }
278                         break;
279                 default:        /* Other ACE types not handled/supported */
280                         break;
281                 }
282         }
283
284 done:
285         if (bits_remaining != 0) {
286                 return NT_STATUS_ACCESS_DENIED;
287         }
288
289         return NT_STATUS_OK;
290 }
291
292
293
294