source: trunk/samba-3.0.25pre1/source/lib/secdesc.c@ 5

Last change on this file since 5 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 14.0 KB
Line 
1/*
2 * Unix SMB/Netbios implementation.
3 * SEC_DESC 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/* Map generic permissions to file object specific permissions */
27
28struct generic_mapping file_generic_mapping = {
29 FILE_GENERIC_READ,
30 FILE_GENERIC_WRITE,
31 FILE_GENERIC_EXECUTE,
32 FILE_GENERIC_ALL
33};
34
35/*******************************************************************
36 Works out the linearization size of a SEC_DESC.
37********************************************************************/
38
39size_t sec_desc_size(SEC_DESC *psd)
40{
41 size_t offset;
42
43 if (!psd) return 0;
44
45 offset = SEC_DESC_HEADER_SIZE;
46
47 /* don't align */
48
49 if (psd->owner_sid != NULL)
50 offset += sid_size(psd->owner_sid);
51
52 if (psd->group_sid != NULL)
53 offset += sid_size(psd->group_sid);
54
55 if (psd->sacl != NULL)
56 offset += psd->sacl->size;
57
58 if (psd->dacl != NULL)
59 offset += psd->dacl->size;
60
61 return offset;
62}
63
64/*******************************************************************
65 Compares two SEC_DESC structures
66********************************************************************/
67
68BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
69{
70 /* Trivial case */
71
72 if (!s1 && !s2) {
73 goto done;
74 }
75
76 if (!s1 || !s2) {
77 return False;
78 }
79
80 /* Check top level stuff */
81
82 if (s1->revision != s2->revision) {
83 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
84 s1->revision, s2->revision));
85 return False;
86 }
87
88 if (s1->type!= s2->type) {
89 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
90 s1->type, s2->type));
91 return False;
92 }
93
94 /* Check owner and group */
95
96 if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
97 fstring str1, str2;
98
99 sid_to_string(str1, s1->owner_sid);
100 sid_to_string(str2, s2->owner_sid);
101
102 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
103 str1, str2));
104 return False;
105 }
106
107 if (!sid_equal(s1->group_sid, s2->group_sid)) {
108 fstring str1, str2;
109
110 sid_to_string(str1, s1->group_sid);
111 sid_to_string(str2, s2->group_sid);
112
113 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
114 str1, str2));
115 return False;
116 }
117
118 /* Check ACLs present in one but not the other */
119
120 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
121 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
122 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
123 return False;
124 }
125
126 /* Sigh - we have to do it the hard way by iterating over all
127 the ACEs in the ACLs */
128
129 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
130 !sec_acl_equal(s1->sacl, s2->sacl)) {
131 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
132 return False;
133 }
134
135 done:
136 DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
137 return True;
138}
139
140/*******************************************************************
141 Merge part of security descriptor old_sec in to the empty sections of
142 security descriptor new_sec.
143********************************************************************/
144
145SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
146{
147 DOM_SID *owner_sid, *group_sid;
148 SEC_DESC_BUF *return_sdb;
149 SEC_ACL *dacl, *sacl;
150 SEC_DESC *psd = NULL;
151 uint16 secdesc_type;
152 size_t secdesc_size;
153
154 /* Copy over owner and group sids. There seems to be no flag for
155 this so just check the pointer values. */
156
157 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
158 old_sdb->sec->owner_sid;
159
160 group_sid = new_sdb->sec->group_sid ? new_sdb->sec->group_sid :
161 old_sdb->sec->group_sid;
162
163 secdesc_type = new_sdb->sec->type;
164
165 /* Ignore changes to the system ACL. This has the effect of making
166 changes through the security tab audit button not sticking.
167 Perhaps in future Samba could implement these settings somehow. */
168
169 sacl = NULL;
170 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
171
172 /* Copy across discretionary ACL */
173
174 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
175 dacl = new_sdb->sec->dacl;
176 } else {
177 dacl = old_sdb->sec->dacl;
178 }
179
180 /* Create new security descriptor from bits */
181
182 psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type,
183 owner_sid, group_sid, sacl, dacl, &secdesc_size);
184
185 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
186
187 return(return_sdb);
188}
189
190/*******************************************************************
191 Creates a SEC_DESC structure
192********************************************************************/
193
194SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
195 const DOM_SID *owner_sid, const DOM_SID *group_sid,
196 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
197{
198 SEC_DESC *dst;
199 uint32 offset = 0;
200
201 *sd_size = 0;
202
203 if(( dst = TALLOC_ZERO_P(ctx, SEC_DESC)) == NULL)
204 return NULL;
205
206 dst->revision = revision;
207 dst->type = type;
208
209 if (sacl)
210 dst->type |= SEC_DESC_SACL_PRESENT;
211 if (dacl)
212 dst->type |= SEC_DESC_DACL_PRESENT;
213
214 dst->off_owner_sid = 0;
215 dst->off_grp_sid = 0;
216 dst->off_sacl = 0;
217 dst->off_dacl = 0;
218
219 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
220 goto error_exit;
221
222 if(group_sid && ((dst->group_sid = sid_dup_talloc(ctx,group_sid)) == NULL))
223 goto error_exit;
224
225 if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
226 goto error_exit;
227
228 if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
229 goto error_exit;
230
231 offset = SEC_DESC_HEADER_SIZE;
232
233 /*
234 * Work out the linearization sizes.
235 */
236
237 if (dst->sacl != NULL) {
238 dst->off_sacl = offset;
239 offset += dst->sacl->size;
240 }
241 if (dst->dacl != NULL) {
242 dst->off_dacl = offset;
243 offset += dst->dacl->size;
244 }
245
246 if (dst->owner_sid != NULL) {
247 dst->off_owner_sid = offset;
248 offset += sid_size(dst->owner_sid);
249 }
250
251 if (dst->group_sid != NULL) {
252 dst->off_grp_sid = offset;
253 offset += sid_size(dst->group_sid);
254 }
255
256 *sd_size = (size_t)offset;
257 return dst;
258
259error_exit:
260
261 *sd_size = 0;
262 return NULL;
263}
264
265/*******************************************************************
266 Duplicate a SEC_DESC structure.
267********************************************************************/
268
269SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
270{
271 size_t dummy;
272
273 if(src == NULL)
274 return NULL;
275
276 return make_sec_desc( ctx, src->revision, src->type,
277 src->owner_sid, src->group_sid, src->sacl,
278 src->dacl, &dummy);
279}
280
281/*******************************************************************
282 Creates a SEC_DESC structure with typical defaults.
283********************************************************************/
284
285SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *group_sid,
286 SEC_ACL *dacl, size_t *sd_size)
287{
288 return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
289 owner_sid, group_sid, NULL, dacl, sd_size);
290}
291
292/*******************************************************************
293 Creates a SEC_DESC_BUF structure.
294********************************************************************/
295
296SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
297{
298 SEC_DESC_BUF *dst;
299
300 if((dst = TALLOC_ZERO_P(ctx, SEC_DESC_BUF)) == NULL)
301 return NULL;
302
303 /* max buffer size (allocated size) */
304 dst->max_len = (uint32)len;
305 dst->len = (uint32)len;
306
307 if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
308 return NULL;
309 }
310
311 dst->ptr = 0x1;
312
313 return dst;
314}
315
316/*******************************************************************
317 Duplicates a SEC_DESC_BUF structure.
318********************************************************************/
319
320SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
321{
322 if(src == NULL)
323 return NULL;
324
325 return make_sec_desc_buf( ctx, src->len, src->sec);
326}
327
328/*******************************************************************
329 Add a new SID with its permissions to SEC_DESC.
330********************************************************************/
331
332NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
333{
334 SEC_DESC *sd = 0;
335 SEC_ACL *dacl = 0;
336 SEC_ACE *ace = 0;
337 NTSTATUS status;
338
339 if (!ctx || !psd || !sid || !sd_size)
340 return NT_STATUS_INVALID_PARAMETER;
341
342 *sd_size = 0;
343
344 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
345
346 if (!NT_STATUS_IS_OK(status))
347 return status;
348
349 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
350 return NT_STATUS_UNSUCCESSFUL;
351
352 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
353 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
354 return NT_STATUS_UNSUCCESSFUL;
355
356 *psd = sd;
357 sd = 0;
358 return NT_STATUS_OK;
359}
360
361/*******************************************************************
362 Modify a SID's permissions in a SEC_DESC.
363********************************************************************/
364
365NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
366{
367 NTSTATUS status;
368
369 if (!sd || !sid)
370 return NT_STATUS_INVALID_PARAMETER;
371
372 status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
373
374 if (!NT_STATUS_IS_OK(status))
375 return status;
376
377 return NT_STATUS_OK;
378}
379
380/*******************************************************************
381 Delete a SID from a SEC_DESC.
382********************************************************************/
383
384NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
385{
386 SEC_DESC *sd = 0;
387 SEC_ACL *dacl = 0;
388 SEC_ACE *ace = 0;
389 NTSTATUS status;
390
391 if (!ctx || !psd[0] || !sid || !sd_size)
392 return NT_STATUS_INVALID_PARAMETER;
393
394 *sd_size = 0;
395
396 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
397
398 if (!NT_STATUS_IS_OK(status))
399 return status;
400
401 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
402 return NT_STATUS_UNSUCCESSFUL;
403
404 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid,
405 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
406 return NT_STATUS_UNSUCCESSFUL;
407
408 *psd = sd;
409 sd = 0;
410 return NT_STATUS_OK;
411}
412
413/* Create a child security descriptor using another security descriptor as
414 the parent container. This child object can either be a container or
415 non-container object. */
416
417SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
418 BOOL child_container)
419{
420 SEC_DESC_BUF *sdb;
421 SEC_DESC *sd;
422 SEC_ACL *new_dacl, *the_acl;
423 SEC_ACE *new_ace_list = NULL;
424 unsigned int new_ace_list_ndx = 0, i;
425 size_t size;
426
427 /* Currently we only process the dacl when creating the child. The
428 sacl should also be processed but this is left out as sacls are
429 not implemented in Samba at the moment.*/
430
431 the_acl = parent_ctr->dacl;
432
433 if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces)))
434 return NULL;
435
436 for (i = 0; i < the_acl->num_aces; i++) {
437 SEC_ACE *ace = &the_acl->aces[i];
438 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
439 uint8 new_flags = 0;
440 BOOL inherit = False;
441 fstring sid_str;
442
443 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
444 inherited by non-container children objects. Container
445 children objects will inherit it as an INHERIT_ONLY
446 ACE. */
447
448 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
449
450 if (!child_container) {
451 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
452 } else {
453 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
454 }
455
456 inherit = True;
457 }
458
459 /* The CONAINER_INHERIT_ACE flag means all child container
460 objects will inherit and use the ACE. */
461
462 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
463 if (!child_container) {
464 inherit = False;
465 } else {
466 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
467 }
468 }
469
470 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
471 function for the parent container, but is inherited by
472 all child objects as a normal ACE. */
473
474 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
475 /* Move along, nothing to see here */
476 }
477
478 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
479 is inherited by child objects but not grandchildren
480 objects. We clear the object inherit and container
481 inherit flags in the inherited ACE. */
482
483 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
484 new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
485 SEC_ACE_FLAG_CONTAINER_INHERIT);
486 }
487
488 /* Add ACE to ACE list */
489
490 if (!inherit)
491 continue;
492
493 init_sec_access(&new_ace->access_mask, ace->access_mask);
494 init_sec_ace(new_ace, &ace->trustee, ace->type,
495 new_ace->access_mask, new_flags);
496
497 sid_to_string(sid_str, &ace->trustee);
498
499 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
500 " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
501 ace->type, ace->flags, ace->access_mask,
502 sid_str, new_ace->type, new_ace->flags,
503 new_ace->access_mask));
504
505 new_ace_list_ndx++;
506 }
507
508 /* Create child security descriptor to return */
509
510 new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
511
512 /* Use the existing user and group sids. I don't think this is
513 correct. Perhaps the user and group should be passed in as
514 parameters by the caller? */
515
516 sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
517 parent_ctr->owner_sid,
518 parent_ctr->group_sid,
519 parent_ctr->sacl,
520 new_dacl, &size);
521
522 sdb = make_sec_desc_buf(ctx, size, sd);
523
524 return sdb;
525}
526
527/*******************************************************************
528 Sets up a SEC_ACCESS structure.
529********************************************************************/
530
531void init_sec_access(SEC_ACCESS *t, uint32 mask)
532{
533 *t = mask;
534}
Note: See TracBrowser for help on using the repository browser.