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