Fixed some missing flags and bugs in the security creation.
[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 #include "librpc/gen_ndr/ndr_security.h"
32
33 /* Todos:
34  * build the security token dacl as follows:
35  * SYSTEM: GA, OWNER: GA, LOGIN_SID:GW|GE
36  * Need session id information for the login SID. Probably
37  * the best place for this is during token creation
38  *
39  * Implement SD Invariants
40  * ACE sorting rules
41  * LDAP_SERVER_SD_FLAGS_OID control
42  * ADTS 7.1.3.3 needs to be clarified
43  */
44
45 /* the mapping function for generic rights for DS.(GA,GR,GW,GX)
46  * The mapping function is passed as an argument to the
47  * descriptor calculating routine and depends on the security
48  * manager that calls the calculating routine.
49  * TODO: need similar mappings for the file system and
50  * registry security managers in order to make this code
51  * generic for all security managers
52  */
53
54 uint32_t map_generic_rights_ds(uint32_t access_mask)
55 {
56         if (access_mask & SEC_GENERIC_ALL){
57                 access_mask |= SEC_ADS_GENERIC_ALL;
58                 access_mask = ~SEC_GENERIC_ALL;
59         }
60
61         if (access_mask & SEC_GENERIC_EXECUTE){
62                 access_mask |= SEC_ADS_GENERIC_EXECUTE;
63                 access_mask = ~SEC_GENERIC_EXECUTE;
64         }
65
66         if (access_mask & SEC_GENERIC_WRITE){
67                 access_mask |= SEC_ADS_GENERIC_WRITE;
68                 access_mask &= ~SEC_GENERIC_WRITE;
69         }
70
71         if (access_mask & SEC_GENERIC_READ){
72                 access_mask |= SEC_ADS_GENERIC_READ;
73                 access_mask &= ~SEC_GENERIC_READ;
74         }
75
76         return access_mask;
77 }
78
79 /* Not sure what this has to be,
80 * and it does not seem to have any influence */
81 static bool object_in_list(struct GUID *object_list, struct GUID *object)
82 {
83         return true;
84 }
85
86
87 static bool contains_inheritable_aces(struct security_acl *acl)
88 {
89         int i;
90         if (!acl)
91                 return false;
92
93         for (i=0; i < acl->num_aces; i++) {
94                 struct security_ace *ace = &acl->aces[i];
95                 if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ||
96                     (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT))
97                         return true;
98         }
99
100         return false;
101 }
102
103 static struct security_acl *preprocess_creator_acl(TALLOC_CTX *mem, struct security_acl *acl)
104 {
105         int i;
106         struct security_acl *new_acl; 
107         if (!acl) {
108                 return NULL;
109         }
110         
111         new_acl = talloc_zero(mem, struct security_acl);
112
113         for (i=0; i < acl->num_aces; i++) {
114                 struct security_ace *ace = &acl->aces[i];
115                 if (!(ace->flags & SEC_ACE_FLAG_INHERITED_ACE)){
116                         new_acl->aces = talloc_realloc(new_acl, new_acl->aces, struct security_ace,
117                                            new_acl->num_aces+1);
118                         if (new_acl->aces == NULL) {
119                                 talloc_free(new_acl);
120                                 return NULL;
121                         }
122                         new_acl->aces[new_acl->num_aces] = *ace;
123                         new_acl->num_aces++;
124                 }
125         }
126         if (new_acl)
127                 new_acl->revision = acl->revision;
128
129         return new_acl;
130 }
131
132 /* This is not exactly as described in the docs. The original seemed to return
133  * only a list of the inherited or flagless ones... */
134
135 static bool postprocess_acl(struct security_acl *acl,
136                             struct dom_sid *owner,
137                             struct dom_sid *group,
138                             uint32_t (*generic_map)(uint32_t access_mask))
139 {
140         int i;
141         struct dom_sid *co, *cg;
142         TALLOC_CTX *tmp_ctx = talloc_new(acl);
143         if (!generic_map){
144                 return false;
145         }
146         co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
147         cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
148         for (i=0; i < acl->num_aces; i++){
149                 struct security_ace *ace = &acl->aces[i];
150                 if (!(ace->flags == 0 || ace->flags & SEC_ACE_FLAG_INHERITED_ACE))
151                         continue;
152                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY)
153                         continue;
154                 if (dom_sid_equal(&ace->trustee, co)){
155                         ace->trustee = *owner;
156                         /* perhaps this should be done somewhere else? */
157                         ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
158                 }
159                 if (dom_sid_equal(&ace->trustee, cg)){
160                         ace->trustee = *group;
161                         ace->flags &= ~SEC_ACE_FLAG_CONTAINER_INHERIT;
162                 }
163                 ace->access_mask = generic_map(ace->access_mask);
164         }
165
166         talloc_free(tmp_ctx);
167         return true;
168 }
169
170 static struct security_acl *calculate_inherited_from_parent(TALLOC_CTX *mem_ctx,
171                                                 struct security_acl *acl,
172                                                 bool is_container,
173                                                 struct GUID *object_list)
174 {
175         int i;
176         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
177         struct security_acl *tmp_acl = talloc_zero(tmp_ctx, struct security_acl);
178         struct security_acl *inh_acl = talloc_zero(tmp_ctx, struct security_acl);
179         struct security_acl *new_acl;
180         struct dom_sid *co, *cg;
181         if (!tmp_acl || !inh_acl)
182                 return NULL;
183
184         co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
185         cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
186
187         for (i=0; i < acl->num_aces; i++){
188                 struct security_ace *ace = &acl->aces[i];
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 *new_acl;
258         struct dom_sid *co, *cg;
259
260         if (!tmp_acl)
261                 return NULL;
262
263         tmp_acl->revision = acl->revision;
264         DEBUG(6,(__location__ ": acl revision %u\n", acl->revision));
265
266         co = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_OWNER);
267         cg = dom_sid_parse_talloc(tmp_ctx,  SID_CREATOR_GROUP);
268
269         for (i=0; i < acl->num_aces; i++){
270                 struct security_ace *ace = &acl->aces[i];
271                 if (ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
272                         continue;
273
274                 tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
275                                               tmp_acl->num_aces+1);
276                 tmp_acl->aces[tmp_acl->num_aces] = *ace;
277                 tmp_acl->num_aces++;
278
279                 if (!dom_sid_equal(&ace->trustee, co) && !dom_sid_equal(&ace->trustee, cg))
280                         continue;
281
282                 tmp_acl->aces = talloc_realloc(tmp_acl, tmp_acl->aces, struct security_ace,
283                                                tmp_acl->num_aces+1);
284                 tmp_acl->aces[tmp_acl->num_aces] = *ace;
285                 tmp_acl->aces[tmp_acl->num_aces].flags |= SEC_ACE_FLAG_INHERIT_ONLY;
286                 tmp_acl->num_aces++;
287         }
288         new_acl = security_acl_dup(mem_ctx,tmp_acl);
289
290         if (new_acl)
291                 new_acl->revision = acl->revision;
292
293         talloc_free(tmp_ctx);
294         return new_acl;
295 }
296
297 static void cr_descr_log_descriptor(struct security_descriptor *sd,
298                                     const char *message,
299                                     int level)
300 {
301         if (sd) {
302                 DEBUG(level,("%s: %s\n", message,
303                              ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_descriptor,
304                                                      "", sd)));
305         }
306         else {
307                 DEBUG(level,("%s: NULL\n", message));
308         }
309 }
310
311 static void cr_descr_log_acl(struct security_acl *acl,
312                                     const char *message,
313                                     int level)
314 {
315         if (acl) {
316                 DEBUG(level,("%s: %s\n", message,
317                              ndr_print_struct_string(0,(ndr_print_fn_t)ndr_print_security_acl,
318                                                      "", acl)));
319         }
320         else {
321                 DEBUG(level,("%s: NULL\n", message));
322         }
323 }
324
325 static bool compute_acl(int acl_type,
326                         struct security_descriptor *parent_sd,
327                         struct security_descriptor *creator_sd,
328                         bool is_container,
329                         uint32_t inherit_flags,
330                         struct GUID *object_list,
331                         uint32_t (*generic_map)(uint32_t access_mask),
332                         struct security_token *token,
333                         struct security_descriptor *new_sd) /* INOUT argument */
334 {
335         struct security_acl *p_acl = NULL, *c_acl = NULL, **new_acl;
336         int level = 10;
337         if (acl_type == SEC_DESC_DACL_PRESENT){
338                 if (parent_sd)
339                         p_acl = parent_sd->dacl;
340                 if (creator_sd)
341                         c_acl = creator_sd->dacl;
342                 new_acl = &new_sd->dacl;
343         }
344         else{
345                 if (parent_sd)
346                         p_acl = parent_sd->sacl;
347                 if (creator_sd)
348                         c_acl = creator_sd->sacl;
349                 new_acl = &new_sd->sacl;
350         }
351
352         cr_descr_log_descriptor(parent_sd, __location__"parent_sd", level);
353         cr_descr_log_descriptor(creator_sd,__location__ "creator_sd", level);
354
355         if (contains_inheritable_aces(p_acl)){
356                 if (!c_acl || (c_acl && inherit_flags & SEC_DEFAULT_DESCRIPTOR)){
357                         *new_acl = calculate_inherited_from_parent(new_sd,
358                                                        p_acl,
359                                                        is_container,
360                                                        object_list);
361                         if (*new_acl == NULL)
362                                 goto final;
363                         if (!postprocess_acl(*new_acl, new_sd->owner_sid,
364                                              new_sd->group_sid, generic_map))
365                                 return false;
366                         else {
367                                 cr_descr_log_descriptor(new_sd,
368                                                         __location__": Nothing from creator, newsd is", level);
369                                 goto final;
370                         }
371                 }
372                 if (c_acl && !(inherit_flags & SEC_DEFAULT_DESCRIPTOR)){
373                         struct security_acl *pr_acl, *tmp_acl, *tpr_acl;
374                         tpr_acl = preprocess_creator_acl(new_sd, c_acl);
375                         tmp_acl = calculate_inherited_from_creator(new_sd,
376                                                       tpr_acl,
377                                                       is_container,
378                                                       object_list);
379
380                         cr_descr_log_acl(tmp_acl, __location__"Inherited from creator", level);
381                         /* Todo some refactoring here! */
382                         if (acl_type == SEC_DESC_DACL_PRESENT &&
383                             !(creator_sd->type & SECINFO_PROTECTED_DACL) &&
384                             (inherit_flags & SEC_DACL_AUTO_INHERIT)){
385                                 pr_acl = calculate_inherited_from_parent(new_sd,
386                                                              p_acl,
387                                                              is_container,
388                                                              object_list);
389                                 cr_descr_log_acl(pr_acl, __location__"Inherited from parent", level);
390                                 *new_acl = security_acl_concatenate(new_sd, tmp_acl, pr_acl);
391                                 new_sd->type |= SEC_DESC_DACL_AUTO_INHERITED;
392                         }
393                         else if (acl_type == SEC_DESC_SACL_PRESENT &&
394                             !(creator_sd->type & SECINFO_PROTECTED_SACL) &&
395                             (inherit_flags & SEC_SACL_AUTO_INHERIT)){
396                                 pr_acl = calculate_inherited_from_parent(new_sd,
397                                                              p_acl,
398                                                              is_container,
399                                                              object_list);
400                                 cr_descr_log_acl(pr_acl, __location__"Inherited from parent", level);
401                                 *new_acl = security_acl_concatenate(new_sd, tmp_acl, pr_acl);
402                                 new_sd->type |= SEC_DESC_SACL_AUTO_INHERITED;
403                         }
404                 }
405                 if (*new_acl == NULL)
406                         goto final;
407                 if (!postprocess_acl(*new_acl, new_sd->owner_sid,
408                                      new_sd->group_sid,generic_map))
409                         return false;
410                 else
411                         goto final;
412         }
413         else{
414                 *new_acl = preprocess_creator_acl(new_sd,c_acl);
415                 if (*new_acl == NULL)
416                         goto final;
417                 if (!postprocess_acl(*new_acl, new_sd->owner_sid,
418                                      new_sd->group_sid,generic_map))
419                         return false;
420                 else
421                         goto final;
422         }
423 final:
424         if (acl_type == SEC_DESC_DACL_PRESENT && new_sd->dacl)
425                 new_sd->type |= SEC_DESC_DACL_PRESENT;
426
427         if (acl_type == SEC_DESC_SACL_PRESENT && new_sd->sacl)
428                 new_sd->type |= SEC_DESC_SACL_PRESENT;
429         /* This is a hack to handle the fact that
430          * apprantly any AI flag provided by the user is preserved */
431         if (creator_sd)
432                 new_sd->type |= creator_sd->type;
433         cr_descr_log_descriptor(new_sd, __location__"final sd", level);
434         return true;
435 }
436
437 struct security_descriptor *create_security_descriptor(TALLOC_CTX *mem_ctx,
438                                                        struct security_descriptor *parent_sd,
439                                                        struct security_descriptor *creator_sd,
440                                                        bool is_container,
441                                                        struct GUID *object_list,
442                                                        uint32_t inherit_flags,
443                                                        struct security_token *token,
444                                                        struct dom_sid *default_owner, /* valid only for DS, NULL for the other RSs */
445                                                        struct dom_sid *default_group, /* valid only for DS, NULL for the other RSs */
446                                                        uint32_t (*generic_map)(uint32_t access_mask))
447 {
448         struct security_descriptor *new_sd;
449         struct dom_sid *new_owner = NULL;
450         struct dom_sid *new_group = NULL;
451
452         new_sd = security_descriptor_initialise(mem_ctx);
453         if (!new_sd) {
454                 return NULL;
455         }
456
457         if (!creator_sd || !creator_sd->owner_sid) {
458                 if ((inherit_flags & SEC_OWNER_FROM_PARENT) && parent_sd) {
459                         new_owner = parent_sd->owner_sid;
460                 } else if (!default_owner) {
461                         new_owner = token->user_sid;
462                 } else {
463                         new_owner = default_owner;
464                         new_sd->type |= SEC_DESC_OWNER_DEFAULTED;
465                 }
466         } else {
467                 new_owner = creator_sd->owner_sid;
468         }
469
470         if (!creator_sd || !creator_sd->group_sid){
471                 if ((inherit_flags & SEC_GROUP_FROM_PARENT) && parent_sd) {
472                         new_group = parent_sd->group_sid;
473                 } else if (!default_group) {
474                         new_group = token->group_sid;
475                 } else {
476                         new_group = default_group;
477                         new_sd->type |= SEC_DESC_GROUP_DEFAULTED;
478                 }
479         } else {
480                 new_group = creator_sd->group_sid;
481         }
482
483         new_sd->owner_sid = talloc_memdup(new_sd, new_owner, sizeof(struct dom_sid));
484         new_sd->group_sid = talloc_memdup(new_sd, new_group, sizeof(struct dom_sid));
485         if (!new_sd->owner_sid || !new_sd->group_sid){
486                 talloc_free(new_sd);
487                 return NULL;
488         }
489
490         if (!compute_acl(SEC_DESC_DACL_PRESENT, parent_sd, creator_sd,
491                          is_container, inherit_flags, object_list,
492                          generic_map,token,new_sd)){
493                 talloc_free(new_sd);
494                 return NULL;
495         }
496
497         if (!compute_acl(SEC_DESC_SACL_PRESENT, parent_sd, creator_sd,
498                          is_container, inherit_flags, object_list,
499                          generic_map, token,new_sd)){
500                 talloc_free(new_sd);
501                 return NULL;
502         }
503
504         return new_sd;
505 }