• 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/source4/libcli/security/
1/*
2   Copyright (C) Nadezhda Ivanova 2009
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 3 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 *  Name: create_descriptor
20 *
21 *  Component: routines for calculating and creating security descriptors
22 *  as described in MS-DTYP 2.5.2.2
23 *
24 *  Description:
25 *
26 *
27 *  Author: Nadezhda Ivanova
28 */
29#include "includes.h"
30#include "libcli/security/security.h"
31
32/* Todos:
33 * build the security token dacl as follows:
34 * SYSTEM: GA, OWNER: GA, LOGIN_SID:GW|GE
35 * Need session id information for the login SID. Probably
36 * the best place for this is during token creation
37 *
38 * Implement SD Invariants
39 * ACE sorting rules
40 * LDAP_SERVER_SD_FLAGS_OID control
41 * ADTS 7.1.3.3 needs to be clarified
42 */
43
44/* the mapping function for generic rights for DS.(GA,GR,GW,GX)
45 * The mapping function is passed as an argument to the
46 * descriptor calculating routine and depends on the security
47 * manager that calls the calculating routine.
48 * TODO: need similar mappings for the file system and
49 * registry security managers in order to make this code
50 * generic for all security managers
51 */
52
53uint32_t map_generic_rights_ds(uint32_t access_mask)
54{
55	if (access_mask & SEC_GENERIC_ALL){
56		access_mask |= SEC_ADS_GENERIC_ALL;
57		access_mask = ~SEC_GENERIC_ALL;
58	}
59
60	if (access_mask & SEC_GENERIC_EXECUTE){
61		access_mask |= SEC_ADS_GENERIC_EXECUTE;
62		access_mask = ~SEC_GENERIC_EXECUTE;
63	}
64
65	if (access_mask & SEC_GENERIC_WRITE){
66		access_mask |= SEC_ADS_GENERIC_WRITE;
67		access_mask &= ~SEC_GENERIC_WRITE;
68	}
69
70	if (access_mask & SEC_GENERIC_READ){
71		access_mask |= SEC_ADS_GENERIC_READ;
72		access_mask &= ~SEC_GENERIC_READ;
73	}
74
75	return access_mask;
76}
77
78/* Not sure what this has to be,
79* and it does not seem to have any influence */
80static bool object_in_list(struct GUID *object_list, struct GUID *object)
81{
82	return true;
83}
84
85
86static bool contains_inheritable_aces(struct security_acl *acl)
87{
88        int i;
89	if (!acl)
90		return false;
91
92	for (i=0; i < acl->num_aces; i++) {
93		struct security_ace *ace = &acl->aces[i];
94		if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ||
95		    (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT))
96			return true;
97	}
98
99	return false;
100}
101
102static struct security_acl *preprocess_creator_acl(TALLOC_CTX *mem, struct security_acl *acl)
103{
104	int i;
105	struct security_acl *new_acl;
106	if (!acl) {
107		return NULL;
108	}
109
110	new_acl = talloc_zero(mem, struct security_acl);
111
112	for (i=0; i < acl->num_aces; i++) {
113		struct security_ace *ace = &acl->aces[i];
114		if (!(ace->flags & SEC_ACE_FLAG_INHERITED_ACE)){
115			new_acl->aces = talloc_realloc(new_acl, new_acl->aces, struct security_ace,
116					   new_acl->num_aces+1);
117			if (new_acl->aces == NULL) {
118				talloc_free(new_acl);
119				return NULL;
120			}
121			new_acl->aces[new_acl->num_aces] = *ace;
122			/*memcpy(&new_acl->aces[new_acl->num_aces], ace,
123			  sizeof(struct security_ace)); */
124			new_acl->num_aces++;
125		}
126	}
127	if (new_acl)
128		new_acl->revision = acl->revision;
129	/* Todo what to do if all were inherited and this is empty */
130	return new_acl;
131}
132
133/* This is not exactly as described in the docs. The original seemed to return
134 * only a list of the inherited or flagless ones... */
135
136static bool postprocess_acl(struct security_acl *acl,
137			    struct dom_sid *owner,
138			    struct dom_sid *group,
139			    uint32_t (*generic_map)(uint32_t access_mask))
140{
141	int i;
142	struct dom_sid *co, *cg;
143	TALLOC_CTX *tmp_ctx = talloc_new(acl);
144	if (!generic_map){
145		return false;
146	}
147	co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
148	cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
149	for (i=0; i < acl->num_aces; i++){
150		struct security_ace *ace = &acl->aces[i];
151		if (!(ace->flags == 0 || ace->flags & SEC_ACE_FLAG_INHERITED_ACE))
152			continue;
153		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY)
154			continue;
155		if (dom_sid_equal(&ace->trustee, co)){
156			ace->trustee = *owner;
157			/* perhaps this should be done somewhere else? */
158			ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
159		}
160		if (dom_sid_equal(&ace->trustee, cg)){
161			ace->trustee = *group;
162			ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
163		}
164		ace->access_mask = generic_map(ace->access_mask);
165	}
166
167	talloc_free(tmp_ctx);
168	return true;
169}
170
171static struct security_acl *calculate_inherited_from_parent(TALLOC_CTX *mem_ctx,
172						struct security_acl *acl,
173						bool is_container,
174						struct GUID *object_list)
175{
176	int i;
177	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
178	struct security_acl *tmp_acl = talloc_zero(tmp_ctx, struct security_acl);
179	struct security_acl *inh_acl = talloc_zero(tmp_ctx, struct security_acl);
180	struct security_acl *new_acl;
181	struct dom_sid *co, *cg;
182	if (!tmp_acl || !inh_acl)
183		return NULL;
184
185	co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
186	cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
187
188	for (i=0; i < acl->num_aces; i++){
189		struct security_ace *ace = &acl->aces[i];
190		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY)
191			continue;
192
193		if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ||
194		    (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)){
195			tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
196						       tmp_acl->num_aces+1);
197			if (tmp_acl->aces == NULL) {
198				talloc_free(tmp_ctx);
199				return NULL;
200			}
201
202			tmp_acl->aces[tmp_acl->num_aces] = *ace;
203			tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERITED_ACE;
204
205			if (is_container && (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT))
206			    tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
207
208			if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
209			    ace->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT){
210				if (!object_in_list(object_list, &ace->object.object.type.type)){
211					tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
212				}
213
214			}
215			tmp_acl->num_aces++;
216		}
217	}
218
219	if (is_container){
220		for (i=0; i < acl->num_aces; i++){
221			struct security_ace *ace = &acl->aces[i];
222
223			if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)
224				continue;
225			if (!dom_sid_equal(&ace->trustee, co) && !dom_sid_equal(&ace->trustee, cg))
226				continue;
227
228			if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ||
229			    (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)){
230				inh_acl->aces = talloc_realloc(inh_acl, inh_acl->aces, struct security_ace,
231							       inh_acl->num_aces+1);
232				if (inh_acl->aces == NULL){
233					talloc_free(tmp_ctx);
234					return NULL;
235				}
236				inh_acl->aces[inh_acl->num_aces] = *ace;
237				inh_acl->aces[inh_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
238				inh_acl->aces[inh_acl->num_aces].flags |= SEC_ACE_FLAG_INHERITED_ACE;
239				inh_acl->num_aces++;
240			}
241		}
242	}
243	new_acl = security_acl_concatenate(mem_ctx,tmp_acl, inh_acl);
244	if (new_acl)
245		new_acl->revision = acl->revision;
246	talloc_free(tmp_ctx);
247	return new_acl;
248}
249
250/* In the docs this looks == calculate_inherited_from_parent. However,
251 * It shouldn't return the inherited, rather filter them out....
252 */
253static struct security_acl *calculate_inherited_from_creator(TALLOC_CTX *mem_ctx,
254						struct security_acl *acl,
255						bool is_container,
256						struct GUID *object_list)
257{
258	int i;
259	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
260	struct security_acl *tmp_acl = talloc_zero(tmp_ctx, struct security_acl);
261/*	struct security_acl *inh_acl = talloc_zero(tmp_ctx, struct security_acl); */
262	struct security_acl *new_acl;
263	struct dom_sid *co, *cg;
264
265	if (!tmp_acl)
266		return NULL;
267
268	tmp_acl->revision = acl->revision;
269	DEBUG(6,(__location__ ": acl revision %u\n", acl->revision));
270
271	co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
272	cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
273
274	for (i=0; i < acl->num_aces; i++){
275		struct security_ace *ace = &acl->aces[i];
276		if (ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
277			continue;
278
279		tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
280					      tmp_acl->num_aces+1);
281		tmp_acl->aces[tmp_acl->num_aces] = *ace;
282		tmp_acl->aces[tmp_acl->num_aces].flags  = 0;
283		tmp_acl->num_aces++;
284
285		if (!dom_sid_equal(&ace->trustee, co) && !dom_sid_equal(&ace->trustee, cg))
286			continue;
287
288		tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
289					       tmp_acl->num_aces+1);
290		tmp_acl->aces[tmp_acl->num_aces] = *ace;
291		tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
292		tmp_acl->num_aces++;
293	}
294	new_acl = security_acl_dup(mem_ctx,tmp_acl);
295
296	talloc_free(tmp_ctx);
297	return new_acl;
298}
299
300static bool compute_acl(int acl_type,
301			struct security_descriptor *parent_sd,
302			struct security_descriptor *creator_sd,
303			bool is_container,
304			uint32_t inherit_flags,
305			struct GUID *object_list,
306			uint32_t (*generic_map)(uint32_t access_mask),
307			struct security_token *token,
308			struct security_descriptor *new_sd) /* INOUT argument */
309{
310	struct security_acl *p_acl = NULL, *c_acl = NULL, **new_acl;
311	if (acl_type == SEC_DESC_DACL_PRESENT){
312		if (parent_sd)
313			p_acl = parent_sd->dacl;
314		if (creator_sd)
315			c_acl = creator_sd->dacl;
316		new_acl = &new_sd->dacl;
317	}
318	else{
319		if (parent_sd)
320			p_acl = parent_sd->sacl;
321		if (creator_sd)
322			c_acl = creator_sd->sacl;
323		new_acl = &new_sd->sacl;
324	}
325	if (contains_inheritable_aces(p_acl)){
326		if (!c_acl || (c_acl && inherit_flags & SEC_DEFAULT_DESCRIPTOR)){
327			*new_acl = calculate_inherited_from_parent(new_sd,
328						       p_acl,
329						       is_container,
330						       object_list);
331			if (*new_acl == NULL)
332				goto final;
333			if (!postprocess_acl(*new_acl, new_sd->owner_sid,
334					     new_sd->group_sid, generic_map))
335				return false;
336			else
337				goto final;
338		}
339		if (c_acl && !(inherit_flags & SEC_DEFAULT_DESCRIPTOR)){
340			struct security_acl *pr_acl, *tmp_acl, *tpr_acl;
341			tpr_acl = preprocess_creator_acl(new_sd, c_acl);
342			tmp_acl = calculate_inherited_from_creator(new_sd,
343						      tpr_acl,
344						      is_container,
345						      object_list);
346			/* Todo some refactoring here! */
347			if (acl_type == SEC_DESC_DACL_PRESENT &&
348			    !(creator_sd->type & SECINFO_PROTECTED_DACL) &&
349			    (inherit_flags & SEC_DACL_AUTO_INHERIT)){
350				pr_acl = calculate_inherited_from_parent(new_sd,
351							     p_acl,
352							     is_container,
353							     object_list);
354
355				*new_acl = security_acl_concatenate(new_sd, tmp_acl, pr_acl);
356				new_sd->type |= SEC_DESC_DACL_AUTO_INHERITED;
357			}
358			else if (acl_type == SEC_DESC_SACL_PRESENT &&
359			    !(creator_sd->type & SECINFO_PROTECTED_SACL) &&
360			    (inherit_flags & SEC_SACL_AUTO_INHERIT)){
361				pr_acl = calculate_inherited_from_parent(new_sd,
362							     p_acl,
363							     is_container,
364							     object_list);
365
366				*new_acl = security_acl_concatenate(new_sd, tmp_acl, pr_acl);
367				new_sd->type |= SEC_DESC_SACL_AUTO_INHERITED;
368			}
369		}
370		if (*new_acl == NULL)
371			goto final;
372		if (!postprocess_acl(*new_acl, new_sd->owner_sid,
373				     new_sd->group_sid,generic_map))
374			return false;
375		else
376			goto final;
377	}
378	else{
379		*new_acl = preprocess_creator_acl(new_sd,c_acl);
380		if (*new_acl == NULL)
381			goto final;
382		if (!postprocess_acl(*new_acl, new_sd->owner_sid,
383				     new_sd->group_sid,generic_map))
384			return false;
385		else
386			goto final;
387	}
388final:
389	if (acl_type == SEC_DESC_DACL_PRESENT && new_sd->dacl)
390		new_sd->type |= SEC_DESC_DACL_PRESENT;
391
392	if (acl_type == SEC_DESC_SACL_PRESENT && new_sd->sacl)
393		new_sd->type |= SEC_DESC_SACL_PRESENT;
394	/* This is a hack to handle the fact that
395	 * apprantly any AI flag provided by the user is preserved */
396	if (creator_sd)
397		new_sd->type |= creator_sd->type;
398	return true;
399}
400
401struct security_descriptor *create_security_descriptor(TALLOC_CTX *mem_ctx,
402						       struct security_descriptor *parent_sd,
403						       struct security_descriptor *creator_sd,
404						       bool is_container,
405						       struct GUID *object_list,
406						       uint32_t inherit_flags,
407						       struct security_token *token,
408						       struct dom_sid *default_owner, /* valid only for DS, NULL for the other RSs */
409						       struct dom_sid *default_group, /* valid only for DS, NULL for the other RSs */
410						       uint32_t (*generic_map)(uint32_t access_mask))
411{
412	struct security_descriptor *new_sd;
413	struct dom_sid *new_owner = NULL;
414	struct dom_sid *new_group = NULL;
415
416	new_sd = security_descriptor_initialise(mem_ctx);
417	if (!new_sd) {
418		return NULL;
419	}
420
421	if (!creator_sd || !creator_sd->owner_sid) {
422		if ((inherit_flags & SEC_OWNER_FROM_PARENT) && parent_sd) {
423			new_owner = parent_sd->owner_sid;
424		} else if (!default_owner) {
425			new_owner = token->user_sid;
426		} else {
427			new_owner = default_owner;
428			new_sd->type |= SEC_DESC_OWNER_DEFAULTED;
429		}
430	} else {
431		new_owner = creator_sd->owner_sid;
432	}
433
434	if (!creator_sd || !creator_sd->group_sid){
435		if ((inherit_flags & SEC_GROUP_FROM_PARENT) && parent_sd) {
436			new_group = parent_sd->group_sid;
437		} else if (!default_group) {
438			new_group = token->group_sid;
439		} else {
440			new_group = default_group;
441			new_sd->type |= SEC_DESC_GROUP_DEFAULTED;
442		}
443	} else {
444		new_group = creator_sd->group_sid;
445	}
446
447	new_sd->owner_sid = talloc_memdup(new_sd, new_owner, sizeof(struct dom_sid));
448	new_sd->group_sid = talloc_memdup(new_sd, new_group, sizeof(struct dom_sid));
449	if (!new_sd->owner_sid || !new_sd->group_sid){
450		talloc_free(new_sd);
451		return NULL;
452	}
453
454	if (!compute_acl(SEC_DESC_DACL_PRESENT, parent_sd, creator_sd,
455			 is_container, inherit_flags, object_list,
456			 generic_map,token,new_sd)){
457		talloc_free(new_sd);
458		return NULL;
459	}
460
461	if (!compute_acl(SEC_DESC_SACL_PRESENT, parent_sd, creator_sd,
462			 is_container, inherit_flags, object_list,
463			 generic_map, token,new_sd)){
464		talloc_free(new_sd);
465		return NULL;
466	}
467
468	return new_sd;
469}
470