r3990: take advantage of the uid->sid and gid->sid code to create a much
[tprouty/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   setup a default ACL for a file
32 */
33 static NTSTATUS pvfs_default_acl(struct pvfs_state *pvfs,
34                                  struct smbsrv_request *req,
35                                  struct pvfs_filename *name, int fd, 
36                                  struct xattr_NTACL *acl)
37 {
38         struct security_descriptor *sd;
39         int i;
40         struct security_ace ace;
41         NTSTATUS status;
42         const char *sid_names[] = {
43                 SID_BUILTIN_ADMINISTRATORS,
44                 SID_CREATOR_OWNER,
45                 SID_CREATOR_GROUP,
46                 SID_WORLD
47         };
48         uint32_t access_masks[4];
49         mode_t mode;
50
51         sd = security_descriptor_initialise(req);
52         if (sd == NULL) {
53                 return NT_STATUS_NO_MEMORY;
54         }
55
56         status = sidmap_uid_to_sid(pvfs->sidmap, sd, name->st.st_uid, &sd->owner_sid);
57         if (!NT_STATUS_IS_OK(status)) {
58                 return status;
59         }
60         status = sidmap_gid_to_sid(pvfs->sidmap, sd, name->st.st_gid, &sd->group_sid);
61         if (!NT_STATUS_IS_OK(status)) {
62                 return status;
63         }
64
65         sd->type |= SEC_DESC_DACL_PRESENT;
66
67         /*
68           we provide 4 ACEs
69             - Administrator
70             - Owner
71             - Group
72             - Everyone
73          */
74         access_masks[0] = SEC_RIGHTS_FULL_CTRL | STD_RIGHT_ALL_ACCESS;
75         access_masks[1] = 0;
76         access_masks[2] = 0;
77         access_masks[3] = 0;
78
79         mode = name->st.st_mode;
80
81         if (mode & S_IRUSR) {
82                 access_masks[1] |= 
83                         SA_RIGHT_FILE_READ_DATA | 
84                         SA_RIGHT_FILE_READ_EA |
85                         SA_RIGHT_FILE_READ_ATTRIBUTES |
86                         SA_RIGHT_FILE_EXECUTE;
87         }
88         if (mode & S_IWUSR) {
89                 access_masks[1] |= 
90                         SA_RIGHT_FILE_WRITE_DATA | 
91                         SA_RIGHT_FILE_APPEND_DATA |
92                         SA_RIGHT_FILE_WRITE_EA |
93                         SA_RIGHT_FILE_DELETE_CHILD |
94                         SA_RIGHT_FILE_WRITE_ATTRIBUTES;
95         }
96
97         if (mode & S_IRGRP) {
98                 access_masks[2] |= 
99                         SA_RIGHT_FILE_READ_DATA | 
100                         SA_RIGHT_FILE_READ_EA |
101                         SA_RIGHT_FILE_READ_ATTRIBUTES |
102                         SA_RIGHT_FILE_EXECUTE;
103         }
104         if (mode & S_IWGRP) {
105                 access_masks[2] |= 
106                         SA_RIGHT_FILE_WRITE_DATA | 
107                         SA_RIGHT_FILE_APPEND_DATA |
108                         SA_RIGHT_FILE_WRITE_EA |
109                         SA_RIGHT_FILE_DELETE_CHILD |
110                         SA_RIGHT_FILE_WRITE_ATTRIBUTES;
111         }
112
113         if (mode & S_IROTH) {
114                 access_masks[3] |= 
115                         SA_RIGHT_FILE_READ_DATA | 
116                         SA_RIGHT_FILE_READ_EA |
117                         SA_RIGHT_FILE_READ_ATTRIBUTES |
118                         SA_RIGHT_FILE_EXECUTE;
119         }
120         if (mode & S_IWOTH) {
121                 access_masks[3] |= 
122                         SA_RIGHT_FILE_WRITE_DATA | 
123                         SA_RIGHT_FILE_APPEND_DATA |
124                         SA_RIGHT_FILE_WRITE_EA |
125                         SA_RIGHT_FILE_DELETE_CHILD |
126                         SA_RIGHT_FILE_WRITE_ATTRIBUTES;
127         }
128
129         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
130         ace.flags = 0;
131
132         for (i=0;i<ARRAY_SIZE(sid_names);i++) {
133                 struct dom_sid *sid;
134
135                 ace.access_mask = access_masks[i];
136
137                 sid = dom_sid_parse_talloc(sd, sid_names[i]);
138                 if (sid == NULL) {
139                         return NT_STATUS_NO_MEMORY;
140                 }
141                 ace.trustee = *sid;
142
143                 status = security_descriptor_dacl_add(sd, &ace);
144                 if (!NT_STATUS_IS_OK(status)) {
145                         return status;
146                 }
147         }
148         
149         acl->version = 1;
150         acl->info.sd = sd;
151
152         return NT_STATUS_OK;
153 }
154                                  
155
156 /*
157   omit any security_descriptor elements not specified in the given
158   secinfo flags
159 */
160 static void normalise_sd_flags(struct security_descriptor *sd, uint32_t secinfo_flags)
161 {
162         if (!(secinfo_flags & OWNER_SECURITY_INFORMATION)) {
163                 sd->owner_sid = NULL;
164         }
165         if (!(secinfo_flags & GROUP_SECURITY_INFORMATION)) {
166                 sd->group_sid = NULL;
167         }
168         if (!(secinfo_flags & DACL_SECURITY_INFORMATION)) {
169                 sd->dacl = NULL;
170         }
171         if (!(secinfo_flags & SACL_SECURITY_INFORMATION)) {
172                 sd->sacl = NULL;
173         }
174 }
175
176 /*
177   answer a setfileinfo for an ACL
178 */
179 NTSTATUS pvfs_acl_set(struct pvfs_state *pvfs, 
180                       struct smbsrv_request *req,
181                       struct pvfs_filename *name, int fd, 
182                       union smb_setfileinfo *info)
183 {
184         struct xattr_NTACL *acl;
185         uint32_t secinfo_flags = info->set_secdesc.in.secinfo_flags;
186         struct security_descriptor *new_sd, *sd;
187         NTSTATUS status;
188
189         acl = talloc_p(req, struct xattr_NTACL);
190         if (acl == NULL) {
191                 return NT_STATUS_NO_MEMORY;
192         }
193
194         status = pvfs_acl_load(pvfs, name, fd, acl);
195         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
196                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
197         }
198         if (!NT_STATUS_IS_OK(status)) {
199                 return status;
200         }
201
202         switch (acl->version) {
203         case 1:
204                 sd = acl->info.sd;
205                 break;
206         default:
207                 return NT_STATUS_INVALID_LEVEL;
208         }
209
210         new_sd = info->set_secdesc.in.sd;
211
212         /* only set the elements that have been specified */
213         if (secinfo_flags & OWNER_SECURITY_INFORMATION) {
214                 sd->owner_sid = new_sd->owner_sid;
215         }
216         if (secinfo_flags & GROUP_SECURITY_INFORMATION) {
217                 sd->group_sid = new_sd->group_sid;
218         }
219         if (secinfo_flags & DACL_SECURITY_INFORMATION) {
220                 sd->dacl = new_sd->dacl;
221         }
222         if (secinfo_flags & SACL_SECURITY_INFORMATION) {
223                 sd->sacl = new_sd->sacl;
224         }
225
226         status = pvfs_acl_save(pvfs, name, fd, acl);
227
228         return status;
229 }
230
231
232 /*
233   answer a fileinfo query for the ACL
234 */
235 NTSTATUS pvfs_acl_query(struct pvfs_state *pvfs, 
236                         struct smbsrv_request *req,
237                         struct pvfs_filename *name, int fd, 
238                         union smb_fileinfo *info)
239 {
240         struct xattr_NTACL *acl;
241         NTSTATUS status;
242         struct security_descriptor *sd;
243
244         acl = talloc_p(req, struct xattr_NTACL);
245         if (acl == NULL) {
246                 return NT_STATUS_NO_MEMORY;
247         }
248
249         status = pvfs_acl_load(pvfs, name, fd, acl);
250         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
251                 status = pvfs_default_acl(pvfs, req, name, fd, acl);
252         }
253         if (!NT_STATUS_IS_OK(status)) {
254                 return status;
255         }
256
257         switch (acl->version) {
258         case 1:
259                 sd = acl->info.sd;
260                 break;
261         default:
262                 return NT_STATUS_INVALID_LEVEL;
263         }
264
265         normalise_sd_flags(sd, info->query_secdesc.in.secinfo_flags);
266
267         info->query_secdesc.out.sd = sd;
268
269         return NT_STATUS_OK;
270 }
271