~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libcli/security/security_descriptor.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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