r4412: SEC_FILE_READ_ATTRIBUTE is always granted, even if not requested. This was...
[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         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
310
311         return NT_STATUS_OK;
312 }
313
314
315 /*
316   check the security descriptor on a file, if any
317   
318   *access_mask is modified with the access actually granted
319 */
320 NTSTATUS pvfs_access_check(struct pvfs_state *pvfs, 
321                            struct smbsrv_request *req,
322                            struct pvfs_filename *name,
323                            uint32_t *access_mask)
324 {
325         struct security_token *token = req->session->session_info->security_token;
326         struct xattr_NTACL *acl;
327         NTSTATUS status;
328         struct security_descriptor *sd;
329
330         acl = talloc_p(req, struct xattr_NTACL);
331         if (acl == NULL) {
332                 return NT_STATUS_NO_MEMORY;
333         }
334
335         status = pvfs_acl_load(pvfs, name, -1, acl);
336         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
337                 talloc_free(acl);
338                 return pvfs_access_check_unix(pvfs, req, name, access_mask);
339         }
340         if (!NT_STATUS_IS_OK(status)) {
341                 return status;
342         }
343
344         switch (acl->version) {
345         case 1:
346                 sd = acl->info.sd;
347                 break;
348         default:
349                 return NT_STATUS_INVALID_ACL;
350         }
351
352         /* expand the generic access bits to file specific bits */
353         *access_mask = pvfs_translate_mask(*access_mask);
354
355         /* check the acl against the required access mask */
356         status = sec_access_check(sd, token, *access_mask, access_mask);
357
358         /* this bit is always granted, even if not asked for */
359         *access_mask |= SEC_FILE_READ_ATTRIBUTE;
360
361         talloc_free(acl);
362         
363         return status;
364 }
365
366
367 /*
368   a simplified interface to access check, designed for calls that
369   do not take or return an access check mask
370 */
371 NTSTATUS pvfs_access_check_simple(struct pvfs_state *pvfs, 
372                                   struct smbsrv_request *req,
373                                   struct pvfs_filename *name,
374                                   uint32_t access_needed)
375 {
376         if (access_needed == 0) {
377                 return NT_STATUS_OK;
378         }
379         return pvfs_access_check(pvfs, req, name, &access_needed);
380 }
381
382 /*
383   access check for creating a new file/directory
384 */
385 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
386                                   struct smbsrv_request *req,
387                                   struct pvfs_filename *name)
388 {
389         struct pvfs_filename *parent;
390         NTSTATUS status;
391
392         status = pvfs_resolve_parent(pvfs, req, name, &parent);
393         if (!NT_STATUS_IS_OK(status)) {
394                 return status;
395         }
396
397         return pvfs_access_check_simple(pvfs, req, parent, SEC_DIR_ADD_FILE);
398 }
399
400
401 /*
402   determine if an ACE is inheritable
403 */
404 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
405                                  const struct security_ace *ace,
406                                  BOOL container)
407 {
408         if (!container) {
409                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
410         }
411
412         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
413                 return True;
414         }
415
416         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
417             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
418                 return True;
419         }
420
421         return False;
422 }
423
424 /*
425   this is the core of ACL inheritance. It copies any inheritable
426   aces from the parent SD to the child SD. Note that the algorithm 
427   depends on whether the child is a container or not
428 */
429 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
430                                       struct security_descriptor *parent_sd,
431                                       struct security_descriptor *sd,
432                                       BOOL container)
433 {
434         int i;
435         
436         for (i=0;i<parent_sd->dacl->num_aces;i++) {
437                 struct security_ace ace = parent_sd->dacl->aces[i];
438                 NTSTATUS status;
439
440                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
441                         continue;
442                 }
443
444                 /* see the RAW-ACLS inheritance test for details on these rules */
445                 if (!container) {
446                         ace.flags = 0;
447                 } else {
448                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
449
450                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
451                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
452                         }
453                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
454                                 ace.flags = 0;
455                         }
456                 }
457
458                 status = security_descriptor_dacl_add(sd, &ace);
459                 if (!NT_STATUS_IS_OK(status)) {
460                         return status;
461                 }
462         }
463
464         return NT_STATUS_OK;
465 }
466
467
468
469 /*
470   setup an ACL on a new file/directory based on the inherited ACL from
471   the parent. If there is no inherited ACL then we don't set anything,
472   as the default ACL applies anyway
473 */
474 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
475                           struct smbsrv_request *req,
476                           struct pvfs_filename *name,
477                           int fd)
478 {
479         struct xattr_NTACL *acl;
480         NTSTATUS status;
481         struct pvfs_filename *parent;
482         struct security_descriptor *parent_sd, *sd;
483         BOOL container;
484
485         /* form the parents path */
486         status = pvfs_resolve_parent(pvfs, req, name, &parent);
487         if (!NT_STATUS_IS_OK(status)) {
488                 return status;
489         }
490
491         acl = talloc_p(req, struct xattr_NTACL);
492         if (acl == NULL) {
493                 return NT_STATUS_NO_MEMORY;
494         }
495
496         status = pvfs_acl_load(pvfs, parent, -1, acl);
497         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
498                 return NT_STATUS_OK;
499         }
500         if (!NT_STATUS_IS_OK(status)) {
501                 return status;
502         }
503
504         switch (acl->version) {
505         case 1:
506                 parent_sd = acl->info.sd;
507                 break;
508         default:
509                 return NT_STATUS_INVALID_ACL;
510         }
511
512         if (parent_sd == NULL ||
513             parent_sd->dacl == NULL ||
514             parent_sd->dacl->num_aces == 0) {
515                 /* go with the default ACL */
516                 return NT_STATUS_OK;
517         }
518
519         /* create the new sd */
520         sd = security_descriptor_initialise(req);
521         if (sd == NULL) {
522                 return NT_STATUS_NO_MEMORY;
523         }
524
525         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
526         if (!NT_STATUS_IS_OK(status)) {
527                 return status;
528         }
529         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
530         if (!NT_STATUS_IS_OK(status)) {
531                 return status;
532         }
533
534         sd->type |= SEC_DESC_DACL_PRESENT;
535
536         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
537
538         /* fill in the aces from the parent */
539         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
540         if (!NT_STATUS_IS_OK(status)) {
541                 return status;
542         }
543
544         /* if there is nothing to inherit then we fallback to the
545            default acl */
546         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
547                 return NT_STATUS_OK;
548         }
549
550         acl->info.sd = sd;
551
552         status = pvfs_acl_save(pvfs, name, fd, acl);
553         
554         return status;
555 }