r4410: pvfs_rename_one() should not check for create permissions, as the rename
[samba.git] / source / 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         if (access_needed == 0) {
375                 return NT_STATUS_OK;
376         }
377         return pvfs_access_check(pvfs, req, name, &access_needed);
378 }
379
380 /*
381   access check for creating a new file/directory
382 */
383 NTSTATUS pvfs_access_check_create(struct pvfs_state *pvfs, 
384                                   struct smbsrv_request *req,
385                                   struct pvfs_filename *name)
386 {
387         struct pvfs_filename *parent;
388         NTSTATUS status;
389
390         status = pvfs_resolve_parent(pvfs, req, name, &parent);
391         if (!NT_STATUS_IS_OK(status)) {
392                 return status;
393         }
394
395         return pvfs_access_check_simple(pvfs, req, name, SEC_DIR_ADD_FILE);
396 }
397
398
399 /*
400   determine if an ACE is inheritable
401 */
402 static BOOL pvfs_inheritable_ace(struct pvfs_state *pvfs,
403                                  const struct security_ace *ace,
404                                  BOOL container)
405 {
406         if (!container) {
407                 return (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0;
408         }
409
410         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
411                 return True;
412         }
413
414         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
415             !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
416                 return True;
417         }
418
419         return False;
420 }
421
422 /*
423   this is the core of ACL inheritance. It copies any inheritable
424   aces from the parent SD to the child SD. Note that the algorithm 
425   depends on whether the child is a container or not
426 */
427 static NTSTATUS pvfs_acl_inherit_aces(struct pvfs_state *pvfs, 
428                                       struct security_descriptor *parent_sd,
429                                       struct security_descriptor *sd,
430                                       BOOL container)
431 {
432         int i;
433         
434         for (i=0;i<parent_sd->dacl->num_aces;i++) {
435                 struct security_ace ace = parent_sd->dacl->aces[i];
436                 NTSTATUS status;
437
438                 if (!pvfs_inheritable_ace(pvfs, &ace, container)) {
439                         continue;
440                 }
441
442                 /* see the RAW-ACLS inheritance test for details on these rules */
443                 if (!container) {
444                         ace.flags = 0;
445                 } else {
446                         ace.flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
447
448                         if (!(ace.flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
449                                 ace.flags |= SEC_ACE_FLAG_INHERIT_ONLY;
450                         }
451                         if (ace.flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
452                                 ace.flags = 0;
453                         }
454                 }
455
456                 status = security_descriptor_dacl_add(sd, &ace);
457                 if (!NT_STATUS_IS_OK(status)) {
458                         return status;
459                 }
460         }
461
462         return NT_STATUS_OK;
463 }
464
465
466
467 /*
468   setup an ACL on a new file/directory based on the inherited ACL from
469   the parent. If there is no inherited ACL then we don't set anything,
470   as the default ACL applies anyway
471 */
472 NTSTATUS pvfs_acl_inherit(struct pvfs_state *pvfs, 
473                           struct smbsrv_request *req,
474                           struct pvfs_filename *name,
475                           int fd)
476 {
477         struct xattr_NTACL *acl;
478         NTSTATUS status;
479         struct pvfs_filename *parent;
480         struct security_descriptor *parent_sd, *sd;
481         BOOL container;
482
483         /* form the parents path */
484         status = pvfs_resolve_parent(pvfs, req, name, &parent);
485         if (!NT_STATUS_IS_OK(status)) {
486                 return status;
487         }
488
489         acl = talloc_p(req, struct xattr_NTACL);
490         if (acl == NULL) {
491                 return NT_STATUS_NO_MEMORY;
492         }
493
494         status = pvfs_acl_load(pvfs, parent, -1, acl);
495         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
496                 return NT_STATUS_OK;
497         }
498         if (!NT_STATUS_IS_OK(status)) {
499                 return status;
500         }
501
502         switch (acl->version) {
503         case 1:
504                 parent_sd = acl->info.sd;
505                 break;
506         default:
507                 return NT_STATUS_INVALID_ACL;
508         }
509
510         if (parent_sd == NULL ||
511             parent_sd->dacl == NULL ||
512             parent_sd->dacl->num_aces == 0) {
513                 /* go with the default ACL */
514                 return NT_STATUS_OK;
515         }
516
517         /* create the new sd */
518         sd = security_descriptor_initialise(req);
519         if (sd == NULL) {
520                 return NT_STATUS_NO_MEMORY;
521         }
522
523         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
524         if (!NT_STATUS_IS_OK(status)) {
525                 return status;
526         }
527         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
528         if (!NT_STATUS_IS_OK(status)) {
529                 return status;
530         }
531
532         sd->type |= SEC_DESC_DACL_PRESENT;
533
534         container = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) ? True:False;
535
536         /* fill in the aces from the parent */
537         status = pvfs_acl_inherit_aces(pvfs, parent_sd, sd, container);
538         if (!NT_STATUS_IS_OK(status)) {
539                 return status;
540         }
541
542         /* if there is nothing to inherit then we fallback to the
543            default acl */
544         if (sd->dacl == NULL || sd->dacl->num_aces == 0) {
545                 return NT_STATUS_OK;
546         }
547
548         acl->info.sd = sd;
549
550         status = pvfs_acl_save(pvfs, name, fd, acl);
551         
552         return status;
553 }