r4147: converted from NT_USER_TOKEN to struct security_token
[samba.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 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 | SEC_STD_DELETE;
54         }
55
56         for (i = 0;i<sd->dacl->num_aces; i++) {
57                 struct security_ace *ace = &sd->dacl->aces[i];
58
59                 if (!sid_active_in_token(&ace->trustee, token)) {
60                         continue;
61                 }
62
63                 switch (ace->type) {
64                         case SEC_ACE_TYPE_ACCESS_ALLOWED:
65                                 granted |= ace->access_mask;
66                                 break;
67                         case SEC_ACE_TYPE_ACCESS_DENIED:
68                         case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
69                                 denied |= ace->access_mask;
70                                 break;
71                 }
72         }
73
74         return granted & ~denied;
75 }
76
77 /*
78   the main entry point for access checking. 
79 */
80 NTSTATUS sec_access_check(const struct security_descriptor *sd, 
81                           const struct security_token *token,
82                           uint32_t access_desired,
83                           uint32_t *access_granted)
84 {
85         int i;
86         uint32_t bits_remaining;
87
88         *access_granted = access_desired;
89         bits_remaining = access_desired;
90
91         /* handle the maximum allowed flag */
92         if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
93                 access_desired |= access_check_max_allowed(sd, token);
94                 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
95                 *access_granted = access_desired;
96                 bits_remaining = access_desired & ~SEC_STD_DELETE;
97         }
98
99 #if 0
100         /* this is where we should check for the "system security" privilege, once we 
101            move to the full security_token and not just the nt_user_token */
102         if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
103                 if (privilege_in_token(SE_PRIVILEGE_SYSTEM_SECURITY, token)) {
104                         bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
105                 } else {
106                         return NT_STATUS_ACCESS_DENIED;
107                 }
108         }
109 #endif
110
111         /* dacl not present allows access */
112         if (!(sd->type & SEC_DESC_DACL_PRESENT)) {
113                 *access_granted = access_desired;
114                 return NT_STATUS_OK;
115         }
116
117         /* empty dacl denies access */
118         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
119                 return NT_STATUS_ACCESS_DENIED;
120         }
121
122         /* the owner always gets SEC_STD_WRITE_DAC & SEC_STD_READ_CONTROL */
123         if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
124             sid_active_in_token(sd->owner_sid, token)) {
125                 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
126         }
127
128         /* check each ace in turn. */
129         for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
130                 struct security_ace *ace = &sd->dacl->aces[i];
131
132                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
133                         continue;
134                 }
135
136                 if (!sid_active_in_token(&ace->trustee, token)) {
137                         continue;
138                 }
139
140                 switch (ace->type) {
141                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
142                         bits_remaining &= ~ace->access_mask;
143                         break;
144                 case SEC_ACE_TYPE_ACCESS_DENIED:
145                 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
146                         if (bits_remaining & ace->access_mask) {
147                                 return NT_STATUS_ACCESS_DENIED;
148                         }
149                         break;
150                 }
151         }
152
153         if (bits_remaining != 0) {
154                 return NT_STATUS_ACCESS_DENIED;
155         }
156
157         return NT_STATUS_OK;
158 }