Started to canonicalize our handling of uid -> sid code in order to
[abartlet/samba.git/.git] / source3 / lib / util_seaccess.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 2.0
4    Copyright (C) Luke Kenneth Casson Leighton 1996-2000.
5    Copyright (C) Tim Potter 2000.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "nterr.h"
24 #include "sids.h"
25
26 extern int DEBUGLEVEL;
27
28 /* Process an access allowed ACE */
29
30 static BOOL ace_grant(uint32 mask, uint32 *acc_desired, uint32 *acc_granted)
31 {
32         uint32 matches;
33
34         /* If there are any matches in the ACE mask and desired access,
35            turn them off in the desired access and on in the granted
36            mask. */ 
37
38         if (*acc_desired == SEC_RIGHTS_MAXIMUM_ALLOWED) {
39                 matches = mask;
40                 *acc_desired = mask;
41         } else {
42                 matches = mask & *acc_desired;
43         }
44
45         if (matches) {
46                 *acc_desired = *acc_desired & ~matches;
47                 *acc_granted = *acc_granted | matches;
48         }
49
50         return *acc_desired == 0;
51 }
52
53 /* Process an access denied ACE */
54
55 static BOOL ace_deny(uint32 mask, uint32 *acc_desired, uint32 *acc_granted)
56 {
57         uint32 matches;
58
59         /* If there are any matches in the ACE mask and the desired access,
60            all bits are turned off in the desired and granted mask. */
61
62         if (*acc_desired == SEC_RIGHTS_MAXIMUM_ALLOWED) {
63                 matches = mask;
64         } else {
65                 matches = mask & *acc_desired;
66         }
67
68         if (matches) {
69                 *acc_desired = *acc_granted = 0;
70         }
71
72         return *acc_desired == 0;
73 }
74
75 /* Check an ACE against a SID.  We return true if the ACE clears all the
76    permission bits in the access desired mask.  This indicates that we have
77    make a decision to deny or allow access and the status is updated
78    accordingly. */
79
80 static BOOL check_ace(SEC_ACE *ace, BOOL is_owner, DOM_SID *sid, 
81                       uint32 *acc_desired, uint32 *acc_granted, 
82                       uint32 *status)
83 {
84         uint32 mask = ace->info.mask;
85
86         /* Inherit only is ignored */
87
88         if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
89                 return False;
90         }
91
92         /* Some debugging stuff */
93
94         if (DEBUGLEVEL >= 3) {
95                 fstring ace_sid_str, sid_str;
96                 fstring ace_name, ace_name_dom, name, name_dom;
97                 uint8 name_type;
98                 
99                 sid_to_string(sid_str, sid);
100                 sid_to_string(ace_sid_str, &ace->sid);
101
102                 if (!lookup_sid(sid, name_dom, name, &name_type)) {
103                         fstrcpy(name_dom, "UNKNOWN");
104                         fstrcpy(name, "UNKNOWN");
105                 }
106
107                 if (!lookup_sid(&ace->sid, ace_name_dom, ace_name, 
108                                         &name_type)) {
109                         fstrcpy(ace_name_dom, "UNKNOWN");
110                         fstrcpy(ace_name, "UNKNOWN");
111                 }
112
113                 DEBUG(3, ("checking %s ACE sid %s (%s%s%s) mask 0x%08x "
114                           "against sid %s (%s%s%s)\n",
115                           (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? 
116                           "allowed" : ((ace->type ==
117                                         SEC_ACE_TYPE_ACCESS_DENIED) ?
118                                        "denied" : "unknown"),
119                           ace_sid_str, ace_name_dom, lp_winbind_separator(),
120                           ace_name, mask, sid_str, name_dom,
121                           lp_winbind_separator(), name));
122         }
123
124         /* Only owner allowed write-owner rights */
125
126         if (!is_owner) {
127                 mask &= (~SEC_RIGHTS_WRITE_OWNER);
128         }
129
130         /* Check the ACE value.  This updates the access_desired and
131            access_granted values appropriately. */
132
133         switch (ace->type) {
134
135                 /* Access allowed ACE */
136
137                 case SEC_ACE_TYPE_ACCESS_ALLOWED: {
138
139                         /* Everyone - or us */
140
141                         if (sid_equal(&ace->sid, global_sid_everyone) ||
142                             sid_equal(&ace->sid, sid)) {
143
144                                 /* Return true if access has been allowed */
145
146                                 if (ace_grant(mask, acc_desired, 
147                                               acc_granted)) {
148                                         *status = NT_STATUS_NO_PROBLEMO;
149                                         DEBUG(3, ("access granted by ace\n"));
150                                         return True;
151                                 }
152                         }
153
154                         break;
155                 }
156
157                 /* Access denied ACE */
158
159                 case SEC_ACE_TYPE_ACCESS_DENIED: {
160
161                         /* Everyone - or us */
162
163                         if (sid_equal(&ace->sid, global_sid_everyone) ||
164                             sid_equal(&ace->sid, sid)) {
165                                 
166                                 /* Return false if access has been denied */
167
168                                 if (ace_deny(mask, acc_desired, 
169                                              acc_granted)) {
170                                         *status = NT_STATUS_ACCESS_DENIED;
171                                         DEBUG(3, ("access denied by ace\n"));
172                                         return True;
173                                 }
174                         }
175
176                         break;
177                 }
178
179                 /* Unimplemented ACE types.  These are ignored. */
180
181                 case SEC_ACE_TYPE_SYSTEM_ALARM:
182                 case SEC_ACE_TYPE_SYSTEM_AUDIT: {
183                         *status = NT_STATUS_NOT_IMPLEMENTED;
184                         return False;
185                 }
186
187                 /* Unknown ACE type */
188
189                 default: {
190                         *status = NT_STATUS_INVALID_PARAMETER;
191                         return False;
192                 }
193         }
194
195         /* There are still some bits set in the access desired mask that
196            haven't been cleared by an ACE.  More checking is required. */
197
198         return False;
199 }
200
201 /* Check access rights of a user against a security descriptor.  Look at
202    each ACE in the security descriptor until an access denied ACE denies
203    any of the desired rights to the user or any of the users groups, or one
204    or more ACEs explicitly grant all requested access rights.  See
205    "Access-Checking" document in MSDN. */ 
206
207 BOOL se_access_check(SEC_DESC *sd, struct current_user *user,
208                      uint32 acc_desired, uint32 *acc_granted, uint32 *status)
209 {
210         DOM_SID user_sid, group_sid;
211         DOM_SID owner_sid;
212         DOM_SID **group_sids = NULL;
213         int i, j;
214         uint ngroup_sids = 0;
215         SEC_ACL *acl;
216         uint8 check_ace_type;
217         fstring sid_str;
218
219         if (!status || !acc_granted)
220                 return False;
221
222         *status = NT_STATUS_ACCESS_DENIED;
223         *acc_granted = 0;
224
225         /*
226          * No security descriptor or security descriptor with no DACL
227          * present allows all access.
228          */
229
230         if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) {
231                 *status = NT_STATUS_NOPROBLEMO;
232                 *acc_granted = acc_desired;
233                 acc_desired = 0;
234                 DEBUG(3, ("se_access_check: no sd or blank DACL, access allowed\n"));
235                 goto done;
236         }
237
238         /* If desired access mask is empty then no access is allowed */
239
240         if (acc_desired == 0) {
241                 *status = NT_STATUS_ACCESS_DENIED;
242                 *acc_granted = 0;
243                 goto done;
244         }
245
246         /* We must know the owner sid */
247
248         if (sd->owner_sid == NULL) {
249                 DEBUG(1, ("no owner for security descriptor\n"));
250                 goto done;
251         }
252
253         /* Create user sid */
254
255         if (!uid_to_sid(&user_sid, user->uid)) {
256                 DEBUG(3, ("could not lookup sid for uid %d\n", user->uid));
257                 goto done;
258         }
259
260         DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &user_sid) ));
261
262         /* If we're the owner, then we can do anything */
263
264         if (sid_equal(&user_sid, sd->owner_sid)) {
265                 *status = NT_STATUS_NOPROBLEMO;
266                 *acc_granted = acc_desired;
267                 acc_desired = 0;
268                 DEBUG(3, ("is owner, access allowed\n"));
269
270                 goto done;
271         }
272
273         /* Create group sid */
274
275         if (!gid_to_sid(&group_sid, user->gid)) {
276                 DEBUG(3, ("could not lookup sid for gid %d\n", user->gid));
277                 goto done;
278         }
279
280         sid_to_string(sid_str, &group_sid);
281         DEBUG(3, ("group sid is %s\n", sid_str));
282
283         /* Create array of group sids */
284
285         add_sid_to_array(&ngroup_sids, &group_sids, &group_sid);
286
287         for (i = 0; i < user->ngroups; i++) {
288                 if (user->groups[i] != user->gid) {
289                         if (gid_to_sid(&group_sid, user->groups[i])) {
290
291                                 /* If we're a group member then we can also
292                                    do anything */
293
294                                 if (sid_equal(&group_sid, sd->grp_sid)) {
295                                         *status = NT_STATUS_NOPROBLEMO;
296                                         *acc_granted = acc_desired;
297                                         acc_desired = 0;
298                                         DEBUG(3, ("is group member "
299                                                   "access allowed\n"));
300
301                                         goto done;
302                                 }
303
304                                 add_sid_to_array(&ngroup_sids, &group_sids, 
305                                                  &group_sid);
306                         } else {
307                                 DEBUG(3, ("could not lookup sid for gid %d\n", 
308                                           user->gid));
309                         }
310
311                         sid_to_string(sid_str, &group_sid);
312                         DEBUG(3, ("supplementary group %s\n", sid_str));
313                 }
314         }
315
316         /* ACL must have something in it */
317
318         acl = sd->dacl;
319
320         if (acl == NULL || acl->ace == NULL || acl->num_aces == 0) {
321
322                 /* Checks against a NULL ACL succeed and return access
323                         granted = access requested. */
324
325                 *status = NT_STATUS_NOPROBLEMO;
326                 *acc_granted = acc_desired;
327                 acc_desired = 0;
328                 DEBUG(3, ("null ace, access allowed\n"));
329
330                 goto done;
331         }
332
333         /* Check each ACE in ACL.  We break out of the loop if an ACE is
334            either explicitly denied or explicitly allowed by the
335            check_ace2() function.  We also check the Access Denied ACEs
336            before Access allowed ones as the Platform SDK documentation is
337            unclear whether ACEs in a ACL are necessarily always in this
338            order.  See the discussion on "Order of ACEs in a DACL" in
339            MSDN. */
340
341         check_ace_type = SEC_ACE_TYPE_ACCESS_DENIED;
342
343     check_aces:
344
345         for (i = 0; i < acl->num_aces; i++) {
346                 SEC_ACE *ace = &acl->ace[i];
347                 BOOL is_group_owner;
348
349                 /* Check user sid */
350
351                 if (ace->type == check_ace_type &&
352                     check_ace(ace, False, &user_sid, &acc_desired,
353                               acc_granted, status)) {
354                         goto done;
355                 }
356
357                 /* Check group sids */
358
359                 for (j = 0; j < ngroup_sids; j++) {
360
361                         is_group_owner = sd->grp_sid ? 
362                                 sid_equal(group_sids[j], sd->grp_sid) : False;
363
364                         if (ace->type == check_ace_type &&
365                             check_ace(ace, is_group_owner, group_sids[j], 
366                                       &acc_desired, acc_granted, status)) {
367                                 goto done;
368                         }
369                 }
370         }
371
372         /* Check access allowed ACEs */
373
374         if (check_ace_type == SEC_ACE_TYPE_ACCESS_DENIED) {
375                 check_ace_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
376                 goto check_aces;
377         }
378
379  done:
380
381         free_sid_array(ngroup_sids, group_sids);
382         
383         /* If any access desired bits are still on, return access denied
384            and turn off any bits already granted. */
385
386         if (acc_desired) {
387                 *acc_granted = 0;
388                 *status = NT_STATUS_ACCESS_DENIED;
389         }
390
391         return *status == NT_STATUS_NOPROBLEMO;
392 }