90959f322e0e28d5d6a1fa9c25d59d264a08a5ce
[kai/samba.git] / source3 / modules / vfs_acl_xattr.c
1 /*
2  * Store Windows ACLs in xattrs.
3  *
4  * Copyright (C) Volker Lendecke, 2008
5  * Copyright (C) Jeremy Allison, 2008
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* NOTE: This is an experimental module, not yet finished. JRA. */
22
23 #include "includes.h"
24 #include "smbd/smbd.h"
25 #include "librpc/gen_ndr/xattr.h"
26 #include "librpc/gen_ndr/ndr_xattr.h"
27 #include "../lib/crypto/crypto.h"
28 #include "auth.h"
29
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_VFS
32
33 /* Pull in the common functions. */
34 #define ACL_MODULE_NAME "acl_xattr"
35
36 #include "modules/vfs_acl_common.c"
37
38 /*******************************************************************
39  Pull a security descriptor into a DATA_BLOB from a xattr.
40 *******************************************************************/
41
42 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
43                         vfs_handle_struct *handle,
44                         files_struct *fsp,
45                         const char *name,
46                         DATA_BLOB *pblob)
47 {
48         size_t size = 1024;
49         uint8_t *val = NULL;
50         uint8_t *tmp;
51         ssize_t sizeret;
52         int saved_errno = 0;
53
54         ZERO_STRUCTP(pblob);
55
56   again:
57
58         tmp = TALLOC_REALLOC_ARRAY(ctx, val, uint8_t, size);
59         if (tmp == NULL) {
60                 TALLOC_FREE(val);
61                 return NT_STATUS_NO_MEMORY;
62         }
63         val = tmp;
64
65         become_root();
66         if (fsp && fsp->fh->fd != -1) {
67                 sizeret = SMB_VFS_FGETXATTR(fsp, XATTR_NTACL_NAME, val, size);
68         } else {
69                 sizeret = SMB_VFS_GETXATTR(handle->conn, name,
70                                         XATTR_NTACL_NAME, val, size);
71         }
72         if (sizeret == -1) {
73                 saved_errno = errno;
74         }
75         unbecome_root();
76
77         /* Max ACL size is 65536 bytes. */
78         if (sizeret == -1) {
79                 errno = saved_errno;
80                 if ((errno == ERANGE) && (size != 65536)) {
81                         /* Too small, try again. */
82                         size = 65536;
83                         goto again;
84                 }
85
86                 /* Real error - exit here. */
87                 TALLOC_FREE(val);
88                 return map_nt_error_from_unix(errno);
89         }
90
91         pblob->data = val;
92         pblob->length = sizeret;
93         return NT_STATUS_OK;
94 }
95
96 /*******************************************************************
97  Store a DATA_BLOB into an xattr given an fsp pointer.
98 *******************************************************************/
99
100 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
101                                 files_struct *fsp,
102                                 DATA_BLOB *pblob)
103 {
104         int ret;
105         int saved_errno = 0;
106
107         DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
108                   (unsigned int)pblob->length, fsp_str_dbg(fsp)));
109
110         become_root();
111         if (fsp->fh->fd != -1) {
112                 ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
113                         pblob->data, pblob->length, 0);
114         } else {
115                 ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name,
116                                 XATTR_NTACL_NAME,
117                                 pblob->data, pblob->length, 0);
118         }
119         if (ret) {
120                 saved_errno = errno;
121         }
122         unbecome_root();
123         if (ret) {
124                 errno = saved_errno;
125                 DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s"
126                         "with error %s\n",
127                         fsp_str_dbg(fsp),
128                         strerror(errno) ));
129                 return map_nt_error_from_unix(errno);
130         }
131         return NT_STATUS_OK;
132 }
133
134 /*********************************************************************
135  Remove a Windows ACL - we're setting the underlying POSIX ACL.
136 *********************************************************************/
137
138 static int sys_acl_set_file_xattr(vfs_handle_struct *handle,
139                               const char *name,
140                               SMB_ACL_TYPE_T type,
141                               SMB_ACL_T theacl)
142 {
143         int ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle,
144                                                 name,
145                                                 type,
146                                                 theacl);
147         if (ret == -1) {
148                 return -1;
149         }
150
151         become_root();
152         SMB_VFS_REMOVEXATTR(handle->conn, name, XATTR_NTACL_NAME);
153         unbecome_root();
154
155         return ret;
156 }
157
158 /*********************************************************************
159  Remove a Windows ACL - we're setting the underlying POSIX ACL.
160 *********************************************************************/
161
162 static int sys_acl_set_fd_xattr(vfs_handle_struct *handle,
163                             files_struct *fsp,
164                             SMB_ACL_T theacl)
165 {
166         int ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
167                                                 fsp,
168                                                 theacl);
169         if (ret == -1) {
170                 return -1;
171         }
172
173         become_root();
174         SMB_VFS_FREMOVEXATTR(fsp, XATTR_NTACL_NAME);
175         unbecome_root();
176
177         return ret;
178 }
179
180 static int connect_acl_xattr(struct vfs_handle_struct *handle,
181                                 const char *service,
182                                 const char *user)
183 {
184         int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
185
186         if (ret < 0) {
187                 return ret;
188         }
189
190         /* Ensure we have the parameters correct if we're
191          * using this module. */
192         DEBUG(2,("connect_acl_xattr: setting 'inherit acls = true' "
193                 "'dos filemode = true' and "
194                 "'force unknown acl user = true' for service %s\n",
195                 service ));
196
197         lp_do_parameter(SNUM(handle->conn), "inherit acls", "true");
198         lp_do_parameter(SNUM(handle->conn), "dos filemode", "true");
199         lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true");
200
201         return 0;
202 }
203
204 static struct vfs_fn_pointers vfs_acl_xattr_fns = {
205         .connect_fn = connect_acl_xattr,
206         .opendir = opendir_acl_common,
207         .mkdir = mkdir_acl_common,
208         .rmdir = rmdir_acl_common,
209         .open = open_acl_common,
210         .create_file = create_file_acl_common,
211         .unlink = unlink_acl_common,
212         .chmod = chmod_acl_module_common,
213         .fchmod = fchmod_acl_module_common,
214         .fget_nt_acl = fget_nt_acl_common,
215         .get_nt_acl = get_nt_acl_common,
216         .fset_nt_acl = fset_nt_acl_common,
217         .chmod_acl = chmod_acl_acl_module_common,
218         .fchmod_acl = fchmod_acl_acl_module_common,
219         .sys_acl_set_file = sys_acl_set_file_xattr,
220         .sys_acl_set_fd = sys_acl_set_fd_xattr
221 };
222
223 NTSTATUS vfs_acl_xattr_init(void)
224 {
225         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_xattr",
226                                 &vfs_acl_xattr_fns);
227 }