Initial implementation of security descriptor creation in DS
[ira/wip.git] / source4 / libcli / security / create_descriptor.c
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
53 uint32_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 */
80 static bool object_in_list(struct GUID *object_list, struct GUID *object)
81 {
82         return true;
83 }
84
85
86 static 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
102 static struct security_acl *preprocess_creator_acl(TALLOC_CTX *mem, struct security_acl *acl)
103 {
104         int i;
105         struct security_acl *new_acl = talloc_zero(mem, struct security_acl);
106
107         new_acl->revision = acl->revision;
108         for (i=0; i < acl->num_aces; i++) {
109                 struct security_ace *ace = &acl->aces[i];
110                 if (!(ace->flags & SEC_ACE_FLAG_INHERITED_ACE)){
111                         new_acl->aces = talloc_realloc(new_acl, new_acl->aces, struct security_ace,
112                                            new_acl->num_aces+1);
113                         if (new_acl->aces == NULL) {
114                                 talloc_free(new_acl);
115                                 return NULL;
116                         }
117                         new_acl->aces[new_acl->num_aces] = *ace;
118                         /*memcpy(&new_acl->aces[new_acl->num_aces], ace,
119                           sizeof(struct security_ace)); */
120                         new_acl->num_aces++;
121                 }
122         }
123         if (new_acl)
124                 new_acl->revision = acl->revision;
125         /* Todo what to do if all were inherited and this is empty */
126         return new_acl;
127 }
128
129 /* This is not exactly as described in the docs. The original seemed to return
130  * only a list of the inherited or flagless ones... */
131
132 static bool postprocess_acl(struct security_acl *acl,
133                             struct dom_sid *owner,
134                             struct dom_sid *group,
135                             uint32_t (*generic_map)(uint32_t access_mask))
136 {
137         int i;
138         struct dom_sid *co, *cg;
139         TALLOC_CTX *tmp_ctx = talloc_new(acl);
140         if (!generic_map){
141                 return false;
142         }
143         co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
144         cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
145         for (i=0; i < acl->num_aces; i++){
146                 struct security_ace *ace = &acl->aces[i];
147                 if (!(ace->flags == 0 || ace->flags & SEC_ACE_FLAG_INHERITED_ACE))
148                         continue;
149                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY)
150                         continue;
151                 if (dom_sid_equal(&ace->trustee, co)){
152                         ace->trustee = *owner;
153                         /* perhaps this should be done somewhere else? */
154                         ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
155                 }
156                 if (dom_sid_equal(&ace->trustee, cg)){
157                         ace->trustee = *group;
158                         ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
159                 }
160                 ace->access_mask = generic_map(ace->access_mask);
161         }
162
163         talloc_free(tmp_ctx);
164         return true;
165 }
166
167 static struct security_acl *calculate_inherited_from_parent(TALLOC_CTX *mem_ctx,
168                                                 struct security_acl *acl,
169                                                 bool is_container,
170                                                 struct GUID *object_list)
171 {
172         int i;
173         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
174         struct security_acl *tmp_acl = talloc_zero(tmp_ctx, struct security_acl);
175         struct security_acl *inh_acl = talloc_zero(tmp_ctx, struct security_acl);
176         struct security_acl *new_acl;
177         struct dom_sid *co, *cg;
178         if (!tmp_acl || !inh_acl)
179                 return NULL;
180
181         co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
182         cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
183
184         for (i=0; i < acl->num_aces; i++){
185                 struct security_ace *ace = &acl->aces[i];
186                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY)
187                         continue;
188
189                 if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ||
190                     (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)){
191                         tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
192                                                        tmp_acl->num_aces+1);
193                         if (tmp_acl->aces == NULL) {
194                                 talloc_free(tmp_ctx);
195                                 return NULL;
196                         }
197
198                         tmp_acl->aces[tmp_acl->num_aces] = *ace;
199                         tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERITED_ACE;
200
201                         if (is_container && (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT))
202                             tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
203
204                         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
205                             ace->type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT){
206                                 if (!object_in_list(object_list, &ace->object.object.type.type)){
207                                         tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
208                                 }
209
210                         }
211                         tmp_acl->num_aces++;
212                 }
213         }
214
215         if (is_container){
216                 for (i=0; i < acl->num_aces; i++){
217                         struct security_ace *ace = &acl->aces[i];
218
219                         if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)
220                                 continue;
221                         if (!dom_sid_equal(&ace->trustee, co) && !dom_sid_equal(&ace->trustee, cg))
222                                 continue;
223
224                         if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ||
225                             (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT)){
226                                 inh_acl->aces = talloc_realloc(inh_acl, inh_acl->aces, struct security_ace,
227                                                                inh_acl->num_aces+1);
228                                 if (inh_acl->aces == NULL){
229                                         talloc_free(tmp_ctx);
230                                         return NULL;
231                                 }
232                                 inh_acl->aces[inh_acl->num_aces] = *ace;
233                                 inh_acl->aces[inh_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
234                                 inh_acl->aces[inh_acl->num_aces].flags |= SEC_ACE_FLAG_INHERITED_ACE;
235                                 inh_acl->num_aces++;
236                         }
237                 }
238         }
239         new_acl = security_acl_concatenate(mem_ctx,tmp_acl, inh_acl);
240         if (new_acl)
241                 new_acl->revision = acl->revision;
242         talloc_free(tmp_ctx);
243         return new_acl;
244 }
245
246 /* In the docs this looks == calculate_inherited_from_parent. However,
247  * It shouldn't return the inherited, rather filter them out....
248  */
249 static struct security_acl *calculate_inherited_from_creator(TALLOC_CTX *mem_ctx,
250                                                 struct security_acl *acl,
251                                                 bool is_container,
252                                                 struct GUID *object_list)
253 {
254         int i;
255         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
256         struct security_acl *tmp_acl = talloc_zero(tmp_ctx, struct security_acl);
257 /*      struct security_acl *inh_acl = talloc_zero(tmp_ctx, struct security_acl); */
258         struct security_acl *new_acl;
259         struct dom_sid *co, *cg;
260
261         if (!tmp_acl)
262                 return NULL;
263
264         co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
265         cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
266
267         for (i=0; i < acl->num_aces; i++){
268                 struct security_ace *ace = &acl->aces[i];
269                 if (ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
270                         continue;
271
272                 tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
273                                               tmp_acl->num_aces+1);
274                 tmp_acl->aces[tmp_acl->num_aces] = *ace;
275                 tmp_acl->aces[tmp_acl->num_aces].flags  = 0;
276                 tmp_acl->num_aces++;
277
278                 if (!dom_sid_equal(&ace->trustee, co) && !dom_sid_equal(&ace->trustee, cg))
279                         continue;
280
281                 tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
282                                                tmp_acl->num_aces+1);
283                 tmp_acl->aces[tmp_acl->num_aces] = *ace;
284                 tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
285                 tmp_acl->num_aces++;
286         }
287         new_acl = security_acl_dup(mem_ctx,tmp_acl);
288
289         talloc_free(tmp_ctx);
290         return new_acl;
291 }
292
293 static bool compute_acl(int acl_type,
294                         struct security_descriptor *parent_sd,
295                         struct security_descriptor *creator_sd,
296                         bool is_container,
297                         uint32_t inherit_flags,
298                         struct GUID *object_list,
299                         uint32_t (*generic_map)(uint32_t access_mask),
300                         struct security_token *token,
301                         struct security_descriptor *new_sd) /* INOUT argument */
302 {
303         struct security_acl *p_acl = NULL, *c_acl = NULL, **new_acl;
304         if (acl_type == SEC_DESC_DACL_PRESENT){
305                 if (parent_sd)
306                         p_acl = parent_sd->dacl;
307                 if (creator_sd)
308                         c_acl = creator_sd->dacl;
309                 new_acl = &new_sd->dacl;
310         }
311         else{
312                 if (parent_sd)
313                         p_acl = parent_sd->sacl;
314                 if (creator_sd)
315                         c_acl = creator_sd->sacl;
316                 new_acl = &new_sd->sacl;
317         }
318         if (contains_inheritable_aces(p_acl)){
319                 if (!c_acl || (c_acl && inherit_flags & SEC_DEFAULT_DESCRIPTOR)){
320                         *new_acl = calculate_inherited_from_parent(new_sd,
321                                                        p_acl,
322                                                        is_container,
323                                                        object_list);
324                         if (*new_acl == NULL)
325                                 goto final;
326                         if (!postprocess_acl(*new_acl, new_sd->owner_sid,
327                                              new_sd->group_sid, generic_map))
328                                 return false;
329                         else
330                                 goto final;
331                 }
332                 if (c_acl && !(inherit_flags & SEC_DEFAULT_DESCRIPTOR)){
333                         struct security_acl *pr_acl, *tmp_acl, *tpr_acl;
334                         tpr_acl = preprocess_creator_acl(new_sd, c_acl);
335                         tmp_acl = calculate_inherited_from_creator(new_sd,
336                                                       tpr_acl,
337                                                       is_container,
338                                                       object_list);
339                         /* Todo some refactoring here! */
340                         if (acl_type == SEC_DESC_DACL_PRESENT &&
341                             !(creator_sd->type & SECINFO_PROTECTED_DACL) &&
342                             (inherit_flags & SEC_DACL_AUTO_INHERIT)){
343                                 pr_acl = calculate_inherited_from_parent(new_sd,
344                                                              p_acl,
345                                                              is_container,
346                                                              object_list);
347
348                                 *new_acl = security_acl_concatenate(new_sd, tmp_acl, pr_acl);
349                                 new_sd->type |= SEC_DESC_DACL_AUTO_INHERITED;
350                         }
351                         else if (acl_type == SEC_DESC_SACL_PRESENT &&
352                             !(creator_sd->type & SECINFO_PROTECTED_SACL) &&
353                             (inherit_flags & SEC_SACL_AUTO_INHERIT)){
354                                 pr_acl = calculate_inherited_from_parent(new_sd,
355                                                              p_acl,
356                                                              is_container,
357                                                              object_list);
358
359                                 *new_acl = security_acl_concatenate(new_sd, tmp_acl, pr_acl);
360                                 new_sd->type |= SEC_DESC_SACL_AUTO_INHERITED;
361                         }
362                 }
363                 if (*new_acl == NULL)
364                         goto final;
365                 if (!postprocess_acl(*new_acl, new_sd->owner_sid,
366                                      new_sd->group_sid,generic_map))
367                         return false;
368                 else
369                         goto final;
370         }
371         else{
372                 if (!c_acl){
373                         if (acl_type == SEC_DESC_DACL_PRESENT && token->default_dacl)
374                                 *new_acl = security_acl_dup(new_sd, token->default_dacl);
375                 }
376                 else{
377                         *new_acl = preprocess_creator_acl(new_sd,c_acl);
378                         if (*new_acl == NULL)
379                                 goto final;
380                         if (!postprocess_acl(*new_acl, new_sd->owner_sid,
381                                              new_sd->group_sid,generic_map))
382                                 return false;
383                         else
384                                 goto final;
385                 }
386         }
387 final:
388         if (acl_type == SEC_DESC_DACL_PRESENT && new_sd->dacl)
389                 new_sd->type |= SEC_DESC_DACL_PRESENT;
390
391         if (acl_type == SEC_DESC_SACL_PRESENT && new_sd->sacl)
392                 new_sd->type |= SEC_DESC_SACL_PRESENT;
393         /* This is a hack to handle the fact that
394          * apprantly any AI flag provided by the user is preserved */
395         if (creator_sd)
396                 new_sd->type |= creator_sd->type;
397         return true;
398 }
399
400 struct security_descriptor *create_security_descriptor(TALLOC_CTX *mem_ctx,
401                                                        struct security_descriptor *parent_sd,
402                                                        struct security_descriptor *creator_sd,
403                                                        bool is_container,
404                                                        struct GUID *object_list,
405                                                        uint32_t inherit_flags,
406                                                        struct security_token *token,
407                                                        struct dom_sid *default_owner, /* valid only for DS, NULL for the other RSs */
408                                                        struct dom_sid *default_group, /* valid only for DS, NULL for the other RSs */
409                                                        uint32_t (*generic_map)(uint32_t access_mask))
410 {
411         struct security_descriptor *new_sd;
412         struct dom_sid *new_owner = NULL;
413         struct dom_sid *new_group = NULL;
414
415         new_sd = security_descriptor_initialise(mem_ctx);
416         if (!new_sd)
417                 return NULL;
418         if (!creator_sd || !creator_sd->owner_sid){
419                 if (inherit_flags & SEC_OWNER_FROM_PARENT)
420                         new_owner = parent_sd->owner_sid;
421                 else if (!default_owner)
422                         new_owner = token->user_sid;
423                 else
424                         new_owner = default_owner;
425         }
426         else
427                 new_owner = creator_sd->owner_sid;
428
429         if (!creator_sd || !creator_sd->group_sid){
430                 if (inherit_flags & SEC_GROUP_FROM_PARENT && parent_sd)
431                         new_group = parent_sd->group_sid;
432                 else if (!default_group)
433                         new_group = token->group_sid;
434                 else new_group = default_group;
435         }
436         else
437                 new_group = creator_sd->group_sid;
438
439         new_sd->owner_sid = talloc_memdup(new_sd, new_owner, sizeof(struct dom_sid));
440         new_sd->group_sid = talloc_memdup(new_sd, new_group, sizeof(struct dom_sid));
441         if (!new_sd->owner_sid || !new_sd->group_sid){
442                 talloc_free(new_sd);
443                 return NULL;
444         }
445
446         if (!compute_acl(SEC_DESC_DACL_PRESENT, parent_sd, creator_sd,
447                          is_container, inherit_flags, object_list,
448                          generic_map,token,new_sd)){
449                 talloc_free(new_sd);
450                 return NULL;
451         }
452
453         if (!compute_acl(SEC_DESC_SACL_PRESENT, parent_sd, creator_sd,
454                          is_container, inherit_flags, object_list,
455                          generic_map, token,new_sd)){
456                 talloc_free(new_sd);
457                 return NULL;
458         }
459
460         return new_sd;
461 }