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 NTSTATUS
zfs_get_nt_acl_common(const char *name
,
46 /* read the number of file aces */
47 if((naces
= acl(name
, ACE_GETACLCNT
, 0, NULL
)) == -1) {
49 DEBUG(9, ("acl(ACE_GETACLCNT, %s): Operation is not "
50 "supported on the filesystem where the file "
53 DEBUG(9, ("acl(ACE_GETACLCNT, %s): %s ", name
,
56 return map_nt_error_from_unix(errno
);
58 /* allocate the field of ZFS aces */
59 mem_ctx
= talloc_tos();
60 acebuf
= (ace_t
*) talloc_size(mem_ctx
, sizeof(ace_t
)*naces
);
62 return NT_STATUS_NO_MEMORY
;
64 /* read the aces into the field */
65 if(acl(name
, ACE_GETACL
, naces
, acebuf
) < 0) {
66 DEBUG(9, ("acl(ACE_GETACL, %s): %s ", name
,
68 return map_nt_error_from_unix(errno
);
70 /* create SMB4ACL data */
71 if((pacl
= smb_create_smb4acl()) == NULL
) {
72 return NT_STATUS_NO_MEMORY
;
74 for(i
=0; i
<naces
; i
++) {
75 SMB_ACE4PROP_T aceprop
;
77 aceprop
.aceType
= (uint32
) acebuf
[i
].a_type
;
78 aceprop
.aceFlags
= (uint32
) acebuf
[i
].a_flags
;
79 aceprop
.aceMask
= (uint32
) acebuf
[i
].a_access_mask
;
80 aceprop
.who
.id
= (uint32
) acebuf
[i
].a_who
;
82 if(aceprop
.aceFlags
& ACE_OWNER
) {
83 aceprop
.flags
= SMB_ACE4_ID_SPECIAL
;
84 aceprop
.who
.special_id
= SMB_ACE4_WHO_OWNER
;
85 } else if(aceprop
.aceFlags
& ACE_GROUP
) {
86 aceprop
.flags
= SMB_ACE4_ID_SPECIAL
;
87 aceprop
.who
.special_id
= SMB_ACE4_WHO_GROUP
;
88 } else if(aceprop
.aceFlags
& ACE_EVERYONE
) {
89 aceprop
.flags
= SMB_ACE4_ID_SPECIAL
;
90 aceprop
.who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
94 if(smb_add_ace4(pacl
, &aceprop
) == NULL
)
95 return NT_STATUS_NO_MEMORY
;
102 /* call-back function processing the NT acl -> ZFS acl using NFSv4 conv. */
103 static bool zfs_process_smbacl(files_struct
*fsp
, SMB4ACL_T
*smbacl
)
105 int naces
= smb_get_naces(smbacl
), i
;
110 /* allocate the field of ZFS aces */
111 mem_ctx
= talloc_tos();
112 acebuf
= (ace_t
*) talloc_size(mem_ctx
, sizeof(ace_t
)*naces
);
117 /* handle all aces */
118 for(smbace
= smb_first_ace4(smbacl
), i
= 0;
120 smbace
= smb_next_ace4(smbace
), i
++) {
121 SMB_ACE4PROP_T
*aceprop
= smb_get_ace4(smbace
);
123 acebuf
[i
].a_type
= aceprop
->aceType
;
124 acebuf
[i
].a_flags
= aceprop
->aceFlags
;
125 acebuf
[i
].a_access_mask
= aceprop
->aceMask
;
126 acebuf
[i
].a_who
= aceprop
->who
.id
;
127 if(aceprop
->flags
& SMB_ACE4_ID_SPECIAL
) {
128 switch(aceprop
->who
.special_id
) {
129 case SMB_ACE4_WHO_EVERYONE
:
130 acebuf
[i
].a_flags
|= ACE_EVERYONE
;
132 case SMB_ACE4_WHO_OWNER
:
133 acebuf
[i
].a_flags
|= ACE_OWNER
;
135 case SMB_ACE4_WHO_GROUP
:
136 acebuf
[i
].a_flags
|= ACE_GROUP
;
139 DEBUG(8, ("unsupported special_id %d\n", \
140 aceprop
->who
.special_id
));
141 continue; /* don't add it !!! */
145 SMB_ASSERT(i
== naces
);
148 if(acl(fsp
->fsp_name
, ACE_SETACL
, naces
, acebuf
)) {
149 if(errno
== ENOSYS
) {
150 DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not "
151 "supported on the filesystem where the file "
152 "reside", fsp
->fsp_name
));
154 DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp
->fsp_name
,
164 * set the local file's acls obtaining it in NT form
165 * using the NFSv4 format conversion
167 static NTSTATUS
zfs_set_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
,
168 uint32 security_info_sent
,
169 struct security_descriptor
*psd
)
171 return smb_set_nt_acl_nfs4(fsp
, security_info_sent
, psd
,
175 static NTSTATUS
zfsacl_fget_nt_acl(struct vfs_handle_struct
*handle
,
176 struct files_struct
*fsp
,
177 uint32 security_info
,
178 struct security_descriptor
**ppdesc
)
183 status
= zfs_get_nt_acl_common(fsp
->fsp_name
, security_info
, &pacl
);
184 if (!NT_STATUS_IS_OK(status
)) {
188 return smb_fget_nt_acl_nfs4(fsp
, security_info
, ppdesc
, pacl
);
191 static NTSTATUS
zfsacl_get_nt_acl(struct vfs_handle_struct
*handle
,
192 const char *name
, uint32 security_info
,
193 struct security_descriptor
**ppdesc
)
198 status
= zfs_get_nt_acl_common(name
, security_info
, &pacl
);
199 if (!NT_STATUS_IS_OK(status
)) {
203 return smb_get_nt_acl_nfs4(handle
->conn
, name
, security_info
, ppdesc
,
207 static NTSTATUS
zfsacl_fset_nt_acl(vfs_handle_struct
*handle
,
209 uint32 security_info_sent
,
212 return zfs_set_nt_acl(handle
, fsp
, security_info_sent
, psd
);
215 static NTSTATUS
zfsacl_set_nt_acl(vfs_handle_struct
*handle
,
217 const char *name
, uint32 security_info_sent
,
220 return zfs_set_nt_acl(handle
, fsp
, security_info_sent
, psd
);
223 /* VFS operations structure */
225 static vfs_op_tuple zfsacl_ops
[] = {
226 {SMB_VFS_OP(zfsacl_fget_nt_acl
), SMB_VFS_OP_FGET_NT_ACL
,
227 SMB_VFS_LAYER_OPAQUE
},
228 {SMB_VFS_OP(zfsacl_get_nt_acl
), SMB_VFS_OP_GET_NT_ACL
,
229 SMB_VFS_LAYER_OPAQUE
},
230 {SMB_VFS_OP(zfsacl_fset_nt_acl
), SMB_VFS_OP_FSET_NT_ACL
,
231 SMB_VFS_LAYER_OPAQUE
},
232 {SMB_VFS_OP(zfsacl_set_nt_acl
), SMB_VFS_OP_SET_NT_ACL
,
233 SMB_VFS_LAYER_OPAQUE
},
234 {SMB_VFS_OP(NULL
), SMB_VFS_OP_NOOP
, SMB_VFS_LAYER_NOOP
}
237 NTSTATUS
vfs_zfsacl_init(void);
238 NTSTATUS
vfs_zfsacl_init(void)
240 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "zfsacl",