r4403: - added ACL inheritance in the pvfs backend. ACLs are now inherited on
[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                       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;
193         NTSTATUS status;
194
195         acl = talloc_p(req, struct xattr_NTACL);
196         if (acl == NULL) {
197                 return NT_STATUS_NO_MEMORY;
198         }
199
200         status = pvfs_acl_load(pvfs, name, fd, acl);
201         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
202                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
203         }
204         if (!NT_STATUS_IS_OK(status)) {
205                 return status;
206         }
207
208         switch (acl->version) {
209         case 1:
210                 sd = acl->info.sd;
211                 break;
212         default:
213                 return NT_STATUS_INVALID_ACL;
214         }
215
216         new_sd = info->set_secdesc.in.sd;
217
218         /* only set the elements that have been specified */
219         if (secinfo_flags & SECINFO_OWNER) {
220                 sd->owner_sid = new_sd->owner_sid;
221         }
222         if (secinfo_flags & SECINFO_GROUP) {
223                 sd->group_sid = new_sd->group_sid;
224         }
225         if (secinfo_flags & SECINFO_DACL) {
226                 sd->dacl = new_sd->dacl;
227                 pvfs_translate_generic_bits(sd->dacl);
228         }
229         if (secinfo_flags & SECINFO_SACL) {
230                 sd->sacl = new_sd->sacl;
231                 pvfs_translate_generic_bits(sd->sacl);
232         }
233
234         status = pvfs_acl_save(pvfs, name, fd, acl);
235
236         return status;
237 }
238
239
240 /*
241   answer a fileinfo query for the ACL
242 */
243 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
244                         struct smbsrv_request *req,
245                         struct pvfs_filename *name, int fd, 
246                         union smb_fileinfo *info)
247 {
248         struct xattr_NTACL *acl;
249         NTSTATUS status;
250         struct security_descriptor *sd;
251
252         acl = talloc_p(req, struct xattr_NTACL);
253         if (acl == NULL) {
254                 return NT_STATUS_NO_MEMORY;
255         }
256
257         status = pvfs_acl_load(pvfs, name, fd, acl);
258         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
259                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
260         }
261         if (!NT_STATUS_IS_OK(status)) {
262                 return status;
263         }
264
265         switch (acl->version) {
266         case 1:
267                 sd = acl->info.sd;
268                 break;
269         default:
270                 return NT_STATUS_INVALID_ACL;
271         }
272
273         normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
274
275         info->query_secdesc.out.sd = sd;
276
277         return NT_STATUS_OK;
278 }
279
280
281 /*
282   default access check function based on unix permissions
283   doing this saves on building a full security descriptor
284   for the common case of access check on files with no 
285   specific NT ACL
286 */
287 NTSTATUS pvfs_access_check_unix(struct pvfs_state *pvfs, 
288                                 struct smbsrv_request *req,
289                                 struct pvfs_filename *name,
290                                 uint32_t *access_mask)
291 {
292         uid_t uid = geteuid();
293         uint32_t max_bits = SEC_RIGHTS_FILE_READ | SEC_FILE_ALL;
294
295         /* owner and root get extra permissions */
296         if (uid == 0 || uid == name->st.st_uid) {
297                 max_bits |= SEC_STD_ALL;
298         }
299
300         if (*access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
301                 *access_mask = max_bits;
302                 return NT_STATUS_OK;
303         }
304
305         if (*access_mask & ~max_bits) {
306                 return NT_STATUS_ACCESS_DENIED;
307         }
308
309         return NT_STATUS_OK;
310 }
311
312
313 /*
314   check the security descriptor on a file, if any
315   
316   *access_mask is modified with the access actually granted
317 */
318 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
319                            struct smbsrv_request *req,
320                            struct pvfs_filename *name,
321                            uint32_t *access_mask)
322 {
323         struct security_token *token = req->session->session_info->security_token;
324         struct xattr_NTACL *acl;
325         NTSTATUS status;
326         struct security_descriptor *sd;
327
328         acl = talloc_p(req, struct xattr_NTACL);
329         if (acl == NULL) {
330                 return NT_STATUS_NO_MEMORY;
331         }
332
333         status = pvfs_acl_load(pvfs, name, -1, acl);
334         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
335                 talloc_free(acl);
336                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
337         }
338         if (!NT_STATUS_IS_OK(status)) {
339                 return status;
340         }
341
342         switch (acl->version) {
343         case 1:
344                 sd = acl->info.sd;
345                 break;
346         default:
347                 return NT_STATUS_INVALID_ACL;
348         }
349
350         /* expand the generic access bits to file specific bits */
351         *access_mask = pvfs_translate_mask(*access_mask);
352
353         /* check the acl against the required access mask */
354         status = sec_access_check(sd, token, *access_mask, access_mask);
355
356         /* this bit is always granted, even if not asked for */
357         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
358
359         talloc_free(acl);
360         
361         return status;
362 }
363
364
365 /*
366   a simplified interface to access check, designed for calls that
367   do not take or return an access check mask
368 */
369 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
370                                   struct smbsrv_request *req,
371                                   struct pvfs_filename *name,
372                                   uint32_t access_needed)
373 {
374         return pvfs_access_check(pvfs, req, name, &access_needed);
375 }
376
377
378 /*
379   determine if an ACE is inheritable
380 */
381 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
382                                  const struct security_ace *ace,
383                                  BOOL container)
384 {
385         if (!container) {
386                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
387         }
388
389         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
390                 return True;
391         }
392
393         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
394             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
395                 return True;
396         }
397
398         return False;
399 }
400
401 /*
402   this is the core of ACL inheritance. It copies any inheritable
403   aces from the parent SD to the child SD. Note that the algorithm 
404   depends on whether the child is a container or not
405 */
406 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
407                                       struct security_descriptor *parent_sd,
408                                       struct security_descriptor *sd,
409                                       BOOL container)
410 {
411         int i;
412         
413         for (i=0;i<parent_sd->dacl->num_aces;i++) {
414                 struct security_ace ace = parent_sd->dacl->aces[i];
415                 NTSTATUS status;
416
417                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
418                         continue;
419                 }
420
421                 /* see the RAW-ACLS inheritance test for details on these rules */
422                 if (!container) {
423                         ace.flags = 0;
424                 } else {
425                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
426
427                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
428                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
429                         }
430                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
431                                 ace.flags = 0;
432                         }
433                 }
434
435                 status = security_descriptor_dacl_add(sd, &ace);
436                 if (!NT_STATUS_IS_OK(status)) {
437                         return status;
438                 }
439         }
440
441         return NT_STATUS_OK;
442 }
443
444
445
446 /*
447   setup an ACL on a new file/directory based on the inherited ACL from
448   the parent. If there is no inherited ACL then we don't set anything,
449   as the default ACL applies anyway
450 */
451 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
452                           struct smbsrv_request *req,
453                           struct pvfs_filename *name,
454                           int fd)
455 {
456         struct xattr_NTACL *acl;
457         NTSTATUS status;
458         struct pvfs_filename *parent;
459         struct security_descriptor *parent_sd, *sd;
460         BOOL container;
461
462         /* form the parents path */
463         status = pvfs_resolve_parent(pvfs, req, name, &parent);
464         if (!NT_STATUS_IS_OK(status)) {
465                 return status;
466         }
467
468         acl = talloc_p(req, struct xattr_NTACL);
469         if (acl == NULL) {
470                 return NT_STATUS_NO_MEMORY;
471         }
472
473         status = pvfs_acl_load(pvfs, parent, -1, acl);
474         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
475                 return NT_STATUS_OK;
476         }
477         if (!NT_STATUS_IS_OK(status)) {
478                 return status;
479         }
480
481         switch (acl->version) {
482         case 1:
483                 parent_sd = acl->info.sd;
484                 break;
485         default:
486                 return NT_STATUS_INVALID_ACL;
487         }
488
489         if (parent_sd == NULL ||
490             parent_sd->dacl == NULL ||
491             parent_sd->dacl->num_aces == 0) {
492                 /* go with the default ACL */
493                 return NT_STATUS_OK;
494         }
495
496         /* create the new sd */
497         sd = security_descriptor_initialise(req);
498         if (sd == NULL) {
499                 return NT_STATUS_NO_MEMORY;
500         }
501
502         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
503         if (!NT_STATUS_IS_OK(status)) {
504                 return status;
505         }
506         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
507         if (!NT_STATUS_IS_OK(status)) {
508                 return status;
509         }
510
511         sd->type |= SEC_DESC_DACL_PRESENT;
512
513         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
514
515         /* fill in the aces from the parent */
516         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
517         if (!NT_STATUS_IS_OK(status)) {
518                 return status;
519         }
520
521         /* if there is nothing to inherit then we fallback to the
522            default acl */
523         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
524                 return NT_STATUS_OK;
525         }
526
527         acl->info.sd = sd;
528
529         status = pvfs_acl_save(pvfs, name, fd, acl);
530         
531         return status;
532 }