2 * Copyright (C) Ralph Boehme 2017
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "smbd/proto.h"
21 #include "libcli/security/security_descriptor.h"
22 #include "libcli/security/security_token.h"
23 #include "nfs4_acls.h"
24 #include "nfs4acl_xattr.h"
27 #define DBGC_CLASS DBGC_VFS
30 /* <rpc/xdr.h> uses TRUE and FALSE */
39 #ifdef HAVE_RPC_TYPES_H
40 #include <rpc/types.h>
44 #include "nfs4acl_xattr_xdr.h"
45 #include "nfs4acl_xattr_util.h"
47 static unsigned nfs4acli_get_naces(nfsacl41i
*nacl
)
49 return nacl
->na41_aces
.na41_aces_len
;
52 static void nfs4acli_set_naces(nfsacl41i
*nacl
, unsigned naces
)
54 nacl
->na41_aces
.na41_aces_len
= naces
;
57 static unsigned nfs4acli_get_flags(nfsacl41i
*nacl
)
59 return nacl
->na41_flag
;
62 static void nfs4acli_set_flags(nfsacl41i
*nacl
, unsigned flags
)
64 nacl
->na41_flag
= flags
;
67 static size_t nfs4acli_get_xdrblob_size(nfsacl41i
*nacl
)
71 unsigned naces
= nfs4acli_get_naces(nacl
);
73 acl_size
= sizeof(aclflag4
) + sizeof(unsigned);
75 if (naces
> NFS4ACL_XDR_MAX_ACES
) {
76 DBG_ERR("Too many ACEs: %u\n", naces
);
80 aces_size
= naces
* sizeof(struct nfsace4i
);
81 if (acl_size
+ aces_size
< acl_size
) {
84 acl_size
+= aces_size
;
89 static size_t nfs4acli_get_xdrblob_naces(size_t _blobsize
)
91 size_t blobsize
= _blobsize
;
93 blobsize
-= sizeof(aclflag4
);
94 blobsize
-= sizeof(unsigned);
95 if (blobsize
> _blobsize
) {
98 return (blobsize
/ sizeof(struct nfsace4i
));
101 static nfsacl41i
*nfs4acli_alloc(TALLOC_CTX
*mem_ctx
, unsigned naces
)
103 size_t acl_size
= sizeof(nfsacl41i
) + (naces
* sizeof(struct nfsace4i
));
104 nfsacl41i
*nacl
= NULL
;
106 if (naces
> NFS4ACL_XDR_MAX_ACES
) {
107 DBG_ERR("Too many ACEs: %d\n", naces
);
111 nacl
= talloc_zero_size(mem_ctx
, acl_size
);
113 DBG_ERR("talloc_zero_size failed\n");
117 nfs4acli_set_naces(nacl
, naces
);
118 nacl
->na41_aces
.na41_aces_val
=
119 (nfsace4i
*)((char *)nacl
+ sizeof(nfsacl41i
));
124 static nfsace4i
*nfs4acli_get_ace(nfsacl41i
*nacl
, size_t n
)
126 return &nacl
->na41_aces
.na41_aces_val
[n
];
129 static bool smb4acl_to_nfs4acli(vfs_handle_struct
*handle
,
131 struct SMB4ACL_T
*smb4acl
,
134 struct nfs4acl_config
*config
= NULL
;
135 struct SMB4ACE_T
*smb4ace
= NULL
;
136 size_t smb4naces
= 0;
137 nfsacl41i
*nacl
= NULL
;
138 uint16_t smb4acl_flags
= 0;
139 unsigned nacl_flags
= 0;
141 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
142 struct nfs4acl_config
,
145 smb4naces
= smb_get_naces(smb4acl
);
146 nacl
= nfs4acli_alloc(mem_ctx
, smb4naces
);
147 nfs4acli_set_naces(nacl
, 0);
149 if (config
->nfs_version
> ACL4_XATTR_VERSION_40
) {
150 smb4acl_flags
= smbacl4_get_controlflags(smb4acl
);
151 nacl_flags
= smb4acl_to_nfs4acl_flags(smb4acl_flags
);
152 nfs4acli_set_flags(nacl
, nacl_flags
);
155 smb4ace
= smb_first_ace4(smb4acl
);
156 while (smb4ace
!= NULL
) {
157 SMB_ACE4PROP_T
*ace4prop
= smb_get_ace4(smb4ace
);
158 size_t nace_count
= nfs4acli_get_naces(nacl
);
159 nfsace4i
*nace
= nfs4acli_get_ace(nacl
, nace_count
);
161 nace
->type
= ace4prop
->aceType
;
162 nace
->flag
= ace4prop
->aceFlags
;
163 nace
->access_mask
= ace4prop
->aceMask
;
165 if (ace4prop
->flags
& SMB_ACE4_ID_SPECIAL
) {
166 nace
->iflag
|= ACEI4_SPECIAL_WHO
;
168 switch (ace4prop
->who
.special_id
) {
169 case SMB_ACE4_WHO_OWNER
:
170 nace
->who
= ACE4_SPECIAL_OWNER
;
173 case SMB_ACE4_WHO_GROUP
:
174 nace
->who
= ACE4_SPECIAL_GROUP
;
177 case SMB_ACE4_WHO_EVERYONE
:
178 nace
->who
= ACE4_SPECIAL_EVERYONE
;
182 DBG_ERR("Unsupported special id [%d]\n",
183 ace4prop
->who
.special_id
);
187 if (ace4prop
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) {
188 nace
->flag
|= ACE4_IDENTIFIER_GROUP
;
189 nace
->who
= ace4prop
->who
.gid
;
191 nace
->who
= ace4prop
->who
.uid
;
196 nfs4acli_set_naces(nacl
, nace_count
);
197 smb4ace
= smb_next_ace4(smb4ace
);
204 NTSTATUS
nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct
*handle
,
206 struct SMB4ACL_T
*smb4acl
,
209 nfsacl41i
*nacl
= NULL
;
215 ok
= smb4acl_to_nfs4acli(handle
, talloc_tos(), smb4acl
, &nacl
);
217 DBG_ERR("smb4acl_to_nfs4acl failed\n");
218 return NT_STATUS_INTERNAL_ERROR
;
221 aclblobsize
= nfs4acli_get_xdrblob_size(nacl
);
222 if (aclblobsize
== 0) {
223 return NT_STATUS_INTERNAL_ERROR
;
226 blob
= data_blob_talloc(mem_ctx
, NULL
, aclblobsize
);
227 if (blob
.data
== NULL
) {
229 return NT_STATUS_NO_MEMORY
;
232 xdrmem_create(&xdr
, (char *)blob
.data
, blob
.length
, XDR_ENCODE
);
234 ok
= xdr_nfsacl41i(&xdr
, nacl
);
237 DBG_ERR("xdr_nfs4acl41 failed\n");
238 return NT_STATUS_NO_MEMORY
;
245 static NTSTATUS
nfs4acl_xdr_blob_to_nfs4acli(struct vfs_handle_struct
*handle
,
250 struct nfs4acl_config
*config
= NULL
;
251 nfsacl41i
*nacl
= NULL
;
256 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
257 struct nfs4acl_config
,
258 return NT_STATUS_INTERNAL_ERROR
);
260 naces
= nfs4acli_get_xdrblob_naces(blob
->length
);
261 nacl
= nfs4acli_alloc(mem_ctx
, naces
);
263 xdrmem_create(&xdr
, (char *)blob
->data
, blob
->length
, XDR_DECODE
);
265 ok
= xdr_nfsacl41i(&xdr
, nacl
);
267 DBG_ERR("xdr_nfs4acl41 failed\n");
268 return NT_STATUS_INTERNAL_ERROR
;
271 if (config
->nfs_version
== ACL4_XATTR_VERSION_40
) {
279 static NTSTATUS
nfs4acli_to_smb4acl(struct vfs_handle_struct
*handle
,
282 struct SMB4ACL_T
**_smb4acl
)
284 struct nfs4acl_config
*config
= NULL
;
285 struct SMB4ACL_T
*smb4acl
= NULL
;
286 unsigned nfsacl41_flag
= 0;
287 uint16_t smb4acl_flags
= 0;
288 unsigned naces
= nfs4acli_get_naces(nacl
);
291 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
292 struct nfs4acl_config
,
293 return NT_STATUS_INTERNAL_ERROR
);
295 smb4acl
= smb_create_smb4acl(mem_ctx
);
296 if (smb4acl
== NULL
) {
297 return NT_STATUS_INTERNAL_ERROR
;
300 if (config
->nfs_version
> ACL4_XATTR_VERSION_40
) {
301 nfsacl41_flag
= nfs4acli_get_flags(nacl
);
302 smb4acl_flags
= nfs4acl_to_smb4acl_flags(nfsacl41_flag
);
303 smbacl4_set_controlflags(smb4acl
, smb4acl_flags
);
306 DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags
, naces
);
308 for (i
= 0; i
< naces
; i
++) {
309 nfsace4i
*nace
= nfs4acli_get_ace(nacl
, i
);
310 SMB_ACE4PROP_T smbace
= { 0 };
312 DBG_DEBUG("type [%d] iflag [%x] flag [%x] mask [%x] who [%d]\n",
313 nace
->type
, nace
->iflag
, nace
->flag
,
314 nace
->access_mask
, nace
->who
);
316 smbace
.aceType
= nace
->type
;
317 smbace
.aceFlags
= nace
->flag
;
318 smbace
.aceMask
= nace
->access_mask
;
320 if (nace
->iflag
& ACEI4_SPECIAL_WHO
) {
321 smbace
.flags
|= SMB_ACE4_ID_SPECIAL
;
324 case ACE4_SPECIAL_OWNER
:
325 smbace
.who
.special_id
= SMB_ACE4_WHO_OWNER
;
328 case ACE4_SPECIAL_GROUP
:
329 smbace
.who
.special_id
= SMB_ACE4_WHO_GROUP
;
332 case ACE4_SPECIAL_EVERYONE
:
333 smbace
.who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
337 DBG_ERR("Unknown special id [%d]\n", nace
->who
);
341 if (nace
->flag
& ACE4_IDENTIFIER_GROUP
) {
342 smbace
.who
.gid
= nace
->who
;
344 smbace
.who
.uid
= nace
->who
;
348 smb_add_ace4(smb4acl
, &smbace
);
355 NTSTATUS
nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct
*handle
,
358 struct SMB4ACL_T
**_smb4acl
)
360 struct nfs4acl_config
*config
= NULL
;
361 nfsacl41i
*nacl
= NULL
;
362 struct SMB4ACL_T
*smb4acl
= NULL
;
365 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
366 struct nfs4acl_config
,
367 return NT_STATUS_INTERNAL_ERROR
);
369 status
= nfs4acl_xdr_blob_to_nfs4acli(handle
, talloc_tos(), blob
, &nacl
);
370 if (!NT_STATUS_IS_OK(status
)) {
374 status
= nfs4acli_to_smb4acl(handle
, mem_ctx
, nacl
, &smb4acl
);
376 if (!NT_STATUS_IS_OK(status
)) {
384 #else /* !HAVE_RPC_XDR_H */
385 #include "nfs4acl_xattr_xdr.h"
386 NTSTATUS
nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct
*handle
,
389 struct SMB4ACL_T
**_smb4acl
)
391 return NT_STATUS_NOT_SUPPORTED
;
394 NTSTATUS
nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct
*handle
,
396 struct SMB4ACL_T
*smbacl
,
399 return NT_STATUS_NOT_SUPPORTED
;
401 #endif /* HAVE_RPC_XDR_H */