r4403: - added ACL inheritance in the pvfs backend. ACLs are now inherited on
[samba.git] / source / 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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25
26
27 /*
28   check if a sid is in the supplied token
29 */
30 static BOOL sid_active_in_token(const struct dom_sid *sid, 
31                                 const struct security_token *token)
32 {
33         int i;
34         for (i=0;i<token->num_sids;i++) {
35                 if (dom_sid_equal(sid, token->sids[i])) {
36                         return True;
37                 }
38         }
39         return False;
40 }
41
42
43 /*
44   perform a SEC_FLAG_MAXIMUM_ALLOWED access check
45 */
46 static uint32_t access_check_max_allowed(const struct security_descriptor *sd, 
47                                          const struct security_token *token)
48 {
49         uint32_t denied = 0, granted = 0;
50         unsigned i;
51         
52         if (sid_active_in_token(sd->owner_sid, token)) {
53                 granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL;
54         }
55         if (sec_privilege_check(token, SEC_PRIV_RESTORE)) {
56                 granted |= SEC_STD_DELETE;
57         }
58
59         for (i = 0;i<sd->dacl->num_aces; i++) {
60                 struct security_ace *ace = &sd->dacl->aces[i];
61
62                 if (!sid_active_in_token(&ace->trustee, token)) {
63                         continue;
64                 }
65
66                 switch (ace->type) {
67                         case SEC_ACE_TYPE_ACCESS_ALLOWED:
68                                 granted |= ace->access_mask;
69                                 break;
70                         case SEC_ACE_TYPE_ACCESS_DENIED:
71                         case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
72                                 denied |= ace->access_mask;
73                                 break;
74                 }
75         }
76
77         return granted & ~denied;
78 }
79
80 /*
81   the main entry point for access checking. 
82 */
83 NTSTATUS sec_access_check(const struct security_descriptor *sd, 
84                           const struct security_token *token,
85                           uint32_t access_desired,
86                           uint32_t *access_granted)
87 {
88         int i;
89         uint32_t bits_remaining;
90
91         *access_granted = access_desired;
92         bits_remaining = access_desired;
93
94         /* handle the maximum allowed flag */
95         if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
96                 access_desired |= access_check_max_allowed(sd, token);
97                 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
98                 *access_granted = access_desired;
99                 bits_remaining = access_desired & ~SEC_STD_DELETE;
100         }
101
102         if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
103                 if (sec_privilege_check(token, SEC_PRIV_SECURITY)) {
104                         bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
105                 } else {
106                         return NT_STATUS_ACCESS_DENIED;
107                 }
108         }
109
110         /* dacl not present allows access */
111         if (!(sd->type & SEC_DESC_DACL_PRESENT)) {
112                 *access_granted = access_desired;
113                 return NT_STATUS_OK;
114         }
115
116         /* empty dacl denies access */
117         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
118                 return NT_STATUS_ACCESS_DENIED;
119         }
120
121         /* the owner always gets SEC_STD_WRITE_DAC & SEC_STD_READ_CONTROL */
122         if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
123             sid_active_in_token(sd->owner_sid, token)) {
124                 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
125         }
126         if ((bits_remaining & SEC_STD_DELETE) &&
127             sec_privilege_check(token, SEC_PRIV_RESTORE)) {
128                 bits_remaining &= ~SEC_STD_DELETE;
129         }
130
131         /* check each ace in turn. */
132         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
133                 struct security_ace *ace = &sd->dacl->aces[i];
134
135                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
136                         continue;
137                 }
138
139                 if (!sid_active_in_token(&ace->trustee, token)) {
140                         continue;
141                 }
142
143                 switch (ace->type) {
144                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
145                         bits_remaining &= ~ace->access_mask;
146                         break;
147                 case SEC_ACE_TYPE_ACCESS_DENIED:
148                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
149                         if (bits_remaining & ace->access_mask) {
150                                 return NT_STATUS_ACCESS_DENIED;
151                         }
152                         break;
153                 }
154         }
155
156         if (bits_remaining != 0) {
157                 return NT_STATUS_ACCESS_DENIED;
158         }
159
160         return NT_STATUS_OK;
161 }