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 "librpc/gen_ndr/xattr.h" 25#include "librpc/gen_ndr/ndr_xattr.h" 26#include "../lib/crypto/crypto.h" 27 28#undef DBGC_CLASS 29#define DBGC_CLASS DBGC_VFS 30 31/* Pull in the common functions. */ 32#define ACL_MODULE_NAME "acl_xattr" 33 34#include "modules/vfs_acl_common.c" 35 36/******************************************************************* 37 Pull a security descriptor into a DATA_BLOB from a xattr. 38*******************************************************************/ 39 40static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, 41 vfs_handle_struct *handle, 42 files_struct *fsp, 43 const char *name, 44 DATA_BLOB *pblob) 45{ 46 size_t size = 1024; 47 uint8_t *val = NULL; 48 uint8_t *tmp; 49 ssize_t sizeret; 50 int saved_errno = 0; 51 52 ZERO_STRUCTP(pblob); 53 54 again: 55 56 tmp = TALLOC_REALLOC_ARRAY(ctx, val, uint8_t, size); 57 if (tmp == NULL) { 58 TALLOC_FREE(val); 59 return NT_STATUS_NO_MEMORY; 60 } 61 val = tmp; 62 63 become_root(); 64 if (fsp && fsp->fh->fd != -1) { 65 sizeret = SMB_VFS_FGETXATTR(fsp, XATTR_NTACL_NAME, val, size); 66 } else { 67 sizeret = SMB_VFS_GETXATTR(handle->conn, name, 68 XATTR_NTACL_NAME, val, size); 69 } 70 if (sizeret == -1) { 71 saved_errno = errno; 72 } 73 unbecome_root(); 74 75 /* Max ACL size is 65536 bytes. */ 76 if (sizeret == -1) { 77 errno = saved_errno; 78 if ((errno == ERANGE) && (size != 65536)) { 79 /* Too small, try again. */ 80 size = 65536; 81 goto again; 82 } 83 84 /* Real error - exit here. */ 85 TALLOC_FREE(val); 86 return map_nt_error_from_unix(errno); 87 } 88 89 pblob->data = val; 90 pblob->length = sizeret; 91 return NT_STATUS_OK; 92} 93 94/******************************************************************* 95 Store a DATA_BLOB into an xattr given an fsp pointer. 96*******************************************************************/ 97 98static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, 99 files_struct *fsp, 100 DATA_BLOB *pblob) 101{ 102 int ret; 103 int saved_errno = 0; 104 105 DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", 106 (unsigned int)pblob->length, fsp_str_dbg(fsp))); 107 108 become_root(); 109 if (fsp->fh->fd != -1) { 110 ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME, 111 pblob->data, pblob->length, 0); 112 } else { 113 ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name, 114 XATTR_NTACL_NAME, 115 pblob->data, pblob->length, 0); 116 } 117 if (ret) { 118 saved_errno = errno; 119 } 120 unbecome_root(); 121 if (ret) { 122 errno = saved_errno; 123 DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s" 124 "with error %s\n", 125 fsp_str_dbg(fsp), 126 strerror(errno) )); 127 return map_nt_error_from_unix(errno); 128 } 129 return NT_STATUS_OK; 130} 131 132/********************************************************************* 133 Remove a Windows ACL - we're setting the underlying POSIX ACL. 134*********************************************************************/ 135 136static int sys_acl_set_file_xattr(vfs_handle_struct *handle, 137 const char *name, 138 SMB_ACL_TYPE_T type, 139 SMB_ACL_T theacl) 140{ 141 int ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, 142 name, 143 type, 144 theacl); 145 if (ret == -1) { 146 return -1; 147 } 148 149 become_root(); 150 SMB_VFS_REMOVEXATTR(handle->conn, name, XATTR_NTACL_NAME); 151 unbecome_root(); 152 153 return ret; 154} 155 156/********************************************************************* 157 Remove a Windows ACL - we're setting the underlying POSIX ACL. 158*********************************************************************/ 159 160static int sys_acl_set_fd_xattr(vfs_handle_struct *handle, 161 files_struct *fsp, 162 SMB_ACL_T theacl) 163{ 164 int ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, 165 fsp, 166 theacl); 167 if (ret == -1) { 168 return -1; 169 } 170 171 become_root(); 172 SMB_VFS_FREMOVEXATTR(fsp, XATTR_NTACL_NAME); 173 unbecome_root(); 174 175 return ret; 176} 177 178static int connect_acl_xattr(struct vfs_handle_struct *handle, 179 const char *service, 180 const char *user) 181{ 182 int ret = SMB_VFS_NEXT_CONNECT(handle, service, user); 183 184 if (ret < 0) { 185 return ret; 186 } 187 188 /* Ensure we have the parameters correct if we're 189 * using this module. */ 190 DEBUG(2,("connect_acl_xattr: setting 'inherit acls = true' " 191 "'dos filemode = true' and " 192 "'force unknown acl user = true' for service %s\n", 193 service )); 194 195 lp_do_parameter(SNUM(handle->conn), "inherit acls", "true"); 196 lp_do_parameter(SNUM(handle->conn), "dos filemode", "true"); 197 lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true"); 198 199 return 0; 200} 201 202static struct vfs_fn_pointers vfs_acl_xattr_fns = { 203 .connect_fn = connect_acl_xattr, 204 .opendir = opendir_acl_common, 205 .mkdir = mkdir_acl_common, 206 .rmdir = rmdir_acl_common, 207 .open = open_acl_common, 208 .create_file = create_file_acl_common, 209 .unlink = unlink_acl_common, 210 .fget_nt_acl = fget_nt_acl_common, 211 .get_nt_acl = get_nt_acl_common, 212 .fset_nt_acl = fset_nt_acl_common, 213 .sys_acl_set_file = sys_acl_set_file_xattr, 214 .sys_acl_set_fd = sys_acl_set_fd_xattr 215}; 216 217NTSTATUS vfs_acl_xattr_init(void) 218{ 219 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_xattr", 220 &vfs_acl_xattr_fns); 221} 222