ce5f3a248b21f75c6f7133e4ca7726e6edc4863d
[samba.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;
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
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         status = pvfs_acl_save(pvfs, name, fd, acl);
269
270         return status;
271 }
272
273
274 /*
275   answer a fileinfo query for the ACL
276 */
277 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
278                         struct smbsrv_request *req,
279                         struct pvfs_filename *name, int fd, 
280                         union smb_fileinfo *info)
281 {
282         struct xattr_NTACL *acl;
283         NTSTATUS status;
284         struct security_descriptor *sd;
285
286         acl = talloc_p(req, struct xattr_NTACL);
287         if (acl == NULL) {
288                 return NT_STATUS_NO_MEMORY;
289         }
290
291         status = pvfs_acl_load(pvfs, name, fd, acl);
292         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
293                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
294         }
295         if (!NT_STATUS_IS_OK(status)) {
296                 return status;
297         }
298
299         switch (acl->version) {
300         case 1:
301                 sd = acl->info.sd;
302                 break;
303         default:
304                 return NT_STATUS_INVALID_ACL;
305         }
306
307         normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
308
309         info->query_secdesc.out.sd = sd;
310
311         return NT_STATUS_OK;
312 }
313
314
315 /*
316   default access check function based on unix permissions
317   doing this saves on building a full security descriptor
318   for the common case of access check on files with no 
319   specific NT ACL
320 */
321 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
322                                 struct smbsrv_request *req,
323                                 struct pvfs_filename *name,
324                                 uint32_t *access_mask)
325 {
326         uid_t uid = geteuid();
327         uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
328
329         /* owner and root get extra permissions */
330         if (uid == 0 || uid == name->st.st_uid) {
331                 max_bits |= SEC_STD_ALL;
332         }
333
334         if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
335                 *access_mask = max_bits;
336                 return NT_STATUS_OK;
337         }
338
339         if (*access_mask & ~max_bits) {
340                 return NT_STATUS_ACCESS_DENIED;
341         }
342
343         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
344
345         return NT_STATUS_OK;
346 }
347
348
349 /*
350   check the security descriptor on a file, if any
351   
352   *access_mask is modified with the access actually granted
353 */
354 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
355                            struct smbsrv_request *req,
356                            struct pvfs_filename *name,
357                            uint32_t *access_mask)
358 {
359         struct security_token *token = req->session->session_info->security_token;
360         struct xattr_NTACL *acl;
361         NTSTATUS status;
362         struct security_descriptor *sd;
363
364         acl = talloc_p(req, struct xattr_NTACL);
365         if (acl == NULL) {
366                 return NT_STATUS_NO_MEMORY;
367         }
368
369         status = pvfs_acl_load(pvfs, name, -1, acl);
370         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
371                 talloc_free(acl);
372                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
373         }
374         if (!NT_STATUS_IS_OK(status)) {
375                 return status;
376         }
377
378         switch (acl->version) {
379         case 1:
380                 sd = acl->info.sd;
381                 break;
382         default:
383                 return NT_STATUS_INVALID_ACL;
384         }
385
386         /* expand the generic access bits to file specific bits */
387         *access_mask = pvfs_translate_mask(*access_mask);
388
389         /* check the acl against the required access mask */
390         status = sec_access_check(sd, token, *access_mask, access_mask);
391
392         /* this bit is always granted, even if not asked for */
393         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
394
395         talloc_free(acl);
396         
397         return status;
398 }
399
400
401 /*
402   a simplified interface to access check, designed for calls that
403   do not take or return an access check mask
404 */
405 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
406                                   struct smbsrv_request *req,
407                                   struct pvfs_filename *name,
408                                   uint32_t access_needed)
409 {
410         if (access_needed == 0) {
411                 return NT_STATUS_OK;
412         }
413         return pvfs_access_check(pvfs, req, name, &access_needed);
414 }
415
416 /*
417   access check for creating a new file/directory
418 */
419 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
420                                   struct smbsrv_request *req,
421                                   struct pvfs_filename *name)
422 {
423         struct pvfs_filename *parent;
424         NTSTATUS status;
425
426         status = pvfs_resolve_parent(pvfs, req, name, &parent);
427         if (!NT_STATUS_IS_OK(status)) {
428                 return status;
429         }
430
431         return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
432 }
433
434
435 /*
436   determine if an ACE is inheritable
437 */
438 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
439                                  const struct security_ace *ace,
440                                  BOOL container)
441 {
442         if (!container) {
443                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
444         }
445
446         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
447                 return True;
448         }
449
450         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
451             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
452                 return True;
453         }
454
455         return False;
456 }
457
458 /*
459   this is the core of ACL inheritance. It copies any inheritable
460   aces from the parent SD to the child SD. Note that the algorithm 
461   depends on whether the child is a container or not
462 */
463 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
464                                       struct security_descriptor *parent_sd,
465                                       struct security_descriptor *sd,
466                                       BOOL container)
467 {
468         int i;
469         
470         for (i=0;i<parent_sd->dacl->num_aces;i++) {
471                 struct security_ace ace = parent_sd->dacl->aces[i];
472                 NTSTATUS status;
473
474                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
475                         continue;
476                 }
477
478                 /* see the RAW-ACLS inheritance test for details on these rules */
479                 if (!container) {
480                         ace.flags = 0;
481                 } else {
482                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
483
484                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
485                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
486                         }
487                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
488                                 ace.flags = 0;
489                         }
490                 }
491
492                 status = security_descriptor_dacl_add(sd, &ace);
493                 if (!NT_STATUS_IS_OK(status)) {
494                         return status;
495                 }
496         }
497
498         return NT_STATUS_OK;
499 }
500
501
502
503 /*
504   setup an ACL on a new file/directory based on the inherited ACL from
505   the parent. If there is no inherited ACL then we don't set anything,
506   as the default ACL applies anyway
507 */
508 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
509                           struct smbsrv_request *req,
510                           struct pvfs_filename *name,
511                           int fd)
512 {
513         struct xattr_NTACL *acl;
514         NTSTATUS status;
515         struct pvfs_filename *parent;
516         struct security_descriptor *parent_sd, *sd;
517         BOOL container;
518
519         /* form the parents path */
520         status = pvfs_resolve_parent(pvfs, req, name, &parent);
521         if (!NT_STATUS_IS_OK(status)) {
522                 return status;
523         }
524
525         acl = talloc_p(req, struct xattr_NTACL);
526         if (acl == NULL) {
527                 return NT_STATUS_NO_MEMORY;
528         }
529
530         status = pvfs_acl_load(pvfs, parent, -1, acl);
531         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
532                 return NT_STATUS_OK;
533         }
534         if (!NT_STATUS_IS_OK(status)) {
535                 return status;
536         }
537
538         switch (acl->version) {
539         case 1:
540                 parent_sd = acl->info.sd;
541                 break;
542         default:
543                 return NT_STATUS_INVALID_ACL;
544         }
545
546         if (parent_sd == NULL ||
547             parent_sd->dacl == NULL ||
548             parent_sd->dacl->num_aces == 0) {
549                 /* go with the default ACL */
550                 return NT_STATUS_OK;
551         }
552
553         /* create the new sd */
554         sd = security_descriptor_initialise(req);
555         if (sd == NULL) {
556                 return NT_STATUS_NO_MEMORY;
557         }
558
559         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
560         if (!NT_STATUS_IS_OK(status)) {
561                 return status;
562         }
563         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
564         if (!NT_STATUS_IS_OK(status)) {
565                 return status;
566         }
567
568         sd->type |= SEC_DESC_DACL_PRESENT;
569
570         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
571
572         /* fill in the aces from the parent */
573         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
574         if (!NT_STATUS_IS_OK(status)) {
575                 return status;
576         }
577
578         /* if there is nothing to inherit then we fallback to the
579            default acl */
580         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
581                 return NT_STATUS_OK;
582         }
583
584         acl->info.sd = sd;
585
586         status = pvfs_acl_save(pvfs, name, fd, acl);
587         
588         return status;
589 }