Initial import
[samba] / source / lib / secace.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  SEC_ACE handling functions
4  *  Copyright (C) Andrew Tridgell              1992-1998,
5  *  Copyright (C) Jeremy R. Allison            1995-2003.
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7  *  Copyright (C) Paul Ashton                  1997-1998.
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "includes.h"
25
26 /*******************************************************************
27  Check if ACE has OBJECT type.
28 ********************************************************************/
29
30 BOOL sec_ace_object(uint8 type)
31 {
32         if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
33             type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
34             type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
35             type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
36                 return True;
37         }
38         return False;
39 }
40
41 /*******************************************************************
42  copy a SEC_ACE structure.
43 ********************************************************************/
44 void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
45 {
46         ace_dest->type  = ace_src->type;
47         ace_dest->flags = ace_src->flags;
48         ace_dest->size  = ace_src->size;
49         ace_dest->info.mask = ace_src->info.mask;
50         ace_dest->obj_flags = ace_src->obj_flags;
51         memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, sizeof(struct uuid));
52         memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, sizeof(struct uuid));
53         sid_copy(&ace_dest->trustee, &ace_src->trustee);
54 }
55
56 /*******************************************************************
57  Sets up a SEC_ACE structure.
58 ********************************************************************/
59
60 void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
61 {
62         t->type = type;
63         t->flags = flag;
64         t->size = sid_size(sid) + 8;
65         t->info = mask;
66
67         ZERO_STRUCTP(&t->trustee);
68         sid_copy(&t->trustee, sid);
69 }
70
71 /*******************************************************************
72  adds new SID with its permissions to ACE list
73 ********************************************************************/
74
75 NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask)
76 {
77         unsigned int i = 0;
78         
79         if (!ctx || !pp_new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
80
81         *num += 1;
82         
83         if((pp_new[0] = TALLOC_ZERO_ARRAY(ctx, SEC_ACE, *num )) == 0)
84                 return NT_STATUS_NO_MEMORY;
85
86         for (i = 0; i < *num - 1; i ++)
87                 sec_ace_copy(&(*pp_new)[i], &old[i]);
88
89         (*pp_new)[i].type  = 0;
90         (*pp_new)[i].flags = 0;
91         (*pp_new)[i].size  = SEC_ACE_HEADER_SIZE + sid_size(sid);
92         (*pp_new)[i].info.mask = mask;
93         sid_copy(&(*pp_new)[i].trustee, sid);
94         return NT_STATUS_OK;
95 }
96
97 /*******************************************************************
98   modify SID's permissions at ACL 
99 ********************************************************************/
100
101 NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask)
102 {
103         unsigned int i = 0;
104
105         if (!ace || !sid)  return NT_STATUS_INVALID_PARAMETER;
106
107         for (i = 0; i < num; i ++) {
108                 if (sid_compare(&ace[i].trustee, sid) == 0) {
109                         ace[i].info.mask = mask;
110                         return NT_STATUS_OK;
111                 }
112         }
113         return NT_STATUS_NOT_FOUND;
114 }
115
116 /*******************************************************************
117  delete SID from ACL
118 ********************************************************************/
119
120 NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, uint32 *num, DOM_SID *sid)
121 {
122         unsigned int i     = 0;
123         unsigned int n_del = 0;
124
125         if (!ctx || !pp_new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
126
127         if((pp_new[0] = TALLOC_ZERO_ARRAY(ctx, SEC_ACE, *num )) == 0)
128                 return NT_STATUS_NO_MEMORY;
129
130         for (i = 0; i < *num; i ++) {
131                 if (sid_compare(&old[i].trustee, sid) != 0)
132                         sec_ace_copy(&(*pp_new)[i], &old[i]);
133                 else
134                         n_del ++;
135         }
136         if (n_del == 0)
137                 return NT_STATUS_NOT_FOUND;
138         else {
139                 *num -= n_del;
140                 return NT_STATUS_OK;
141         }
142 }
143
144 /*******************************************************************
145  Compares two SEC_ACE structures
146 ********************************************************************/
147
148 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
149 {
150         /* Trivial case */
151
152         if (!s1 && !s2) return True;
153
154         /* Check top level stuff */
155
156         if (s1->type != s2->type || s1->flags != s2->flags ||
157             s1->info.mask != s2->info.mask) {
158                 return False;
159         }
160
161         /* Check SID */
162
163         if (!sid_equal(&s1->trustee, &s2->trustee)) {
164                 return False;
165         }
166
167         return True;
168 }
169
170 int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2)
171 {
172         int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE;
173         int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE;
174
175         if (a1_inh == a2_inh)
176                 return 0;
177
178         if (!a1_inh && a2_inh)
179                 return -1;
180         return 1;
181 }
182
183 /*******************************************************************
184   Comparison function to apply the order explained below in a group.
185 *******************************************************************/
186
187 int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2)
188 {
189         if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
190                                 (a2->type != SEC_ACE_TYPE_ACCESS_DENIED))
191                 return -1;
192
193         if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
194                                 (a1->type != SEC_ACE_TYPE_ACCESS_DENIED))
195                 return 1;
196
197         /* Both access denied or access allowed. */
198
199         /* 1. ACEs that apply to the object itself */
200
201         if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
202                         (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY))
203                 return -1;
204         else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
205                         (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY))
206                 return 1;
207
208         /* 2. ACEs that apply to a subobject of the object, such as
209          * a property set or property. */
210
211         if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
212                         !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
213                 return -1;
214         else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
215                         !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
216                 return 1;
217
218         return 0;
219 }
220
221 /*******************************************************************
222  Functions to convert a SEC_DESC ACE DACL list into canonical order.
223  JRA.
224
225 --- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
226
227 The following describes the preferred order:
228
229  To ensure that noninherited ACEs have precedence over inherited ACEs,
230  place all noninherited ACEs in a group before any inherited ACEs.
231  This ordering ensures, for example, that a noninherited access-denied ACE
232  is enforced regardless of any inherited ACE that allows access.
233
234  Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows:
235         1. Access-denied ACEs that apply to the object itself
236         2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property
237         3. Access-allowed ACEs that apply to the object itself
238         4. Access-allowed ACEs that apply to a subobject of the object"
239
240 ********************************************************************/
241
242 void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces)
243 {
244         unsigned int i;
245
246         if (!srclist || num_aces == 0)
247                 return;
248
249         /* Sort so that non-inherited ACE's come first. */
250         qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp);
251
252         /* Find the boundary between non-inherited ACEs. */
253         for (i = 0; i < num_aces; i++ ) {
254                 SEC_ACE *curr_ace = &srclist[i];
255
256                 if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
257                         break;
258         }
259
260         /* i now points at entry number of the first inherited ACE. */
261
262         /* Sort the non-inherited ACEs. */
263         if (i)
264                 qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
265
266         /* Now sort the inherited ACEs. */
267         if (num_aces - i)
268                 qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
269 }
270
271 /*******************************************************************
272  Check if this ACE has a SID in common with the token.
273 ********************************************************************/
274
275 BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
276 {
277         size_t i;
278
279         for (i = 0; i < token->num_sids; i++) {
280                 if (sid_equal(&ace->trustee, &token->user_sids[i]))
281                         return True;
282         }
283
284         return False;
285 }