source: branches/samba-3.0/source/lib/secdesc.c@ 158

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

Upgrade source to 3.0.25a

File size: 14.6 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 (the_acl->num_aces) {
434 if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces)))
435 return NULL;
436 } else {
437 new_ace_list = NULL;
438 }
439
440 for (i = 0; i < the_acl->num_aces; i++) {
441 SEC_ACE *ace = &the_acl->aces[i];
442 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
443 uint8 new_flags = 0;
444 BOOL inherit = False;
445 fstring sid_str;
446
447 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
448 inherited by non-container children objects. Container
449 children objects will inherit it as an INHERIT_ONLY
450 ACE. */
451
452 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
453
454 if (!child_container) {
455 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
456 } else {
457 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
458 }
459
460 inherit = True;
461 }
462
463 /* The CONAINER_INHERIT_ACE flag means all child container
464 objects will inherit and use the ACE. */
465
466 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
467 if (!child_container) {
468 inherit = False;
469 } else {
470 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
471 }
472 }
473
474 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
475 function for the parent container, but is inherited by
476 all child objects as a normal ACE. */
477
478 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
479 /* Move along, nothing to see here */
480 }
481
482 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
483 is inherited by child objects but not grandchildren
484 objects. We clear the object inherit and container
485 inherit flags in the inherited ACE. */
486
487 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
488 new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
489 SEC_ACE_FLAG_CONTAINER_INHERIT);
490 }
491
492 /* Add ACE to ACE list */
493
494 if (!inherit)
495 continue;
496
497 init_sec_access(&new_ace->access_mask, ace->access_mask);
498 init_sec_ace(new_ace, &ace->trustee, ace->type,
499 new_ace->access_mask, new_flags);
500
501 sid_to_string(sid_str, &ace->trustee);
502
503 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
504 " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
505 ace->type, ace->flags, ace->access_mask,
506 sid_str, new_ace->type, new_ace->flags,
507 new_ace->access_mask));
508
509 new_ace_list_ndx++;
510 }
511
512 /* Create child security descriptor to return */
513
514 new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
515
516 /* Use the existing user and group sids. I don't think this is
517 correct. Perhaps the user and group should be passed in as
518 parameters by the caller? */
519
520 sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
521 parent_ctr->owner_sid,
522 parent_ctr->group_sid,
523 parent_ctr->sacl,
524 new_dacl, &size);
525
526 sdb = make_sec_desc_buf(ctx, size, sd);
527
528 return sdb;
529}
530
531/*******************************************************************
532 Sets up a SEC_ACCESS structure.
533********************************************************************/
534
535void init_sec_access(SEC_ACCESS *t, uint32 mask)
536{
537 *t = mask;
538}
Note: See TracBrowser for help on using the repository browser.