s4:selftest: explicitly set NSS/RESOLV_WAPPER_* in wait_for_start
[Samba.git] / source3 / modules / vfs_acl_xattr.c
blob38ad81cc24418d99a6fb091408bd1d70c0f7fdb7
1 /*
2 * Store Windows ACLs in xattrs.
4 * Copyright (C) Volker Lendecke, 2008
5 * Copyright (C) Jeremy Allison, 2008
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.
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.
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/>.
21 #include "includes.h"
22 #include "smbd/smbd.h"
23 #include "librpc/gen_ndr/xattr.h"
24 #include "../lib/crypto/sha256.h"
25 #include "auth.h"
26 #include "vfs_acl_common.h"
28 /* Pull in the common functions. */
29 #define ACL_MODULE_NAME "acl_xattr"
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_VFS
34 /*******************************************************************
35 Pull a security descriptor into a DATA_BLOB from a xattr.
36 *******************************************************************/
38 static ssize_t getxattr_do(vfs_handle_struct *handle,
39 files_struct *fsp,
40 const struct smb_filename *smb_fname,
41 const char *xattr_name,
42 uint8_t *val,
43 size_t size)
45 ssize_t sizeret;
46 int saved_errno = 0;
48 become_root();
49 if (fsp && fsp->fh->fd != -1) {
50 sizeret = SMB_VFS_FGETXATTR(fsp, xattr_name, val, size);
51 } else {
52 sizeret = SMB_VFS_GETXATTR(handle->conn, smb_fname,
53 XATTR_NTACL_NAME, val, size);
55 if (sizeret == -1) {
56 saved_errno = errno;
58 unbecome_root();
60 if (saved_errno != 0) {
61 errno = saved_errno;
64 return sizeret;
67 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
68 vfs_handle_struct *handle,
69 files_struct *fsp,
70 const struct smb_filename *smb_fname,
71 DATA_BLOB *pblob)
73 size_t size = 4096;
74 uint8_t *val = NULL;
75 uint8_t *tmp;
76 ssize_t sizeret;
78 ZERO_STRUCTP(pblob);
80 again:
82 tmp = talloc_realloc(ctx, val, uint8_t, size);
83 if (tmp == NULL) {
84 TALLOC_FREE(val);
85 return NT_STATUS_NO_MEMORY;
87 val = tmp;
89 sizeret =
90 getxattr_do(handle, fsp, smb_fname, XATTR_NTACL_NAME, val, size);
92 if (sizeret >= 0) {
93 pblob->data = val;
94 pblob->length = sizeret;
95 return NT_STATUS_OK;
98 if (errno != ERANGE) {
99 goto err;
102 /* Too small, try again. */
103 sizeret =
104 getxattr_do(handle, fsp, smb_fname, XATTR_NTACL_NAME, NULL, 0);
105 if (sizeret < 0) {
106 goto err;
109 if (size < sizeret) {
110 size = sizeret;
113 if (size > 65536) {
114 /* Max ACL size is 65536 bytes. */
115 errno = ERANGE;
116 goto err;
119 goto again;
120 err:
121 /* Real error - exit here. */
122 TALLOC_FREE(val);
123 return map_nt_error_from_unix(errno);
126 /*******************************************************************
127 Store a DATA_BLOB into an xattr given an fsp pointer.
128 *******************************************************************/
130 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
131 files_struct *fsp,
132 DATA_BLOB *pblob)
134 int ret;
135 int saved_errno = 0;
137 DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
138 (unsigned int)pblob->length, fsp_str_dbg(fsp)));
140 become_root();
141 if (fsp->fh->fd != -1) {
142 ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME,
143 pblob->data, pblob->length, 0);
144 } else {
145 ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name,
146 XATTR_NTACL_NAME,
147 pblob->data, pblob->length, 0);
149 if (ret) {
150 saved_errno = errno;
152 unbecome_root();
153 if (ret) {
154 DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s"
155 "with error %s\n",
156 fsp_str_dbg(fsp),
157 strerror(saved_errno) ));
158 errno = saved_errno;
159 return map_nt_error_from_unix(saved_errno);
161 return NT_STATUS_OK;
164 /*********************************************************************
165 Remove a Windows ACL - we're setting the underlying POSIX ACL.
166 *********************************************************************/
168 static int sys_acl_set_file_xattr(vfs_handle_struct *handle,
169 const struct smb_filename *smb_fname,
170 SMB_ACL_TYPE_T type,
171 SMB_ACL_T theacl)
173 int ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle,
174 smb_fname,
175 type,
176 theacl);
177 if (ret == -1) {
178 return -1;
181 become_root();
182 SMB_VFS_REMOVEXATTR(handle->conn, smb_fname,
183 XATTR_NTACL_NAME);
184 unbecome_root();
186 return ret;
189 /*********************************************************************
190 Remove a Windows ACL - we're setting the underlying POSIX ACL.
191 *********************************************************************/
193 static int sys_acl_set_fd_xattr(vfs_handle_struct *handle,
194 files_struct *fsp,
195 SMB_ACL_T theacl)
197 int ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
198 fsp,
199 theacl);
200 if (ret == -1) {
201 return -1;
204 become_root();
205 SMB_VFS_FREMOVEXATTR(fsp, XATTR_NTACL_NAME);
206 unbecome_root();
208 return ret;
211 static int connect_acl_xattr(struct vfs_handle_struct *handle,
212 const char *service,
213 const char *user)
215 int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
216 bool ok;
217 struct acl_common_config *config = NULL;
219 if (ret < 0) {
220 return ret;
223 ok = init_acl_common_config(handle, ACL_MODULE_NAME);
224 if (!ok) {
225 DBG_ERR("init_acl_common_config failed\n");
226 return -1;
229 /* Ensure we have the parameters correct if we're
230 * using this module. */
231 DEBUG(2,("connect_acl_xattr: setting 'inherit acls = true' "
232 "'dos filemode = true' and "
233 "'force unknown acl user = true' for service %s\n",
234 service ));
236 lp_do_parameter(SNUM(handle->conn), "inherit acls", "true");
237 lp_do_parameter(SNUM(handle->conn), "dos filemode", "true");
238 lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true");
240 SMB_VFS_HANDLE_GET_DATA(handle, config,
241 struct acl_common_config,
242 return -1);
244 if (config->ignore_system_acls) {
245 mode_t create_mask = lp_create_mask(SNUM(handle->conn));
246 char *create_mask_str = NULL;
248 if ((create_mask & 0666) != 0666) {
249 create_mask |= 0666;
250 create_mask_str = talloc_asprintf(handle, "0%o",
251 create_mask);
252 if (create_mask_str == NULL) {
253 DBG_ERR("talloc_asprintf failed\n");
254 return -1;
257 DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
259 lp_do_parameter (SNUM(handle->conn),
260 "create mask", create_mask_str);
262 TALLOC_FREE(create_mask_str);
265 DBG_NOTICE("setting 'directory mask = 0777', "
266 "'store dos attributes = yes' and all "
267 "'map ...' options to 'no'\n");
269 lp_do_parameter(SNUM(handle->conn), "directory mask", "0777");
270 lp_do_parameter(SNUM(handle->conn), "map archive", "no");
271 lp_do_parameter(SNUM(handle->conn), "map hidden", "no");
272 lp_do_parameter(SNUM(handle->conn), "map readonly", "no");
273 lp_do_parameter(SNUM(handle->conn), "map system", "no");
274 lp_do_parameter(SNUM(handle->conn), "store dos attributes",
275 "yes");
278 return 0;
281 static NTSTATUS acl_xattr_fget_nt_acl(vfs_handle_struct *handle,
282 files_struct *fsp,
283 uint32_t security_info,
284 TALLOC_CTX *mem_ctx,
285 struct security_descriptor **ppdesc)
287 NTSTATUS status;
288 status = get_nt_acl_common(get_acl_blob, handle, fsp, NULL,
289 security_info, mem_ctx, ppdesc);
290 return status;
293 static NTSTATUS acl_xattr_get_nt_acl(vfs_handle_struct *handle,
294 const struct smb_filename *smb_fname,
295 uint32_t security_info,
296 TALLOC_CTX *mem_ctx,
297 struct security_descriptor **ppdesc)
299 NTSTATUS status;
300 status = get_nt_acl_common(get_acl_blob, handle, NULL, smb_fname,
301 security_info, mem_ctx, ppdesc);
302 return status;
305 static NTSTATUS acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
306 files_struct *fsp,
307 uint32_t security_info_sent,
308 const struct security_descriptor *psd)
310 NTSTATUS status;
311 status = fset_nt_acl_common(get_acl_blob, store_acl_blob_fsp,
312 ACL_MODULE_NAME,
313 handle, fsp, security_info_sent, psd);
314 return status;
317 static struct vfs_fn_pointers vfs_acl_xattr_fns = {
318 .connect_fn = connect_acl_xattr,
319 .rmdir_fn = rmdir_acl_common,
320 .unlink_fn = unlink_acl_common,
321 .chmod_fn = chmod_acl_module_common,
322 .fchmod_fn = fchmod_acl_module_common,
323 .fget_nt_acl_fn = acl_xattr_fget_nt_acl,
324 .get_nt_acl_fn = acl_xattr_get_nt_acl,
325 .fset_nt_acl_fn = acl_xattr_fset_nt_acl,
326 .chmod_acl_fn = chmod_acl_acl_module_common,
327 .fchmod_acl_fn = fchmod_acl_acl_module_common,
328 .sys_acl_set_file_fn = sys_acl_set_file_xattr,
329 .sys_acl_set_fd_fn = sys_acl_set_fd_xattr
332 static_decl_vfs;
333 NTSTATUS vfs_acl_xattr_init(TALLOC_CTX *ctx)
335 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_xattr",
336 &vfs_acl_xattr_fns);