2 * Convert ZFS/NFSv4 acls 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
7 * Many thanks to Axel Apitz for help to fix the special ace's handling
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 #include "nfs4_acls.h"
29 #define DBGC_CLASS DBGC_VFS
31 #define ZFSACL_MODULE_NAME "zfsacl"
34 * read the local file's acls and return it in NT form
35 * using the NFSv4 format conversion
37 static size_t zfs_get_nt_acl(struct files_struct
*fsp
, uint32 security_info
,
38 struct security_descriptor
**ppdesc
)
45 /* read the number of file aces */
46 if((naces
= acl(fsp
->fsp_name
, ACE_GETACLCNT
, 0, NULL
)) == -1) {
48 DEBUG(9, ("acl(ACE_GETACLCNT, %s): Operation is not supported on the filesystem where the file reside"));
50 DEBUG(9, ("acl(ACE_GETACLCNT, %s): %s ", fsp
->fsp_name
,
55 /* allocate the field of ZFS aces */
56 mem_ctx
= main_loop_talloc_get();
57 acebuf
= (ace_t
*) talloc_size(mem_ctx
, sizeof(ace_t
)*naces
);
62 /* read the aces into the field */
63 if(acl(fsp
->fsp_name
, ACE_GETACL
, naces
, acebuf
) < 0) {
64 DEBUG(9, ("acl(ACE_GETACL, %s): %s ", fsp
->fsp_name
,
68 /* create SMB4ACL data */
69 if((pacl
= smb_create_smb4acl()) == NULL
) return 0;
70 for(i
=0; i
<naces
; i
++) {
71 SMB_ACE4PROP_T aceprop
;
73 aceprop
.aceType
= (uint32
) acebuf
[i
].a_type
;
74 aceprop
.aceFlags
= (uint32
) acebuf
[i
].a_flags
;
75 aceprop
.aceMask
= (uint32
) acebuf
[i
].a_access_mask
;
76 aceprop
.who
.id
= (uint32
) acebuf
[i
].a_who
;
78 if(aceprop
.aceFlags
& ACE_OWNER
) {
79 aceprop
.flags
= SMB_ACE4_ID_SPECIAL
;
80 aceprop
.who
.special_id
= SMB_ACE4_WHO_OWNER
;
81 } else if(aceprop
.aceFlags
& ACE_GROUP
) {
82 aceprop
.flags
= SMB_ACE4_ID_SPECIAL
;
83 aceprop
.who
.special_id
= SMB_ACE4_WHO_GROUP
;
84 } else if(aceprop
.aceFlags
& ACE_EVERYONE
) {
85 aceprop
.flags
= SMB_ACE4_ID_SPECIAL
;
86 aceprop
.who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
90 if(smb_add_ace4(pacl
, &aceprop
) == NULL
) return 0;
93 return smb_get_nt_acl_nfs4(fsp
, security_info
, ppdesc
, pacl
);
96 /* call-back function processing the NT acl -> ZFS acl using NFSv4 conv. */
97 static BOOL
zfs_process_smbacl(files_struct
*fsp
, SMB4ACL_T
*smbacl
)
99 int naces
= smb_get_naces(smbacl
), i
;
104 /* allocate the field of ZFS aces */
105 mem_ctx
= main_loop_talloc_get();
106 acebuf
= (ace_t
*) talloc_size(mem_ctx
, sizeof(ace_t
)*naces
);
111 /* handle all aces */
112 for(smbace
= smb_first_ace4(smbacl
), i
= 0;
114 smbace
= smb_next_ace4(smbace
), i
++) {
115 SMB_ACE4PROP_T
*aceprop
= smb_get_ace4(smbace
);
117 acebuf
[i
].a_type
= aceprop
->aceType
;
118 acebuf
[i
].a_flags
= aceprop
->aceFlags
;
119 acebuf
[i
].a_access_mask
= aceprop
->aceMask
;
120 acebuf
[i
].a_who
= aceprop
->who
.id
;
121 if(aceprop
->flags
& SMB_ACE4_ID_SPECIAL
) {
122 switch(aceprop
->who
.special_id
) {
123 case SMB_ACE4_WHO_EVERYONE
:
124 acebuf
[i
].a_flags
|= ACE_EVERYONE
;
126 case SMB_ACE4_WHO_OWNER
:
127 acebuf
[i
].a_flags
|= ACE_OWNER
;
129 case SMB_ACE4_WHO_GROUP
:
130 acebuf
[i
].a_flags
|= ACE_GROUP
;
133 DEBUG(8, ("unsupported special_id %d\n", \
134 aceprop
->who
.special_id
));
135 continue; /* don't add it !!! */
139 SMB_ASSERT(i
== naces
);
142 if(acl(fsp
->fsp_name
, ACE_SETACL
, naces
, acebuf
)) {
143 if(errno
== ENOSYS
) {
144 DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not supported on the filesystem where the file reside"));
146 DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp
->fsp_name
,
156 * set the local file's acls obtaining it in NT form
157 * using the NFSv4 format conversion
159 static NTSTATUS
zfs_set_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
,
160 uint32 security_info_sent
,
161 struct security_descriptor
*psd
)
163 return smb_set_nt_acl_nfs4(fsp
, security_info_sent
, psd
,
167 static size_t zfsacl_fget_nt_acl(struct vfs_handle_struct
*handle
,
168 struct files_struct
*fsp
,
169 int fd
, uint32 security_info
,
170 struct security_descriptor
**ppdesc
)
172 return zfs_get_nt_acl(fsp
, security_info
, ppdesc
);
175 static size_t zfsacl_get_nt_acl(struct vfs_handle_struct
*handle
,
176 struct files_struct
*fsp
,
177 const char *name
, uint32 security_info
,
178 struct security_descriptor
**ppdesc
)
180 return zfs_get_nt_acl(fsp
, security_info
, ppdesc
);
183 static NTSTATUS
zfsacl_fset_nt_acl(vfs_handle_struct
*handle
,
185 int fd
, uint32 security_info_sent
,
188 return zfs_set_nt_acl(handle
, fsp
, security_info_sent
, psd
);
191 static NTSTATUS
zfsacl_set_nt_acl(vfs_handle_struct
*handle
,
193 const char *name
, uint32 security_info_sent
,
196 return zfs_set_nt_acl(handle
, fsp
, security_info_sent
, psd
);
199 /* VFS operations structure */
201 static vfs_op_tuple zfsacl_ops
[] = {
202 {SMB_VFS_OP(zfsacl_fget_nt_acl
), SMB_VFS_OP_FGET_NT_ACL
,
203 SMB_VFS_LAYER_OPAQUE
},
204 {SMB_VFS_OP(zfsacl_get_nt_acl
), SMB_VFS_OP_GET_NT_ACL
,
205 SMB_VFS_LAYER_OPAQUE
},
206 {SMB_VFS_OP(zfsacl_fset_nt_acl
), SMB_VFS_OP_FSET_NT_ACL
,
207 SMB_VFS_LAYER_OPAQUE
},
208 {SMB_VFS_OP(zfsacl_set_nt_acl
), SMB_VFS_OP_SET_NT_ACL
,
209 SMB_VFS_LAYER_OPAQUE
},
210 {SMB_VFS_OP(NULL
), SMB_VFS_OP_NOOP
, SMB_VFS_LAYER_NOOP
}
213 /* != 0 if this module will be compiled as static */
218 NTSTATUS
vfs_zfsacl_init(void);
220 NTSTATUS
init_module(void);
231 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "zfsacl",