r4584: fix pvfs backend to pass the new enhanced RAW-ACLS test. Easy once I really the
[gd/samba-autobuild/.git] / source4 / ntvfs / posix / pvfs_acl.c
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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "auth/auth.h"
25 #include "system/filesys.h"
26 #include "vfs_posix.h"
27 #include "librpc/gen_ndr/ndr_xattr.h"
28
29
30 /*
31   map a single access_mask from generic to specific bits for files/dirs
32 */
33 static uint32_t pvfs_translate_mask(uint32_t access_mask)
34 {
35         if (access_mask & SEC_MASK_GENERIC) {
36                 if (access_mask & SEC_GENERIC_READ)    access_mask |= SEC_RIGHTS_FILE_READ;
37                 if (access_mask & SEC_GENERIC_WRITE)   access_mask |= SEC_RIGHTS_FILE_WRITE;
38                 if (access_mask & SEC_GENERIC_EXECUTE) access_mask |= SEC_RIGHTS_FILE_EXECUTE;
39                 if (access_mask & SEC_GENERIC_ALL)     access_mask |= SEC_RIGHTS_FILE_ALL;
40                 access_mask &= ~SEC_MASK_GENERIC;
41         }
42         return access_mask;
43 }
44
45
46 /*
47   map any generic access bits in the given acl
48   this relies on the fact that the mappings for files and directories
49   are the same
50 */
51 static void pvfs_translate_generic_bits(struct security_acl *acl)
52 {
53         unsigned i;
54
55         for (i=0;i<acl->num_aces;i++) {
56                 struct security_ace *ace = &acl->aces[i];
57                 ace->access_mask = pvfs_translate_mask(ace->access_mask);
58         }
59 }
60
61
62 /*
63   setup a default ACL for a file
64 */
65 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
66                                  struct smbsrv_request *req,
67                                  struct pvfs_filename *name, int fd, 
68                                  struct xattr_NTACL *acl)
69 {
70         struct security_descriptor *sd;
71         NTSTATUS status;
72         struct security_ace ace;
73         mode_t mode;
74
75         sd = security_descriptor_initialise(req);
76         if (sd == NULL) {
77                 return NT_STATUS_NO_MEMORY;
78         }
79
80         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
81         if (!NT_STATUS_IS_OK(status)) {
82                 return status;
83         }
84         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
85         if (!NT_STATUS_IS_OK(status)) {
86                 return status;
87         }
88
89         sd->type |= SEC_DESC_DACL_PRESENT;
90
91         mode = name->st.st_mode;
92
93         /*
94           we provide up to 4 ACEs
95             - Owner
96             - Group
97             - Everyone
98             - Administrator
99          */
100
101
102         /* setup owner ACE */
103         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
104         ace.flags = 0;
105         ace.trustee = *sd->owner_sid;
106         ace.access_mask = 0;
107
108         if (mode & S_IRUSR) {
109                 if (mode & S_IWUSR) {
110                         ace.access_mask |= SEC_RIGHTS_FILE_ALL;
111                 } else {
112                         ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
113                 }
114         }
115         if (mode & S_IWUSR) {
116                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
117         }
118         if (ace.access_mask) {
119                 security_descriptor_dacl_add(sd, &ace);
120         }
121
122
123         /* setup group ACE */
124         ace.trustee = *sd->group_sid;
125         ace.access_mask = 0;
126         if (mode & S_IRGRP) {
127                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
128         }
129         if (mode & S_IWGRP) {
130                 /* note that delete is not granted - this matches posix behaviour */
131                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
132         }
133         if (ace.access_mask) {
134                 security_descriptor_dacl_add(sd, &ace);
135         }
136
137         /* setup other ACE */
138         ace.trustee = *dom_sid_parse_talloc(req, SID_WORLD);
139         ace.access_mask = 0;
140         if (mode & S_IROTH) {
141                 ace.access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
142         }
143         if (mode & S_IWOTH) {
144                 ace.access_mask |= SEC_RIGHTS_FILE_WRITE;
145         }
146         if (ace.access_mask) {
147                 security_descriptor_dacl_add(sd, &ace);
148         }
149
150         /* setup system ACE */
151         ace.trustee = *dom_sid_parse_talloc(req, SID_NT_SYSTEM);
152         ace.access_mask = SEC_RIGHTS_FILE_ALL;
153         security_descriptor_dacl_add(sd, &ace);
154         
155         acl->version = 1;
156         acl->info.sd = sd;
157
158         return NT_STATUS_OK;
159 }
160                                  
161
162 /*
163   omit any security_descriptor elements not specified in the given
164   secinfo flags
165 */
166 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
167 {
168         if (!(secinfo_flags & SECINFO_OWNER)) {
169                 sd->owner_sid = NULL;
170         }
171         if (!(secinfo_flags & SECINFO_GROUP)) {
172                 sd->group_sid = NULL;
173         }
174         if (!(secinfo_flags & SECINFO_DACL)) {
175                 sd->dacl = NULL;
176         }
177         if (!(secinfo_flags & SECINFO_SACL)) {
178                 sd->sacl = NULL;
179         }
180 }
181
182 /*
183   answer a setfileinfo for an ACL
184 */
185 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, 
186                       struct smbsrv_request *req,
187                       struct pvfs_filename *name, int fd, 
188                       uint32_t access_mask,
189                       union smb_setfileinfo *info)
190 {
191         struct xattr_NTACL *acl;
192         uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
193         struct security_descriptor *new_sd, *sd, orig_sd;
194         NTSTATUS status;
195         uid_t uid = -1;
196         gid_t gid = -1;
197
198         acl = talloc_p(req, struct xattr_NTACL);
199         if (acl == NULL) {
200                 return NT_STATUS_NO_MEMORY;
201         }
202
203         status = pvfs_acl_load(pvfs, name, fd, acl);
204         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
205                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
206         }
207         if (!NT_STATUS_IS_OK(status)) {
208                 return status;
209         }
210
211         switch (acl->version) {
212         case 1:
213                 sd = acl->info.sd;
214                 break;
215         default:
216                 return NT_STATUS_INVALID_ACL;
217         }
218
219         new_sd = info->set_secdesc.in.sd;
220         orig_sd = *sd;
221
222         uid = name->st.st_uid;
223         gid = name->st.st_gid;
224
225         /* only set the elements that have been specified */
226         if ((secinfo_flags & SECINFO_OWNER) && 
227             !dom_sid_equal(sd->owner_sid, new_sd->owner_sid)) {
228                 if (!(access_mask & SEC_STD_WRITE_OWNER)) {
229                         return NT_STATUS_ACCESS_DENIED;
230                 }
231                 sd->owner_sid = new_sd->owner_sid;
232                 status = sidmap_sid_to_unixuid(pvfs->sidmap, sd->owner_sid, &uid);
233                 if (!NT_STATUS_IS_OK(status)) {
234                         return status;
235                 }
236         }
237         if ((secinfo_flags & SECINFO_GROUP) &&
238             !dom_sid_equal(sd->group_sid, new_sd->group_sid)) {
239                 sd->group_sid = new_sd->group_sid;
240                 status = sidmap_sid_to_unixgid(pvfs->sidmap, sd->owner_sid, &gid);
241                 if (!NT_STATUS_IS_OK(status)) {
242                         return status;
243                 }
244         }
245         if (secinfo_flags & SECINFO_DACL) {
246                 sd->dacl = new_sd->dacl;
247                 pvfs_translate_generic_bits(sd->dacl);
248         }
249         if (secinfo_flags & SECINFO_SACL) {
250                 sd->sacl = new_sd->sacl;
251                 if (!(access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
252                         return NT_STATUS_ACCESS_DENIED;
253                 }
254                 pvfs_translate_generic_bits(sd->sacl);
255         }
256
257         if (uid != -1 || gid != -1) {
258                 int ret;
259                 if (fd == -1) {
260                         ret = chown(name->full_name, uid, gid);
261                 } else {
262                         ret = fchown(fd, uid, gid);
263                 }
264                 if (ret == -1) {
265                         return pvfs_map_errno(pvfs, errno);
266                 }
267         }
268
269         /* we avoid saving if the sd is the same. This means when clients
270            copy files and end up copying the default sd that we don't
271            needlessly use xattrs */
272         if (!security_descriptor_equal(sd, &orig_sd)) {
273                 status = pvfs_acl_save(pvfs, name, fd, acl);
274         }
275
276         return status;
277 }
278
279
280 /*
281   answer a fileinfo query for the ACL
282 */
283 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
284                         struct smbsrv_request *req,
285                         struct pvfs_filename *name, int fd, 
286                         union smb_fileinfo *info)
287 {
288         struct xattr_NTACL *acl;
289         NTSTATUS status;
290         struct security_descriptor *sd;
291
292         acl = talloc_p(req, struct xattr_NTACL);
293         if (acl == NULL) {
294                 return NT_STATUS_NO_MEMORY;
295         }
296
297         status = pvfs_acl_load(pvfs, name, fd, acl);
298         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
299                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
300         }
301         if (!NT_STATUS_IS_OK(status)) {
302                 return status;
303         }
304
305         switch (acl->version) {
306         case 1:
307                 sd = acl->info.sd;
308                 break;
309         default:
310                 return NT_STATUS_INVALID_ACL;
311         }
312
313         normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
314
315         info->query_secdesc.out.sd = sd;
316
317         return NT_STATUS_OK;
318 }
319
320
321 /*
322   default access check function based on unix permissions
323   doing this saves on building a full security descriptor
324   for the common case of access check on files with no 
325   specific NT ACL
326 */
327 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
328                                 struct smbsrv_request *req,
329                                 struct pvfs_filename *name,
330                                 uint32_t *access_mask)
331 {
332         uid_t uid = geteuid();
333         uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
334
335         /* owner and root get extra permissions */
336         if (uid == 0 || uid == name->st.st_uid) {
337                 max_bits |= SEC_STD_ALL;
338         }
339
340         if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
341                 *access_mask = max_bits;
342                 return NT_STATUS_OK;
343         }
344
345         if (*access_mask & ~max_bits) {
346                 return NT_STATUS_ACCESS_DENIED;
347         }
348
349         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
350
351         return NT_STATUS_OK;
352 }
353
354
355 /*
356   check the security descriptor on a file, if any
357   
358   *access_mask is modified with the access actually granted
359 */
360 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
361                            struct smbsrv_request *req,
362                            struct pvfs_filename *name,
363                            uint32_t *access_mask)
364 {
365         struct security_token *token = req->session->session_info->security_token;
366         struct xattr_NTACL *acl;
367         NTSTATUS status;
368         struct security_descriptor *sd;
369
370         acl = talloc_p(req, struct xattr_NTACL);
371         if (acl == NULL) {
372                 return NT_STATUS_NO_MEMORY;
373         }
374
375         status = pvfs_acl_load(pvfs, name, -1, acl);
376         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
377                 talloc_free(acl);
378                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
379         }
380         if (!NT_STATUS_IS_OK(status)) {
381                 return status;
382         }
383
384         switch (acl->version) {
385         case 1:
386                 sd = acl->info.sd;
387                 break;
388         default:
389                 return NT_STATUS_INVALID_ACL;
390         }
391
392         /* expand the generic access bits to file specific bits */
393         *access_mask = pvfs_translate_mask(*access_mask);
394
395         *access_mask &= ~SEC_FILE_READ_ATTRIBUTE;
396
397         /* check the acl against the required access mask */
398         status = sec_access_check(sd, token, *access_mask, access_mask);
399
400         /* this bit is always granted, even if not asked for */
401         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
402
403         talloc_free(acl);
404         
405         return status;
406 }
407
408
409 /*
410   a simplified interface to access check, designed for calls that
411   do not take or return an access check mask
412 */
413 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
414                                   struct smbsrv_request *req,
415                                   struct pvfs_filename *name,
416                                   uint32_t access_needed)
417 {
418         if (access_needed == 0) {
419                 return NT_STATUS_OK;
420         }
421         return pvfs_access_check(pvfs, req, name, &access_needed);
422 }
423
424 /*
425   access check for creating a new file/directory
426 */
427 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
428                                   struct smbsrv_request *req,
429                                   struct pvfs_filename *name,
430                                   uint32_t *access_mask)
431 {
432         struct pvfs_filename *parent;
433         NTSTATUS status;
434
435         status = pvfs_resolve_parent(pvfs, req, name, &parent);
436         if (!NT_STATUS_IS_OK(status)) {
437                 return status;
438         }
439
440         status = pvfs_access_check(pvfs, req, parent, access_mask);
441         if (!NT_STATUS_IS_OK(status)) {
442                 return status;
443         }
444
445         if (! ((*access_mask) & SEC_DIR_ADD_FILE)) {
446                 return pvfs_access_check_simple(pvfs, req, name, SEC_DIR_ADD_FILE);
447         }
448
449         return status;
450 }
451
452 /*
453   access check for creating a new file/directory - no access mask supplied
454 */
455 NTSTATUS pvfs_access_check_create_nomask(struct pvfs_state *pvfs, 
456                                          struct smbsrv_request *req,
457                                          struct pvfs_filename *name)
458 {
459         struct pvfs_filename *parent;
460         NTSTATUS status;
461
462         status = pvfs_resolve_parent(pvfs, req, name, &parent);
463         if (!NT_STATUS_IS_OK(status)) {
464                 return status;
465         }
466
467         return pvfs_access_check_simple(pvfs, req, name, SEC_DIR_ADD_FILE);
468 }
469
470
471 /*
472   determine if an ACE is inheritable
473 */
474 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
475                                  const struct security_ace *ace,
476                                  BOOL container)
477 {
478         if (!container) {
479                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
480         }
481
482         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
483                 return True;
484         }
485
486         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
487             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
488                 return True;
489         }
490
491         return False;
492 }
493
494 /*
495   this is the core of ACL inheritance. It copies any inheritable
496   aces from the parent SD to the child SD. Note that the algorithm 
497   depends on whether the child is a container or not
498 */
499 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
500                                       struct security_descriptor *parent_sd,
501                                       struct security_descriptor *sd,
502                                       BOOL container)
503 {
504         int i;
505         
506         for (i=0;i<parent_sd->dacl->num_aces;i++) {
507                 struct security_ace ace = parent_sd->dacl->aces[i];
508                 NTSTATUS status;
509                 const struct dom_sid *creator = NULL, *new_id = NULL;
510                 uint32_t orig_flags;
511
512                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
513                         continue;
514                 }
515
516                 orig_flags = ace.flags;
517
518                 /* see the RAW-ACLS inheritance test for details on these rules */
519                 if (!container) {
520                         ace.flags = 0;
521                 } else {
522                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
523
524                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
525                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
526                         }
527                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
528                                 ace.flags = 0;
529                         }
530                 }
531
532                 /* the CREATOR sids are special when inherited */
533                 if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_owner)) {
534                         creator = pvfs->sid_cache.creator_owner;
535                         new_id = sd->owner_sid;
536                 } else if (dom_sid_equal(&ace.trustee, pvfs->sid_cache.creator_group)) {
537                         creator = pvfs->sid_cache.creator_group;
538                         new_id = sd->group_sid;
539                 } else {
540                         new_id = &ace.trustee;
541                 }
542
543                 if (creator && container && 
544                     (ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
545                         uint32_t flags = ace.flags;
546
547                         ace.trustee = *new_id;
548                         ace.flags = 0;
549                         status = security_descriptor_dacl_add(sd, &ace);
550                         if (!NT_STATUS_IS_OK(status)) {
551                                 return status;
552                         }
553
554                         ace.trustee = *creator;
555                         ace.flags = flags | SEC_ACE_FLAG_INHERIT_ONLY;
556                         status = security_descriptor_dacl_add(sd, &ace);
557                 } else if (container && 
558                            !(orig_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
559                         status = security_descriptor_dacl_add(sd, &ace);
560                 } else {
561                         ace.trustee = *new_id;
562                         status = security_descriptor_dacl_add(sd, &ace);
563                 }
564
565                 if (!NT_STATUS_IS_OK(status)) {
566                         return status;
567                 }
568         }
569
570         return NT_STATUS_OK;
571 }
572
573
574
575 /*
576   setup an ACL on a new file/directory based on the inherited ACL from
577   the parent. If there is no inherited ACL then we don't set anything,
578   as the default ACL applies anyway
579 */
580 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
581                           struct smbsrv_request *req,
582                           struct pvfs_filename *name,
583                           int fd)
584 {
585         struct xattr_NTACL *acl;
586         NTSTATUS status;
587         struct pvfs_filename *parent;
588         struct security_descriptor *parent_sd, *sd;
589         BOOL container;
590
591         /* form the parents path */
592         status = pvfs_resolve_parent(pvfs, req, name, &parent);
593         if (!NT_STATUS_IS_OK(status)) {
594                 return status;
595         }
596
597         acl = talloc_p(req, struct xattr_NTACL);
598         if (acl == NULL) {
599                 return NT_STATUS_NO_MEMORY;
600         }
601
602         status = pvfs_acl_load(pvfs, parent, -1, acl);
603         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
604                 return NT_STATUS_OK;
605         }
606         if (!NT_STATUS_IS_OK(status)) {
607                 return status;
608         }
609
610         switch (acl->version) {
611         case 1:
612                 parent_sd = acl->info.sd;
613                 break;
614         default:
615                 return NT_STATUS_INVALID_ACL;
616         }
617
618         if (parent_sd == NULL ||
619             parent_sd->dacl == NULL ||
620             parent_sd->dacl->num_aces == 0) {
621                 /* go with the default ACL */
622                 return NT_STATUS_OK;
623         }
624
625         /* create the new sd */
626         sd = security_descriptor_initialise(req);
627         if (sd == NULL) {
628                 return NT_STATUS_NO_MEMORY;
629         }
630
631         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
632         if (!NT_STATUS_IS_OK(status)) {
633                 return status;
634         }
635         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
636         if (!NT_STATUS_IS_OK(status)) {
637                 return status;
638         }
639
640         sd->type |= SEC_DESC_DACL_PRESENT;
641
642         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
643
644         /* fill in the aces from the parent */
645         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
646         if (!NT_STATUS_IS_OK(status)) {
647                 return status;
648         }
649
650         /* if there is nothing to inherit then we fallback to the
651            default acl */
652         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
653                 return NT_STATUS_OK;
654         }
655
656         acl->info.sd = sd;
657
658         status = pvfs_acl_save(pvfs, name, fd, acl);
659         
660         return status;
661 }