2 * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
4 * Copyright (C) Jiri Sasek, 2007
5 * based on the foobar.c module which is copyrighted by Volker Lendecke
6 * based on pvfs_acl_nfs4.c Copyright (C) Andrew Tridgell 2006
8 * based on vfs_fake_acls:
9 * Copyright (C) Tim Potter, 1999-2000
10 * Copyright (C) Alexander Bokovoy, 2002
11 * Copyright (C) Andrew Bartlett, 2002,2012
12 * Copyright (C) Ralph Boehme 2017
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <http://www.gnu.org/licenses/>.
30 #include "system/filesys.h"
31 #include "smbd/smbd.h"
32 #include "nfs4_acls.h"
33 #include "librpc/gen_ndr/ndr_nfs4acl.h"
34 #include "nfs4acl_xattr.h"
35 #include "nfs4acl_xattr_ndr.h"
38 #define DBGC_CLASS DBGC_VFS
40 static const struct enum_list nfs4acl_encoding[] = {
41 {NFS4ACL_ENCODING_NDR, "ndr"},
42 {NFS4ACL_ENCODING_XDR, "xdr"},
45 static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle,
47 const struct smb_filename *smb_fname_in,
51 struct nfs4acl_config *config = NULL;
52 const struct smb_filename *smb_fname = NULL;
53 size_t allocsize = 256;
57 SMB_VFS_HANDLE_GET_DATA(handle, config,
58 struct nfs4acl_config,
59 return NT_STATUS_INTERNAL_ERROR);
61 *blob = data_blob_null;
63 if (fsp == NULL && smb_fname_in == NULL) {
64 return NT_STATUS_INTERNAL_ERROR;
66 smb_fname = smb_fname_in;
67 if (smb_fname == NULL) {
68 smb_fname = fsp->fsp_name;
70 if (smb_fname == NULL) {
71 return NT_STATUS_INTERNAL_ERROR;
76 ok = data_blob_realloc(mem_ctx, blob, allocsize);
78 return NT_STATUS_NO_MEMORY;
81 if (fsp != NULL && fsp->fh->fd != -1) {
82 length = SMB_VFS_NEXT_FGETXATTR(handle,
88 length = SMB_VFS_NEXT_GETXATTR(handle,
94 } while (length == -1 && errno == ERANGE && allocsize <= 65536);
97 return map_nt_error_from_unix(errno);
103 static NTSTATUS nfs4acl_xattr_default_sd(
104 struct vfs_handle_struct *handle,
105 const struct smb_filename *smb_fname,
107 struct security_descriptor **sd)
109 struct nfs4acl_config *config = NULL;
110 enum default_acl_style default_acl_style;
111 mode_t required_mode;
112 SMB_STRUCT_STAT sbuf = smb_fname->st;
115 SMB_VFS_HANDLE_GET_DATA(handle, config,
116 struct nfs4acl_config,
117 return NT_STATUS_INTERNAL_ERROR);
119 default_acl_style = config->default_acl_style;
121 if (!VALID_STAT(sbuf)) {
122 ret = vfs_stat_smb_basename(handle->conn,
126 return map_nt_error_from_unix(errno);
130 if (S_ISDIR(sbuf.st_ex_mode)) {
131 required_mode = 0777;
133 required_mode = 0666;
135 if ((sbuf.st_ex_mode & required_mode) != required_mode) {
136 default_acl_style = DEFAULT_ACL_POSIX;
139 return make_default_filesystem_acl(mem_ctx,
141 smb_fname->base_name,
146 static NTSTATUS nfs4acl_blob_to_smb4(struct vfs_handle_struct *handle,
149 struct SMB4ACL_T **smb4acl)
151 struct nfs4acl_config *config = NULL;
154 SMB_VFS_HANDLE_GET_DATA(handle, config,
155 struct nfs4acl_config,
156 return NT_STATUS_INTERNAL_ERROR);
158 switch (config->encoding) {
159 case NFS4ACL_ENCODING_NDR:
160 status = nfs4acl_ndr_blob_to_smb4(handle, mem_ctx, blob, smb4acl);
163 status = NT_STATUS_INTERNAL_ERROR;
170 static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
171 struct files_struct *fsp,
172 uint32_t security_info,
174 struct security_descriptor **sd)
176 struct SMB4ACL_T *smb4acl = NULL;
177 TALLOC_CTX *frame = talloc_stackframe();
181 status = nfs4acl_get_blob(handle, fsp, NULL, frame, &blob);
182 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
184 return nfs4acl_xattr_default_sd(
185 handle, fsp->fsp_name, mem_ctx, sd);
187 if (!NT_STATUS_IS_OK(status)) {
192 status = nfs4acl_blob_to_smb4(handle, &blob, frame, &smb4acl);
193 if (!NT_STATUS_IS_OK(status)) {
198 status = smb_fget_nt_acl_nfs4(fsp, NULL, security_info, mem_ctx,
204 static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle,
205 const struct smb_filename *smb_fname,
206 uint32_t security_info,
208 struct security_descriptor **sd)
210 struct SMB4ACL_T *smb4acl = NULL;
211 TALLOC_CTX *frame = talloc_stackframe();
215 status = nfs4acl_get_blob(handle, NULL, smb_fname, frame, &blob);
216 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
218 return nfs4acl_xattr_default_sd(
219 handle, smb_fname, mem_ctx, sd);
221 if (!NT_STATUS_IS_OK(status)) {
226 status = nfs4acl_blob_to_smb4(handle, &blob, frame, &smb4acl);
227 if (!NT_STATUS_IS_OK(status)) {
232 status = smb_get_nt_acl_nfs4(handle->conn, smb_fname, NULL,
233 security_info, mem_ctx, sd,
239 static bool nfs4acl_smb4acl_set_fn(vfs_handle_struct *handle,
241 struct SMB4ACL_T *smb4acl)
243 struct nfs4acl_config *config = NULL;
248 SMB_VFS_HANDLE_GET_DATA(handle, config,
249 struct nfs4acl_config,
252 switch (config->encoding) {
253 case NFS4ACL_ENCODING_NDR:
254 status = nfs4acl_smb4acl_to_ndr_blob(handle, talloc_tos(),
258 status = NT_STATUS_INTERNAL_ERROR;
261 if (!NT_STATUS_IS_OK(status)) {
265 if (fsp->fh->fd != -1) {
266 ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, config->xattr_name,
267 blob.data, blob.length, 0);
269 ret = SMB_VFS_NEXT_SETXATTR(handle, fsp->fsp_name,
271 blob.data, blob.length, 0);
273 data_blob_free(&blob);
275 DBG_ERR("can't store acl in xattr: %s\n", strerror(errno));
282 static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
284 uint32_t security_info_sent,
285 const struct security_descriptor *psd)
287 struct nfs4acl_config *config = NULL;
289 SMB_VFS_HANDLE_GET_DATA(handle, config,
290 struct nfs4acl_config,
291 return NT_STATUS_INTERNAL_ERROR);
293 return smb_set_nt_acl_nfs4(handle,
295 &config->nfs4_params,
298 nfs4acl_smb4acl_set_fn);
301 static int nfs4acl_connect(struct vfs_handle_struct *handle,
305 struct nfs4acl_config *config = NULL;
306 const struct enum_list *default_acl_style_list = NULL;
307 const char *default_xattr_name = NULL;
309 unsigned nfs_version;
312 default_acl_style_list = get_default_acl_style_list();
314 config = talloc_zero(handle->conn, struct nfs4acl_config);
315 if (config == NULL) {
316 DBG_ERR("talloc_zero() failed\n");
320 ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
326 ret = smbacl4_get_vfs_params(handle->conn, &config->nfs4_params);
332 enumval = lp_parm_enum(SNUM(handle->conn),
336 NFS4ACL_ENCODING_NDR);
338 DBG_ERR("Invalid \"nfs4acl_xattr:encoding\" parameter\n");
341 config->encoding = (enum nfs4acl_encoding)enumval;
343 switch (config->encoding) {
344 case NFS4ACL_ENCODING_NDR:
346 default_xattr_name = NFS4ACL_NDR_XATTR_NAME;
350 nfs_version = (unsigned)lp_parm_int(SNUM(handle->conn),
354 switch (nfs_version) {
356 config->nfs_version = ACL4_XATTR_VERSION_40;
359 config->nfs_version = ACL4_XATTR_VERSION_41;
362 config->nfs_version = ACL4_XATTR_VERSION_DEFAULT;
366 config->default_acl_style = lp_parm_enum(SNUM(handle->conn),
369 default_acl_style_list,
370 DEFAULT_ACL_EVERYONE);
372 config->xattr_name = lp_parm_talloc_string(config,
378 SMB_VFS_HANDLE_SET_DATA(handle, config, NULL, struct nfs4acl_config,
382 * Ensure we have the parameters correct if we're using this module.
384 DBG_NOTICE("Setting 'inherit acls = true', "
385 "'dos filemode = true', "
386 "'force unknown acl user = true', "
387 "'create mask = 0666', "
388 "'directory mask = 0777' and "
389 "'store dos attributes = yes' "
390 "for service [%s]\n", service);
392 lp_do_parameter(SNUM(handle->conn), "inherit acls", "true");
393 lp_do_parameter(SNUM(handle->conn), "dos filemode", "true");
394 lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true");
395 lp_do_parameter(SNUM(handle->conn), "create mask", "0666");
396 lp_do_parameter(SNUM(handle->conn), "directory mask", "0777");
397 lp_do_parameter(SNUM(handle->conn), "store dos attributes", "yes");
403 As long as Samba does not support an exiplicit method for a module
404 to define conflicting vfs methods, we should override all conflicting
405 methods here. That way, we know we are using the NFSv4 storage
407 Function declarations taken from vfs_solarisacl
410 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file(vfs_handle_struct *handle,
411 const struct smb_filename *smb_fname,
415 return (SMB_ACL_T)NULL;
418 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd(vfs_handle_struct *handle,
422 return (SMB_ACL_T)NULL;
425 static int nfs4acl_xattr_fail__sys_acl_set_file(vfs_handle_struct *handle,
426 const struct smb_filename *smb_fname,
433 static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
440 static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
441 const struct smb_filename *smb_fname)
446 static int nfs4acl_xattr_fail__sys_acl_blob_get_file(vfs_handle_struct *handle,
447 const struct smb_filename *smb_fname,
449 char **blob_description,
455 static int nfs4acl_xattr_fail__sys_acl_blob_get_fd(vfs_handle_struct *handle, files_struct *fsp, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
460 /* VFS operations structure */
462 static struct vfs_fn_pointers nfs4acl_xattr_fns = {
463 .connect_fn = nfs4acl_connect,
464 .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl,
465 .get_nt_acl_fn = nfs4acl_xattr_get_nt_acl,
466 .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl,
468 .sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file,
469 .sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd,
470 .sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file,
471 .sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd,
472 .sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file,
473 .sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd,
474 .sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file,
477 NTSTATUS vfs_nfs4acl_xattr_init(TALLOC_CTX *);
478 NTSTATUS vfs_nfs4acl_xattr_init(TALLOC_CTX *ctx)
480 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",