/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- pvfs_acl_register
- pvfs_acl_backend_byname
- pvfs_acl_init
- pvfs_translate_mask
- pvfs_translate_generic_bits
- pvfs_default_acl
- normalise_sd_flags
- pvfs_acl_set
- pvfs_acl_query
- pvfs_read_only
- pvfs_access_check_unix
- pvfs_access_check
- pvfs_access_check_simple
- pvfs_access_check_create
- pvfs_access_check_parent
- pvfs_inheritable_ace
- pvfs_acl_inherit_aces
- pvfs_acl_inherit
- pvfs_access_maximal_allowed
1 /*
2 Unix SMB/CIFS implementation.
3
4 POSIX NTVFS backend - ACL support
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 "auth/auth.h"
24 #include "vfs_posix.h"
25 #include "librpc/gen_ndr/xattr.h"
26 #include "libcli/security/security.h"
27 #include "param/param.h"
28
29
30 /* the list of currently registered ACL backends */
31 static struct pvfs_acl_backend {
32 const struct pvfs_acl_ops *ops;
33 } *backends = NULL;
34 static int num_backends;
35
36 /*
37 register a pvfs acl backend.
38
39 The 'name' can be later used by other backends to find the operations
40 structure for this backend.
41 */
42 NTSTATUS pvfs_acl_register(const struct pvfs_acl_ops *ops)
/* [<][>][^][v][top][bottom][index][help] */
43 {
44 struct pvfs_acl_ops *new_ops;
45
46 if (pvfs_acl_backend_byname(ops->name) != NULL) {
47 DEBUG(0,("pvfs acl backend '%s' already registered\n", ops->name));
48 return NT_STATUS_OBJECT_NAME_COLLISION;
49 }
50
51 backends = talloc_realloc(talloc_autofree_context(), backends, struct pvfs_acl_backend, num_backends+1);
52 NT_STATUS_HAVE_NO_MEMORY(backends);
53
54 new_ops = (struct pvfs_acl_ops *)talloc_memdup(backends, ops, sizeof(*ops));
55 new_ops->name = talloc_strdup(new_ops, ops->name);
56
57 backends[num_backends].ops = new_ops;
58
59 num_backends++;
60
61 DEBUG(3,("NTVFS backend '%s' registered\n", ops->name));
62
63 return NT_STATUS_OK;
64 }
65
66
67 /*
68 return the operations structure for a named backend
69 */
70 const struct pvfs_acl_ops *pvfs_acl_backend_byname(const char *name)
/* [<][>][^][v][top][bottom][index][help] */
71 {
72 int i;
73
74 for (i=0;i<num_backends;i++) {
75 if (strcmp(backends[i].ops->name, name) == 0) {
76 return backends[i].ops;
77 }
78 }
79
80 return NULL;
81 }
82
83 NTSTATUS pvfs_acl_init(struct loadparm_context *lp_ctx)
/* [<][>][^][v][top][bottom][index][help] */
84 {
85 static bool initialized = false;
86 extern NTSTATUS pvfs_acl_nfs4_init(void);
87 extern NTSTATUS pvfs_acl_xattr_init(void);
88 init_module_fn static_init[] = { STATIC_pvfs_acl_MODULES };
89 init_module_fn *shared_init;
90
91 if (initialized) return NT_STATUS_OK;
92 initialized = true;
93
94 shared_init = load_samba_modules(NULL, lp_ctx, "pvfs_acl");
95
96 run_init_functions(static_init);
97 run_init_functions(shared_init);
98
99 talloc_free(shared_init);
100
101 return NT_STATUS_OK;
102 }
103
104
105 /*
106 map a single access_mask from generic to specific bits for files/dirs
107 */
108 static uint32_t pvfs_translate_mask(uint32_t access_mask)
/* [<][>][^][v][top][bottom][index][help] */
109 {
110 if (access_mask & SEC_MASK_GENERIC) {
111 if (access_mask & SEC_GENERIC_READ) access_mask |= SEC_RIGHTS_FILE_READ;
112 if (access_mask & SEC_GENERIC_WRITE) access_mask |= SEC_RIGHTS_FILE_WRITE;
113 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
114 if (access_mask & SEC_GENERIC_ALL) access_mask |= SEC_RIGHTS_FILE_ALL;
115 access_mask &= ~SEC_MASK_GENERIC;
116 }
117 return access_mask;
118 }
119
120
121 /*
122 map any generic access bits in the given acl
123 this relies on the fact that the mappings for files and directories
124 are the same
125 */
126 static void pvfs_translate_generic_bits(struct security_acl *acl)
/* [<][>][^][v][top][bottom][index][help] */
127 {
128 unsigned i;
129
130 if (!acl) return;
131
132 for (i=0;i<acl->num_aces;i++) {
133 struct security_ace *ace = &acl->aces[i];
134 ace->access_mask = pvfs_translate_mask(ace->access_mask);
135 }
136 }
137
138
139 /*
140 setup a default ACL for a file
141 */
142 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
143 struct ntvfs_request *req,
144 struct pvfs_filename *name, int fd,
145 struct security_descriptor **psd)
146 {
147 struct security_descriptor *sd;
148 NTSTATUS status;
149 struct security_ace ace;
150 mode_t mode;
151 struct id_mapping *ids;
152 struct composite_context *ctx;
153
154 *psd = security_descriptor_initialise(req);
155 if (*psd == NULL) {
156 return NT_STATUS_NO_MEMORY;
157 }
158 sd = *psd;
159
160 ids = talloc_zero_array(sd, struct id_mapping, 2);
161 NT_STATUS_HAVE_NO_MEMORY(ids);
162
163 ids[0].unixid = talloc(ids, struct unixid);
164 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
165
166 ids[0].unixid->id = name->st.st_uid;
167 ids[0].unixid->type = ID_TYPE_UID;
168 ids[0].sid = NULL;
169
170 ids[1].unixid = talloc(ids, struct unixid);
171 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
172
173 ids[1].unixid->id = name->st.st_gid;
174 ids[1].unixid->type = ID_TYPE_GID;
175 ids[1].sid = NULL;
176
177 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
178 NT_STATUS_HAVE_NO_MEMORY(ctx);
179
180 status = wbc_xids_to_sids_recv(ctx, &ids);
181 NT_STATUS_NOT_OK_RETURN(status);
182
183 sd->owner_sid = talloc_steal(sd, ids[0].sid);
184 sd->group_sid = talloc_steal(sd, ids[1].sid);
185
186 talloc_free(ids);
187 sd->type |= SEC_DESC_DACL_PRESENT;
188
189 mode = name->st.st_mode;
190
191 /*
192 we provide up to 4 ACEs
193 - Owner
194 - Group
195 - Everyone
196 - Administrator
197 */
198
199
200 /* setup owner ACE */
201 ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
202 ace.flags = 0;
203 ace.trustee = *sd->owner_sid;
204 ace.access_mask = 0;
205
206 if (mode & S_IRUSR) {
207 if (mode & S_IWUSR) {
208 ace.access_mask |= SEC_RIGHTS_FILE_ALL;
209 } else {
210 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
211 }
212 }
213 if (mode & S_IWUSR) {
214 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
215 }
216 if (ace.access_mask) {
217 security_descriptor_dacl_add(sd, &ace);
218 }
219
220
221 /* setup group ACE */
222 ace.trustee = *sd->group_sid;
223 ace.access_mask = 0;
224 if (mode & S_IRGRP) {
225 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
226 }
227 if (mode & S_IWGRP) {
228 /* note that delete is not granted - this matches posix behaviour */
229 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
230 }
231 if (ace.access_mask) {
232 security_descriptor_dacl_add(sd, &ace);
233 }
234
235 /* setup other ACE */
236 ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
237 ace.access_mask = 0;
238 if (mode & S_IROTH) {
239 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
240 }
241 if (mode & S_IWOTH) {
242 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
243 }
244 if (ace.access_mask) {
245 security_descriptor_dacl_add(sd, &ace);
246 }
247
248 /* setup system ACE */
249 ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
250 ace.access_mask = SEC_RIGHTS_FILE_ALL;
251 security_descriptor_dacl_add(sd, &ace);
252
253 return NT_STATUS_OK;
254 }
255
256
257 /*
258 omit any security_descriptor elements not specified in the given
259 secinfo flags
260 */
261 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
/* [<][>][^][v][top][bottom][index][help] */
262 {
263 if (!(secinfo_flags & SECINFO_OWNER)) {
264 sd->owner_sid = NULL;
265 }
266 if (!(secinfo_flags & SECINFO_GROUP)) {
267 sd->group_sid = NULL;
268 }
269 if (!(secinfo_flags & SECINFO_DACL)) {
270 sd->dacl = NULL;
271 }
272 if (!(secinfo_flags & SECINFO_SACL)) {
273 sd->sacl = NULL;
274 }
275 }
276
277 /*
278 answer a setfileinfo for an ACL
279 */
280 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
281 struct ntvfs_request *req,
282 struct pvfs_filename *name, int fd,
283 uint32_t access_mask,
284 union smb_setfileinfo *info)
285 {
286 uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
287 struct security_descriptor *new_sd, *sd, orig_sd;
288 NTSTATUS status = NT_STATUS_NOT_FOUND;
289 uid_t old_uid = -1;
290 gid_t old_gid = -1;
291 uid_t new_uid = -1;
292 gid_t new_gid = -1;
293 struct id_mapping *ids;
294 struct composite_context *ctx;
295
296 if (pvfs->acl_ops != NULL) {
297 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
298 }
299 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
300 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
301 }
302 if (!NT_STATUS_IS_OK(status)) {
303 return status;
304 }
305
306 ids = talloc(req, struct id_mapping);
307 NT_STATUS_HAVE_NO_MEMORY(ids);
308 ids->unixid = NULL;
309 ids->sid = NULL;
310 ids->status = NT_STATUS_NONE_MAPPED;
311
312 new_sd = info->set_secdesc.in.sd;
313 orig_sd = *sd;
314
315 old_uid = name->st.st_uid;
316 old_gid = name->st.st_gid;
317
318 /* only set the elements that have been specified */
319 if (secinfo_flags & SECINFO_OWNER) {
320 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
321 return NT_STATUS_ACCESS_DENIED;
322 }
323 if (!dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
324 ids->sid = new_sd->owner_sid;
325 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
326 NT_STATUS_HAVE_NO_MEMORY(ctx);
327 status = wbc_sids_to_xids_recv(ctx, &ids);
328 NT_STATUS_NOT_OK_RETURN(status);
329
330 if (ids->unixid->type == ID_TYPE_BOTH ||
331 ids->unixid->type == ID_TYPE_UID) {
332 new_uid = ids->unixid->id;
333 }
334 }
335 sd->owner_sid = new_sd->owner_sid;
336 }
337 if (secinfo_flags & SECINFO_GROUP) {
338 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
339 return NT_STATUS_ACCESS_DENIED;
340 }
341 if (!dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
342 ids->sid = new_sd->group_sid;
343 ctx = wbc_sids_to_xids_send(pvfs->wbc_ctx, ids, 1, ids);
344 NT_STATUS_HAVE_NO_MEMORY(ctx);
345 status = wbc_sids_to_xids_recv(ctx, &ids);
346 NT_STATUS_NOT_OK_RETURN(status);
347
348 if (ids->unixid->type == ID_TYPE_BOTH ||
349 ids->unixid->type == ID_TYPE_GID) {
350 new_gid = ids->unixid->id;
351 }
352
353 }
354 sd->group_sid = new_sd->group_sid;
355 }
356 if (secinfo_flags & SECINFO_DACL) {
357 if (!(access_mask & SEC_STD_WRITE_DAC)) {
358 return NT_STATUS_ACCESS_DENIED;
359 }
360 sd->dacl = new_sd->dacl;
361 pvfs_translate_generic_bits(sd->dacl);
362 }
363 if (secinfo_flags & SECINFO_SACL) {
364 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
365 return NT_STATUS_ACCESS_DENIED;
366 }
367 sd->sacl = new_sd->sacl;
368 pvfs_translate_generic_bits(sd->sacl);
369 }
370
371 if (new_uid == old_uid) {
372 new_uid = -1;
373 }
374
375 if (new_gid == old_gid) {
376 new_gid = -1;
377 }
378
379 /* if there's something to change try it */
380 if (new_uid != -1 || new_gid != -1) {
381 int ret;
382 if (fd == -1) {
383 ret = chown(name->full_name, new_uid, new_gid);
384 } else {
385 ret = fchown(fd, new_uid, new_gid);
386 }
387 if (ret == -1) {
388 return pvfs_map_errno(pvfs, errno);
389 }
390 }
391
392 /* we avoid saving if the sd is the same. This means when clients
393 copy files and end up copying the default sd that we don't
394 needlessly use xattrs */
395 if (!security_descriptor_equal(sd, &orig_sd) && pvfs->acl_ops) {
396 status = pvfs->acl_ops->acl_save(pvfs, name, fd, sd);
397 }
398
399 return status;
400 }
401
402
403 /*
404 answer a fileinfo query for the ACL
405 */
406 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
407 struct ntvfs_request *req,
408 struct pvfs_filename *name, int fd,
409 union smb_fileinfo *info)
410 {
411 NTSTATUS status = NT_STATUS_NOT_FOUND;
412 struct security_descriptor *sd;
413
414 if (pvfs->acl_ops) {
415 status = pvfs->acl_ops->acl_load(pvfs, name, fd, req, &sd);
416 }
417 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
418 status = pvfs_default_acl(pvfs, req, name, fd, &sd);
419 }
420 if (!NT_STATUS_IS_OK(status)) {
421 return status;
422 }
423
424 normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
425
426 info->query_secdesc.out.sd = sd;
427
428 return NT_STATUS_OK;
429 }
430
431
432 /*
433 check the read only bit against any of the write access bits
434 */
435 static bool pvfs_read_only(struct pvfs_state *pvfs, uint32_t access_mask)
/* [<][>][^][v][top][bottom][index][help] */
436 {
437 if ((pvfs->flags & PVFS_FLAG_READONLY) &&
438 (access_mask & (SEC_FILE_WRITE_DATA |
439 SEC_FILE_APPEND_DATA |
440 SEC_FILE_WRITE_EA |
441 SEC_FILE_WRITE_ATTRIBUTE |
442 SEC_STD_DELETE |
443 SEC_STD_WRITE_DAC |
444 SEC_STD_WRITE_OWNER |
445 SEC_DIR_DELETE_CHILD))) {
446 return true;
447 }
448 return false;
449 }
450
451 /*
452 default access check function based on unix permissions
453 doing this saves on building a full security descriptor
454 for the common case of access check on files with no
455 specific NT ACL
456 */
457 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
458 struct ntvfs_request *req,
459 struct pvfs_filename *name,
460 uint32_t *access_mask)
461 {
462 uid_t uid = geteuid();
463 uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
464
465 if (pvfs_read_only(pvfs, *access_mask)) {
466 return NT_STATUS_ACCESS_DENIED;
467 }
468
469 /* owner and root get extra permissions */
470 if (uid == 0) {
471 max_bits |= SEC_STD_ALL | SEC_FLAG_SYSTEM_SECURITY;
472 } else if (uid == name->st.st_uid) {
473 max_bits |= SEC_STD_ALL;
474 }
475
476 if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
477 *access_mask = max_bits;
478 return NT_STATUS_OK;
479 }
480
481 if (uid != 0 && (*access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
482 return NT_STATUS_ACCESS_DENIED;
483 }
484
485 if (*access_mask & ~max_bits) {
486 return NT_STATUS_ACCESS_DENIED;
487 }
488
489 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
490 /* on SMB, this bit is always granted, even if not
491 asked for */
492 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
493 }
494
495 return NT_STATUS_OK;
496 }
497
498
499 /*
500 check the security descriptor on a file, if any
501
502 *access_mask is modified with the access actually granted
503 */
504 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
505 struct ntvfs_request *req,
506 struct pvfs_filename *name,
507 uint32_t *access_mask)
508 {
509 struct security_token *token = req->session_info->security_token;
510 struct xattr_NTACL *acl;
511 NTSTATUS status;
512 struct security_descriptor *sd;
513
514 /* on SMB2 a blank access mask is always denied */
515 if (pvfs->ntvfs->ctx->protocol == PROTOCOL_SMB2 &&
516 *access_mask == 0) {
517 return NT_STATUS_ACCESS_DENIED;
518 }
519
520 if (pvfs_read_only(pvfs, *access_mask)) {
521 return NT_STATUS_ACCESS_DENIED;
522 }
523
524 acl = talloc(req, struct xattr_NTACL);
525 if (acl == NULL) {
526 return NT_STATUS_NO_MEMORY;
527 }
528
529 /* expand the generic access bits to file specific bits */
530 *access_mask = pvfs_translate_mask(*access_mask);
531 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
532 *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
533 }
534
535 status = pvfs_acl_load(pvfs, name, -1, acl);
536 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
537 talloc_free(acl);
538 return pvfs_access_check_unix(pvfs, req, name, access_mask);
539 }
540 if (!NT_STATUS_IS_OK(status)) {
541 return status;
542 }
543
544 switch (acl->version) {
545 case 1:
546 sd = acl->info.sd;
547 break;
548 default:
549 return NT_STATUS_INVALID_ACL;
550 }
551
552 /* check the acl against the required access mask */
553 status = sec_access_check(sd, token, *access_mask, access_mask);
554
555 if (pvfs->ntvfs->ctx->protocol != PROTOCOL_SMB2) {
556 /* on SMB, this bit is always granted, even if not
557 asked for */
558 *access_mask |= SEC_FILE_READ_ATTRIBUTE;
559 }
560
561 talloc_free(acl);
562
563 return status;
564 }
565
566
567 /*
568 a simplified interface to access check, designed for calls that
569 do not take or return an access check mask
570 */
571 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
572 struct ntvfs_request *req,
573 struct pvfs_filename *name,
574 uint32_t access_needed)
575 {
576 if (access_needed == 0) {
577 return NT_STATUS_OK;
578 }
579 return pvfs_access_check(pvfs, req, name, &access_needed);
580 }
581
582 /*
583 access check for creating a new file/directory
584 */
585 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
586 struct ntvfs_request *req,
587 struct pvfs_filename *name,
588 uint32_t *access_mask)
589 {
590 struct pvfs_filename *parent;
591 NTSTATUS status;
592
593 status = pvfs_resolve_parent(pvfs, req, name, &parent);
594 if (!NT_STATUS_IS_OK(status)) {
595 return status;
596 }
597
598 status = pvfs_access_check(pvfs, req, parent, access_mask);
599 if (!NT_STATUS_IS_OK(status)) {
600 return status;
601 }
602
603 if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
604 return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
605 }
606
607 return status;
608 }
609
610 /*
611 access check for creating a new file/directory - no access mask supplied
612 */
613 NTSTATUS pvfs_access_check_parent(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
614 struct ntvfs_request *req,
615 struct pvfs_filename *name,
616 uint32_t access_mask)
617 {
618 struct pvfs_filename *parent;
619 NTSTATUS status;
620
621 status = pvfs_resolve_parent(pvfs, req, name, &parent);
622 if (!NT_STATUS_IS_OK(status)) {
623 return status;
624 }
625
626 return pvfs_access_check_simple(pvfs, req, parent, access_mask);
627 }
628
629
630 /*
631 determine if an ACE is inheritable
632 */
633 static bool pvfs_inheritable_ace(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
634 const struct security_ace *ace,
635 bool container)
636 {
637 if (!container) {
638 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
639 }
640
641 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
642 return true;
643 }
644
645 if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
646 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
647 return true;
648 }
649
650 return false;
651 }
652
653 /*
654 this is the core of ACL inheritance. It copies any inheritable
655 aces from the parent SD to the child SD. Note that the algorithm
656 depends on whether the child is a container or not
657 */
658 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
659 struct security_descriptor *parent_sd,
660 struct security_descriptor *sd,
661 bool container)
662 {
663 int i;
664
665 for (i=0;i<parent_sd->dacl->num_aces;i++) {
666 struct security_ace ace = parent_sd->dacl->aces[i];
667 NTSTATUS status;
668 const struct dom_sid *creator = NULL, *new_id = NULL;
669 uint32_t orig_flags;
670
671 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
672 continue;
673 }
674
675 orig_flags = ace.flags;
676
677 /* see the RAW-ACLS inheritance test for details on these rules */
678 if (!container) {
679 ace.flags = 0;
680 } else {
681 ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
682
683 if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
684 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
685 }
686 if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
687 ace.flags = 0;
688 }
689 }
690
691 /* the CREATOR sids are special when inherited */
692 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
693 creator = pvfs->sid_cache.creator_owner;
694 new_id = sd->owner_sid;
695 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
696 creator = pvfs->sid_cache.creator_group;
697 new_id = sd->group_sid;
698 } else {
699 new_id = &ace.trustee;
700 }
701
702 if (creator && container &&
703 (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
704 uint32_t flags = ace.flags;
705
706 ace.trustee = *new_id;
707 ace.flags = 0;
708 status = security_descriptor_dacl_add(sd, &ace);
709 if (!NT_STATUS_IS_OK(status)) {
710 return status;
711 }
712
713 ace.trustee = *creator;
714 ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
715 status = security_descriptor_dacl_add(sd, &ace);
716 } else if (container &&
717 !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
718 status = security_descriptor_dacl_add(sd, &ace);
719 } else {
720 ace.trustee = *new_id;
721 status = security_descriptor_dacl_add(sd, &ace);
722 }
723
724 if (!NT_STATUS_IS_OK(status)) {
725 return status;
726 }
727 }
728
729 return NT_STATUS_OK;
730 }
731
732
733
734 /*
735 setup an ACL on a new file/directory based on the inherited ACL from
736 the parent. If there is no inherited ACL then we don't set anything,
737 as the default ACL applies anyway
738 */
739 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
740 struct ntvfs_request *req,
741 struct pvfs_filename *name,
742 int fd)
743 {
744 struct xattr_NTACL *acl;
745 NTSTATUS status;
746 struct pvfs_filename *parent;
747 struct security_descriptor *parent_sd, *sd;
748 bool container;
749 struct id_mapping *ids;
750 struct composite_context *ctx;
751
752 /* form the parents path */
753 status = pvfs_resolve_parent(pvfs, req, name, &parent);
754 if (!NT_STATUS_IS_OK(status)) {
755 return status;
756 }
757
758 acl = talloc(req, struct xattr_NTACL);
759 if (acl == NULL) {
760 return NT_STATUS_NO_MEMORY;
761 }
762
763 status = pvfs_acl_load(pvfs, parent, -1, acl);
764 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
765 return NT_STATUS_OK;
766 }
767 if (!NT_STATUS_IS_OK(status)) {
768 return status;
769 }
770
771 switch (acl->version) {
772 case 1:
773 parent_sd = acl->info.sd;
774 break;
775 default:
776 return NT_STATUS_INVALID_ACL;
777 }
778
779 if (parent_sd == NULL ||
780 parent_sd->dacl == NULL ||
781 parent_sd->dacl->num_aces == 0) {
782 /* go with the default ACL */
783 return NT_STATUS_OK;
784 }
785
786 /* create the new sd */
787 sd = security_descriptor_initialise(req);
788 if (sd == NULL) {
789 return NT_STATUS_NO_MEMORY;
790 }
791
792 ids = talloc_array(sd, struct id_mapping, 2);
793 NT_STATUS_HAVE_NO_MEMORY(ids);
794
795 ids[0].unixid = talloc(ids, struct unixid);
796 NT_STATUS_HAVE_NO_MEMORY(ids[0].unixid);
797 ids[0].unixid->id = name->st.st_uid;
798 ids[0].unixid->type = ID_TYPE_UID;
799 ids[0].sid = NULL;
800 ids[0].status = NT_STATUS_NONE_MAPPED;
801
802 ids[1].unixid = talloc(ids, struct unixid);
803 NT_STATUS_HAVE_NO_MEMORY(ids[1].unixid);
804 ids[1].unixid->id = name->st.st_gid;
805 ids[1].unixid->type = ID_TYPE_GID;
806 ids[1].sid = NULL;
807 ids[1].status = NT_STATUS_NONE_MAPPED;
808
809 ctx = wbc_xids_to_sids_send(pvfs->wbc_ctx, ids, 2, ids);
810 NT_STATUS_HAVE_NO_MEMORY(ctx);
811
812 status = wbc_xids_to_sids_recv(ctx, &ids);
813 NT_STATUS_NOT_OK_RETURN(status);
814
815 sd->owner_sid = talloc_steal(sd, ids[0].sid);
816 sd->group_sid = talloc_steal(sd, ids[1].sid);
817
818 sd->type |= SEC_DESC_DACL_PRESENT;
819
820 container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? true:false;
821
822 /* fill in the aces from the parent */
823 status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
824 if (!NT_STATUS_IS_OK(status)) {
825 return status;
826 }
827
828 /* if there is nothing to inherit then we fallback to the
829 default acl */
830 if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
831 return NT_STATUS_OK;
832 }
833
834 acl->info.sd = sd;
835
836 status = pvfs_acl_save(pvfs, name, fd, acl);
837
838 return status;
839 }
840
841 /*
842 return the maximum allowed access mask
843 */
844 NTSTATUS pvfs_access_maximal_allowed(struct pvfs_state *pvfs,
/* [<][>][^][v][top][bottom][index][help] */
845 struct ntvfs_request *req,
846 struct pvfs_filename *name,
847 uint32_t *maximal_access)
848 {
849 *maximal_access = SEC_FLAG_MAXIMUM_ALLOWED;
850 return pvfs_access_check(pvfs, req, name, maximal_access);
851 }