• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/libcli/security/
1/*
2   Unix SMB/CIFS implementation.
3
4   security descriptror utility functions
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 3 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, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "libcli/security/security_descriptor.h"
24#include "libcli/security/dom_sid.h"
25
26/*
27  return a blank security descriptor (no owners, dacl or sacl)
28*/
29struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx)
30{
31	struct security_descriptor *sd;
32
33	sd = talloc(mem_ctx, struct security_descriptor);
34	if (!sd) {
35		return NULL;
36	}
37
38	sd->revision = SD_REVISION;
39	/* we mark as self relative, even though it isn't while it remains
40	   a pointer in memory because this simplifies the ndr code later.
41	   All SDs that we store/emit are in fact SELF_RELATIVE
42	*/
43	sd->type = SEC_DESC_SELF_RELATIVE;
44
45	sd->owner_sid = NULL;
46	sd->group_sid = NULL;
47	sd->sacl = NULL;
48	sd->dacl = NULL;
49
50	return sd;
51}
52
53struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx,
54					     const struct security_acl *oacl)
55{
56	struct security_acl *nacl;
57
58	nacl = talloc (mem_ctx, struct security_acl);
59	if (nacl == NULL) {
60		return NULL;
61	}
62
63	nacl->aces = (struct security_ace *)talloc_memdup (nacl, oacl->aces, sizeof(struct security_ace) * oacl->num_aces);
64	if ((nacl->aces == NULL) && (oacl->num_aces > 0)) {
65		goto failed;
66	}
67
68	nacl->revision = oacl->revision;
69	nacl->size = oacl->size;
70	nacl->num_aces = oacl->num_aces;
71
72	return nacl;
73
74 failed:
75	talloc_free (nacl);
76	return NULL;
77
78}
79
80struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx,
81                                              const struct security_acl *acl1,
82                                              const struct security_acl *acl2)
83{
84        struct security_acl *nacl;
85        int i;
86
87        if (!acl1 && !acl2)
88                return NULL;
89
90        if (!acl1){
91                nacl = security_acl_dup(mem_ctx, acl2);
92                return nacl;
93        }
94
95        if (!acl2){
96                nacl = security_acl_dup(mem_ctx, acl1);
97                return nacl;
98        }
99
100        nacl = talloc (mem_ctx, struct security_acl);
101        if (nacl == NULL) {
102                return NULL;
103        }
104
105        nacl->revision = acl1->revision;
106        nacl->size = acl1->size + acl2->size;
107        nacl->num_aces = acl1->num_aces + acl2->num_aces;
108
109        if (nacl->num_aces == 0)
110                return nacl;
111
112        nacl->aces = (struct security_ace *)talloc_array (mem_ctx, struct security_ace, acl1->num_aces+acl2->num_aces);
113        if ((nacl->aces == NULL) && (nacl->num_aces > 0)) {
114                goto failed;
115        }
116
117        for (i = 0; i < acl1->num_aces; i++)
118                nacl->aces[i] = acl1->aces[i];
119        for (i = 0; i < acl2->num_aces; i++)
120                nacl->aces[i + acl1->num_aces] = acl2->aces[i];
121
122        return nacl;
123
124 failed:
125        talloc_free (nacl);
126        return NULL;
127
128}
129
130/*
131   talloc and copy a security descriptor
132 */
133struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx,
134						     const struct security_descriptor *osd)
135{
136	struct security_descriptor *nsd;
137
138	nsd = talloc_zero(mem_ctx, struct security_descriptor);
139	if (!nsd) {
140		return NULL;
141	}
142
143	if (osd->owner_sid) {
144		nsd->owner_sid = dom_sid_dup(nsd, osd->owner_sid);
145		if (nsd->owner_sid == NULL) {
146			goto failed;
147		}
148	}
149
150	if (osd->group_sid) {
151		nsd->group_sid = dom_sid_dup(nsd, osd->group_sid);
152		if (nsd->group_sid == NULL) {
153			goto failed;
154		}
155	}
156
157	if (osd->sacl) {
158		nsd->sacl = security_acl_dup(nsd, osd->sacl);
159		if (nsd->sacl == NULL) {
160			goto failed;
161		}
162	}
163
164	if (osd->dacl) {
165		nsd->dacl = security_acl_dup(nsd, osd->dacl);
166		if (nsd->dacl == NULL) {
167			goto failed;
168		}
169	}
170
171	nsd->revision = osd->revision;
172	nsd->type = osd->type;
173
174	return nsd;
175
176 failed:
177	talloc_free(nsd);
178
179	return NULL;
180}
181
182/*
183  add an ACE to an ACL of a security_descriptor
184*/
185
186static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
187					    bool add_to_sacl,
188					    const struct security_ace *ace)
189{
190	struct security_acl *acl = NULL;
191
192	if (add_to_sacl) {
193		acl = sd->sacl;
194	} else {
195		acl = sd->dacl;
196	}
197
198	if (acl == NULL) {
199		acl = talloc(sd, struct security_acl);
200		if (acl == NULL) {
201			return NT_STATUS_NO_MEMORY;
202		}
203		acl->revision = SECURITY_ACL_REVISION_NT4;
204		acl->size     = 0;
205		acl->num_aces = 0;
206		acl->aces     = NULL;
207	}
208
209	acl->aces = talloc_realloc(acl, acl->aces,
210				   struct security_ace, acl->num_aces+1);
211	if (acl->aces == NULL) {
212		return NT_STATUS_NO_MEMORY;
213	}
214
215	acl->aces[acl->num_aces] = *ace;
216
217	switch (acl->aces[acl->num_aces].type) {
218	case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
219	case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
220	case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
221	case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
222		acl->revision = SECURITY_ACL_REVISION_ADS;
223		break;
224	default:
225		break;
226	}
227
228	acl->num_aces++;
229
230	if (add_to_sacl) {
231		sd->sacl = acl;
232		sd->type |= SEC_DESC_SACL_PRESENT;
233	} else {
234		sd->dacl = acl;
235		sd->type |= SEC_DESC_DACL_PRESENT;
236	}
237
238	return NT_STATUS_OK;
239}
240
241/*
242  add an ACE to the SACL of a security_descriptor
243*/
244
245NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd,
246				      const struct security_ace *ace)
247{
248	return security_descriptor_acl_add(sd, true, ace);
249}
250
251/*
252  add an ACE to the DACL of a security_descriptor
253*/
254
255NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd,
256				      const struct security_ace *ace)
257{
258	return security_descriptor_acl_add(sd, false, ace);
259}
260
261/*
262  delete the ACE corresponding to the given trustee in an ACL of a
263  security_descriptor
264*/
265
266static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd,
267					    bool sacl_del,
268					    const struct dom_sid *trustee)
269{
270	int i;
271	bool found = false;
272	struct security_acl *acl = NULL;
273
274	if (sacl_del) {
275		acl = sd->sacl;
276	} else {
277		acl = sd->dacl;
278	}
279
280	if (acl == NULL) {
281		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
282	}
283
284	/* there can be multiple ace's for one trustee */
285	for (i=0;i<acl->num_aces;i++) {
286		if (dom_sid_equal(trustee, &acl->aces[i].trustee)) {
287			memmove(&acl->aces[i], &acl->aces[i+1],
288				sizeof(acl->aces[i]) * (acl->num_aces - (i+1)));
289			acl->num_aces--;
290			if (acl->num_aces == 0) {
291				acl->aces = NULL;
292			}
293			found = true;
294		}
295	}
296
297	if (!found) {
298		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
299	}
300
301	acl->revision = SECURITY_ACL_REVISION_NT4;
302
303	for (i=0;i<acl->num_aces;i++) {
304		switch (acl->aces[i].type) {
305		case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
306		case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
307		case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
308		case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
309			acl->revision = SECURITY_ACL_REVISION_ADS;
310			return NT_STATUS_OK;
311		default:
312			break; /* only for the switch statement */
313		}
314	}
315
316	return NT_STATUS_OK;
317}
318
319/*
320  delete the ACE corresponding to the given trustee in the DACL of a
321  security_descriptor
322*/
323
324NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd,
325				      const struct dom_sid *trustee)
326{
327	return security_descriptor_acl_del(sd, false, trustee);
328}
329
330/*
331  delete the ACE corresponding to the given trustee in the SACL of a
332  security_descriptor
333*/
334
335NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd,
336				      const struct dom_sid *trustee)
337{
338	return security_descriptor_acl_del(sd, true, trustee);
339}
340
341/*
342  compare two security ace structures
343*/
344bool security_ace_equal(const struct security_ace *ace1,
345			const struct security_ace *ace2)
346{
347	if (ace1 == ace2) return true;
348	if (!ace1 || !ace2) return false;
349	if (ace1->type != ace2->type) return false;
350	if (ace1->flags != ace2->flags) return false;
351	if (ace1->access_mask != ace2->access_mask) return false;
352	if (!dom_sid_equal(&ace1->trustee, &ace2->trustee)) return false;
353
354	return true;
355}
356
357
358/*
359  compare two security acl structures
360*/
361bool security_acl_equal(const struct security_acl *acl1,
362			const struct security_acl *acl2)
363{
364	int i;
365
366	if (acl1 == acl2) return true;
367	if (!acl1 || !acl2) return false;
368	if (acl1->revision != acl2->revision) return false;
369	if (acl1->num_aces != acl2->num_aces) return false;
370
371	for (i=0;i<acl1->num_aces;i++) {
372		if (!security_ace_equal(&acl1->aces[i], &acl2->aces[i])) return false;
373	}
374	return true;
375}
376
377/*
378  compare two security descriptors.
379*/
380bool security_descriptor_equal(const struct security_descriptor *sd1,
381			       const struct security_descriptor *sd2)
382{
383	if (sd1 == sd2) return true;
384	if (!sd1 || !sd2) return false;
385	if (sd1->revision != sd2->revision) return false;
386	if (sd1->type != sd2->type) return false;
387
388	if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false;
389	if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false;
390	if (!security_acl_equal(sd1->sacl, sd2->sacl))      return false;
391	if (!security_acl_equal(sd1->dacl, sd2->dacl))      return false;
392
393	return true;
394}
395
396/*
397  compare two security descriptors, but allow certain (missing) parts
398  to be masked out of the comparison
399*/
400bool security_descriptor_mask_equal(const struct security_descriptor *sd1,
401				    const struct security_descriptor *sd2,
402				    uint32_t mask)
403{
404	if (sd1 == sd2) return true;
405	if (!sd1 || !sd2) return false;
406	if (sd1->revision != sd2->revision) return false;
407	if ((sd1->type & mask) != (sd2->type & mask)) return false;
408
409	if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false;
410	if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false;
411	if ((mask & SEC_DESC_DACL_PRESENT) && !security_acl_equal(sd1->dacl, sd2->dacl))      return false;
412	if ((mask & SEC_DESC_SACL_PRESENT) && !security_acl_equal(sd1->sacl, sd2->sacl))      return false;
413
414	return true;
415}
416
417
418static struct security_descriptor *security_descriptor_appendv(struct security_descriptor *sd,
419							       bool add_ace_to_sacl,
420							       va_list ap)
421{
422	const char *sidstr;
423
424	while ((sidstr = va_arg(ap, const char *))) {
425		struct dom_sid *sid;
426		struct security_ace *ace = talloc_zero(sd, struct security_ace);
427		NTSTATUS status;
428
429		if (ace == NULL) {
430			talloc_free(sd);
431			return NULL;
432		}
433		ace->type = va_arg(ap, unsigned int);
434		ace->access_mask = va_arg(ap, unsigned int);
435		ace->flags = va_arg(ap, unsigned int);
436		sid = dom_sid_parse_talloc(ace, sidstr);
437		if (sid == NULL) {
438			talloc_free(sd);
439			return NULL;
440		}
441		ace->trustee = *sid;
442		if (add_ace_to_sacl) {
443			status = security_descriptor_sacl_add(sd, ace);
444		} else {
445			status = security_descriptor_dacl_add(sd, ace);
446		}
447		/* TODO: check: would talloc_free(ace) here be correct? */
448		if (!NT_STATUS_IS_OK(status)) {
449			talloc_free(sd);
450			return NULL;
451		}
452	}
453
454	return sd;
455}
456
457struct security_descriptor *security_descriptor_append(struct security_descriptor *sd,
458						       ...)
459{
460	va_list ap;
461
462	va_start(ap, sd);
463	sd = security_descriptor_appendv(sd, false, ap);
464	va_end(ap);
465
466	return sd;
467}
468
469static struct security_descriptor *security_descriptor_createv(TALLOC_CTX *mem_ctx,
470							       uint16_t sd_type,
471							       const char *owner_sid,
472							       const char *group_sid,
473							       bool add_ace_to_sacl,
474							       va_list ap)
475{
476	struct security_descriptor *sd;
477
478	sd = security_descriptor_initialise(mem_ctx);
479	if (sd == NULL) {
480		return NULL;
481	}
482
483	sd->type |= sd_type;
484
485	if (owner_sid) {
486		sd->owner_sid = dom_sid_parse_talloc(sd, owner_sid);
487		if (sd->owner_sid == NULL) {
488			talloc_free(sd);
489			return NULL;
490		}
491	}
492	if (group_sid) {
493		sd->group_sid = dom_sid_parse_talloc(sd, group_sid);
494		if (sd->group_sid == NULL) {
495			talloc_free(sd);
496			return NULL;
497		}
498	}
499
500	return security_descriptor_appendv(sd, add_ace_to_sacl, ap);
501}
502
503/*
504  create a security descriptor using string SIDs. This is used by the
505  torture code to allow the easy creation of complex ACLs
506  This is a varargs function. The list of DACL ACEs ends with a NULL sid.
507
508  Each ACE contains a set of 4 parameters:
509  SID, ACCESS_TYPE, MASK, FLAGS
510
511  a typical call would be:
512
513    sd = security_descriptor_dacl_create(mem_ctx,
514                                         sd_type_flags,
515                                         mysid,
516                                         mygroup,
517                                         SID_NT_AUTHENTICATED_USERS,
518                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
519                                         SEC_FILE_ALL,
520                                         SEC_ACE_FLAG_OBJECT_INHERIT,
521                                         NULL);
522  that would create a sd with one DACL ACE
523*/
524
525struct security_descriptor *security_descriptor_dacl_create(TALLOC_CTX *mem_ctx,
526							    uint16_t sd_type,
527							    const char *owner_sid,
528							    const char *group_sid,
529							    ...)
530{
531	struct security_descriptor *sd = NULL;
532	va_list ap;
533	va_start(ap, group_sid);
534	sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid,
535					 group_sid, false, ap);
536	va_end(ap);
537
538	return sd;
539}
540
541struct security_descriptor *security_descriptor_sacl_create(TALLOC_CTX *mem_ctx,
542							    uint16_t sd_type,
543							    const char *owner_sid,
544							    const char *group_sid,
545							    ...)
546{
547	struct security_descriptor *sd = NULL;
548	va_list ap;
549	va_start(ap, group_sid);
550	sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid,
551					 group_sid, true, ap);
552	va_end(ap);
553
554	return sd;
555}
556
557struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx,
558					 const char *sid_str,
559					 enum security_ace_type type,
560					 uint32_t access_mask,
561					 uint8_t flags)
562
563{
564	struct dom_sid *sid;
565	struct security_ace *ace;
566
567	ace = talloc_zero(mem_ctx, struct security_ace);
568	if (ace == NULL) {
569		return NULL;
570	}
571
572	sid = dom_sid_parse_talloc(ace, sid_str);
573	if (sid == NULL) {
574		talloc_free(ace);
575		return NULL;
576	}
577
578	ace->trustee = *sid;
579	ace->type = type;
580	ace->access_mask = access_mask;
581	ace->flags = flags;
582
583	return ace;
584}
585