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 */
41 #include "nfs4acl_xattr_xdr.h"
43 static unsigned nfs4acl_get_naces(nfsacl41
*nacl
)
45 return nacl
->na41_aces
.na41_aces_len
;
48 static void nfs4acl_set_naces(nfsacl41
*nacl
, unsigned naces
)
50 nacl
->na41_aces
.na41_aces_len
= naces
;
53 static unsigned nfs4acl_get_flags(nfsacl41
*nacl
)
55 return nacl
->na41_flag
;
58 static void nfs4acl_set_flags(nfsacl41
*nacl
, unsigned flags
)
60 nacl
->na41_flag
= flags
;
63 static size_t nfs4acl_get_xdrblob_size(nfsacl41
*nacl
)
67 unsigned naces
= nfs4acl_get_naces(nacl
);
69 acl_size
= sizeof(aclflag4
) + sizeof(unsigned);
71 if (naces
> NFS4ACL_XDR_MAX_ACES
) {
72 DBG_ERR("Too many ACEs: %u", naces
);
76 aces_size
= naces
* sizeof(struct nfsace4
);
77 if (acl_size
+ aces_size
< acl_size
) {
80 acl_size
+= aces_size
;
85 static size_t nfs4acl_get_xdrblob_naces(size_t _blobsize
)
87 size_t blobsize
= _blobsize
;
89 blobsize
-= sizeof(aclflag4
);
90 blobsize
-= sizeof(unsigned);
91 if (blobsize
> _blobsize
) {
94 return (blobsize
/ sizeof(struct nfsace4
));
97 static nfsacl41
*nfs4acl_alloc(TALLOC_CTX
*mem_ctx
, unsigned naces
)
99 size_t acl_size
= sizeof(nfsacl41
) + (naces
* sizeof(struct nfsace4
));
100 nfsacl41
*nacl
= NULL
;
102 if (naces
> NFS4ACL_XDR_MAX_ACES
) {
103 DBG_ERR("Too many ACEs: %d\n", naces
);
107 nacl
= talloc_zero_size(mem_ctx
, acl_size
);
109 DBG_ERR("talloc_zero_size failed\n");
113 nfs4acl_set_naces(nacl
, naces
);
114 nacl
->na41_aces
.na41_aces_val
=
115 (nfsace4
*)((char *)nacl
+ sizeof(nfsacl41
));
120 static nfsace4
*nfs4acl_get_ace(nfsacl41
*nacl
, size_t n
)
122 return &nacl
->na41_aces
.na41_aces_val
[n
];
125 static unsigned smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags
)
127 unsigned nfs4acl_flags
= 0;
129 if (smb4acl_flags
& SEC_DESC_DACL_AUTO_INHERITED
) {
130 nfs4acl_flags
|= ACL4_AUTO_INHERIT
;
132 if (smb4acl_flags
& SEC_DESC_DACL_PROTECTED
) {
133 nfs4acl_flags
|= ACL4_PROTECTED
;
135 if (smb4acl_flags
& SEC_DESC_DACL_DEFAULTED
) {
136 nfs4acl_flags
|= ACL4_DEFAULTED
;
139 return nfs4acl_flags
;
142 static bool smb4acl_to_nfs4acl(vfs_handle_struct
*handle
,
144 struct SMB4ACL_T
*smb4acl
,
147 struct nfs4acl_config
*config
= NULL
;
148 struct SMB4ACE_T
*smb4ace
= NULL
;
149 size_t smb4naces
= 0;
150 nfsacl41
*nacl
= NULL
;
151 uint16_t smb4acl_flags
= 0;
152 unsigned nacl_flags
= 0;
154 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
155 struct nfs4acl_config
,
158 smb4naces
= smb_get_naces(smb4acl
);
159 nacl
= nfs4acl_alloc(mem_ctx
, smb4naces
);
160 nfs4acl_set_naces(nacl
, 0);
162 if (config
->nfs_version
> ACL4_XATTR_VERSION_40
) {
163 smb4acl_flags
= smbacl4_get_controlflags(smb4acl
);
164 nacl_flags
= smb4acl_to_nfs4acl_flags(smb4acl_flags
);
165 nfs4acl_set_flags(nacl
, nacl_flags
);
168 smb4ace
= smb_first_ace4(smb4acl
);
169 while (smb4ace
!= NULL
) {
170 SMB_ACE4PROP_T
*ace4prop
= smb_get_ace4(smb4ace
);
171 size_t nace_count
= nfs4acl_get_naces(nacl
);
172 nfsace4
*nace
= nfs4acl_get_ace(nacl
, nace_count
);
174 nace
->type
= ace4prop
->aceType
;
175 nace
->flag
= ace4prop
->aceFlags
;
176 nace
->access_mask
= ace4prop
->aceMask
;
178 if (ace4prop
->flags
& SMB_ACE4_ID_SPECIAL
) {
179 nace
->iflag
|= ACEI4_SPECIAL_WHO
;
181 switch (ace4prop
->who
.special_id
) {
182 case SMB_ACE4_WHO_OWNER
:
183 nace
->who
= ACE4_SPECIAL_OWNER
;
186 case SMB_ACE4_WHO_GROUP
:
187 nace
->who
= ACE4_SPECIAL_GROUP
;
190 case SMB_ACE4_WHO_EVERYONE
:
191 nace
->who
= ACE4_SPECIAL_EVERYONE
;
195 DBG_ERR("Unsupported special id [%d]\n",
196 ace4prop
->who
.special_id
);
200 if (ace4prop
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) {
201 nace
->flag
|= ACE4_IDENTIFIER_GROUP
;
202 nace
->who
= ace4prop
->who
.gid
;
204 nace
->who
= ace4prop
->who
.uid
;
209 nfs4acl_set_naces(nacl
, nace_count
);
210 smb4ace
= smb_next_ace4(smb4ace
);
217 NTSTATUS
nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct
*handle
,
219 struct SMB4ACL_T
*smb4acl
,
222 nfsacl41
*nacl
= NULL
;
228 ok
= smb4acl_to_nfs4acl(handle
, talloc_tos(), smb4acl
, &nacl
);
230 DBG_ERR("smb4acl_to_nfs4acl failed\n");
231 return NT_STATUS_INTERNAL_ERROR
;
234 aclblobsize
= nfs4acl_get_xdrblob_size(nacl
);
235 if (aclblobsize
== 0) {
236 return NT_STATUS_INTERNAL_ERROR
;
239 blob
= data_blob_talloc(mem_ctx
, NULL
, aclblobsize
);
240 if (blob
.data
== NULL
) {
242 return NT_STATUS_NO_MEMORY
;
245 xdrmem_create(&xdr
, (char *)blob
.data
, blob
.length
, XDR_ENCODE
);
247 ok
= xdr_nfsacl41(&xdr
, nacl
);
250 DBG_ERR("xdr_nfs4acl41 failed\n");
251 return NT_STATUS_NO_MEMORY
;
258 static uint16_t nfs4acl_to_smb4acl_flags(unsigned nfsacl41_flags
)
260 uint16_t smb4acl_flags
= SEC_DESC_SELF_RELATIVE
;
262 if (nfsacl41_flags
& ACL4_AUTO_INHERIT
) {
263 smb4acl_flags
|= SEC_DESC_DACL_AUTO_INHERITED
;
265 if (nfsacl41_flags
& ACL4_PROTECTED
) {
266 smb4acl_flags
|= SEC_DESC_DACL_PROTECTED
;
268 if (nfsacl41_flags
& ACL4_DEFAULTED
) {
269 smb4acl_flags
|= SEC_DESC_DACL_DEFAULTED
;
272 return smb4acl_flags
;
275 static NTSTATUS
nfs4acl_xdr_blob_to_nfs4acl(struct vfs_handle_struct
*handle
,
280 struct nfs4acl_config
*config
= NULL
;
281 nfsacl41
*nacl
= NULL
;
286 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
287 struct nfs4acl_config
,
288 return NT_STATUS_INTERNAL_ERROR
);
290 naces
= nfs4acl_get_xdrblob_naces(blob
->length
);
291 nacl
= nfs4acl_alloc(mem_ctx
, naces
);
293 xdrmem_create(&xdr
, (char *)blob
->data
, blob
->length
, XDR_DECODE
);
295 ok
= xdr_nfsacl41(&xdr
, nacl
);
297 DBG_ERR("xdr_nfs4acl41 failed\n");
298 return NT_STATUS_INTERNAL_ERROR
;
301 if (config
->nfs_version
== ACL4_XATTR_VERSION_40
) {
309 static NTSTATUS
nfs4acl_to_smb4acl(struct vfs_handle_struct
*handle
,
312 struct SMB4ACL_T
**_smb4acl
)
314 struct nfs4acl_config
*config
= NULL
;
315 struct SMB4ACL_T
*smb4acl
= NULL
;
316 unsigned nfsacl41_flag
= 0;
317 uint16_t smb4acl_flags
= 0;
318 unsigned naces
= nfs4acl_get_naces(nacl
);
321 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
322 struct nfs4acl_config
,
323 return NT_STATUS_INTERNAL_ERROR
);
325 smb4acl
= smb_create_smb4acl(mem_ctx
);
326 if (smb4acl
== NULL
) {
327 return NT_STATUS_INTERNAL_ERROR
;
330 if (config
->nfs_version
> ACL4_XATTR_VERSION_40
) {
331 nfsacl41_flag
= nfs4acl_get_flags(nacl
);
332 smb4acl_flags
= nfs4acl_to_smb4acl_flags(nfsacl41_flag
);
333 smbacl4_set_controlflags(smb4acl
, smb4acl_flags
);
336 DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags
, naces
);
338 for (i
= 0; i
< naces
; i
++) {
339 nfsace4
*nace
= nfs4acl_get_ace(nacl
, i
);
340 SMB_ACE4PROP_T smbace
= { 0 };
342 DBG_DEBUG("type [%d] iflag [%x] flag [%x] mask [%x] who [%d]\n",
343 nace
->type
, nace
->iflag
, nace
->flag
,
344 nace
->access_mask
, nace
->who
);
346 smbace
.aceType
= nace
->type
;
347 smbace
.aceFlags
= nace
->flag
;
348 smbace
.aceMask
= nace
->access_mask
;
350 if (nace
->iflag
& ACEI4_SPECIAL_WHO
) {
351 smbace
.flags
|= SMB_ACE4_ID_SPECIAL
;
354 case ACE4_SPECIAL_OWNER
:
355 smbace
.who
.special_id
= SMB_ACE4_WHO_OWNER
;
358 case ACE4_SPECIAL_GROUP
:
359 smbace
.who
.special_id
= SMB_ACE4_WHO_GROUP
;
362 case ACE4_SPECIAL_EVERYONE
:
363 smbace
.who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
367 DBG_ERR("Unknown special id [%d]\n", nace
->who
);
371 if (nace
->flag
& ACE4_IDENTIFIER_GROUP
) {
372 smbace
.who
.gid
= nace
->who
;
374 smbace
.who
.uid
= nace
->who
;
378 smb_add_ace4(smb4acl
, &smbace
);
385 NTSTATUS
nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct
*handle
,
388 struct SMB4ACL_T
**_smb4acl
)
390 struct nfs4acl_config
*config
= NULL
;
391 nfsacl41
*nacl
= NULL
;
392 struct SMB4ACL_T
*smb4acl
= NULL
;
395 SMB_VFS_HANDLE_GET_DATA(handle
, config
,
396 struct nfs4acl_config
,
397 return NT_STATUS_INTERNAL_ERROR
);
399 status
= nfs4acl_xdr_blob_to_nfs4acl(handle
, talloc_tos(), blob
, &nacl
);
400 if (!NT_STATUS_IS_OK(status
)) {
404 status
= nfs4acl_to_smb4acl(handle
, mem_ctx
, nacl
, &smb4acl
);
406 if (!NT_STATUS_IS_OK(status
)) {
414 #else /* !HAVE_RPC_XDR_H */
415 #include "nfs4acl_xattr_xdr.h"
416 NTSTATUS
nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct
*handle
,
419 struct SMB4ACL_T
**_smb4acl
)
421 return NT_STATUS_NOT_SUPPORTED
;
424 NTSTATUS
nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct
*handle
,
426 struct SMB4ACL_T
*smbacl
,
429 return NT_STATUS_NOT_SUPPORTED
;
431 #endif /* HAVE_RPC_XDR_H */