selftest:Samba4: report when samba is started and ready
[Samba.git] / source3 / modules / nfs4acl_xattr_xdr.c
blob399c104faa4c33aa1f58a1833f82fd24b8c636f8
1 /*
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/>.
19 #include "includes.h"
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"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_VFS
29 #ifdef HAVE_RPC_XDR_H
30 /* <rpc/xdr.h> uses TRUE and FALSE */
31 #ifdef TRUE
32 #undef TRUE
33 #endif
35 #ifdef FALSE
36 #undef FALSE
37 #endif
39 #include <rpc/xdr.h>
40 #include "nfs41acl.h"
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)
65 size_t acl_size;
66 size_t aces_size;
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);
73 return 0;
76 aces_size = naces * sizeof(struct nfsace4);
77 if (acl_size + aces_size < acl_size) {
78 return 0;
80 acl_size += aces_size;
82 return acl_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) {
92 return 0;
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);
104 return NULL;
107 nacl = talloc_zero_size(mem_ctx, acl_size);
108 if (nacl == NULL) {
109 DBG_ERR("talloc_zero_size failed\n");
110 return NULL;
113 nfs4acl_set_naces(nacl, naces);
114 nacl->na41_aces.na41_aces_val =
115 (nfsace4 *)((char *)nacl + sizeof(nfsacl41));
117 return nacl;
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,
143 TALLOC_CTX *mem_ctx,
144 struct SMB4ACL_T *smb4acl,
145 nfsacl41 **_nacl)
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,
156 return false);
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;
184 break;
186 case SMB_ACE4_WHO_GROUP:
187 nace->who = ACE4_SPECIAL_GROUP;
188 break;
190 case SMB_ACE4_WHO_EVERYONE:
191 nace->who = ACE4_SPECIAL_EVERYONE;
192 break;
194 default:
195 DBG_ERR("Unsupported special id [%d]\n",
196 ace4prop->who.special_id);
197 continue;
199 } else {
200 if (ace4prop->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
201 nace->flag |= ACE4_IDENTIFIER_GROUP;
202 nace->who = ace4prop->who.gid;
203 } else {
204 nace->who = ace4prop->who.uid;
208 nace_count++;
209 nfs4acl_set_naces(nacl, nace_count);
210 smb4ace = smb_next_ace4(smb4ace);
213 *_nacl = nacl;
214 return true;
217 NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
218 TALLOC_CTX *mem_ctx,
219 struct SMB4ACL_T *smb4acl,
220 DATA_BLOB *_blob)
222 nfsacl41 *nacl = NULL;
223 XDR xdr = {0};
224 size_t aclblobsize;
225 DATA_BLOB blob;
226 bool ok;
228 ok = smb4acl_to_nfs4acl(handle, talloc_tos(), smb4acl, &nacl);
229 if (!ok) {
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) {
241 TALLOC_FREE(nacl);
242 return NT_STATUS_NO_MEMORY;
245 xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE);
247 ok = xdr_nfsacl41(&xdr, nacl);
248 TALLOC_FREE(nacl);
249 if (!ok) {
250 DBG_ERR("xdr_nfs4acl41 failed\n");
251 return NT_STATUS_NO_MEMORY;
254 *_blob = blob;
255 return NT_STATUS_OK;
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,
276 TALLOC_CTX *mem_ctx,
277 DATA_BLOB *blob,
278 nfsacl41 **_nacl)
280 struct nfs4acl_config *config = NULL;
281 nfsacl41 *nacl = NULL;
282 size_t naces;
283 XDR xdr = {0};
284 bool ok;
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);
296 if (!ok) {
297 DBG_ERR("xdr_nfs4acl41 failed\n");
298 return NT_STATUS_INTERNAL_ERROR;
301 if (config->nfs_version == ACL4_XATTR_VERSION_40) {
302 nacl->na41_flag = 0;
305 *_nacl = nacl;
306 return NT_STATUS_OK;
309 static NTSTATUS nfs4acl_to_smb4acl(struct vfs_handle_struct *handle,
310 TALLOC_CTX *mem_ctx,
311 nfsacl41 *nacl,
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);
319 int i;
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;
353 switch (nace->who) {
354 case ACE4_SPECIAL_OWNER:
355 smbace.who.special_id = SMB_ACE4_WHO_OWNER;
356 break;
358 case ACE4_SPECIAL_GROUP:
359 smbace.who.special_id = SMB_ACE4_WHO_GROUP;
360 break;
362 case ACE4_SPECIAL_EVERYONE:
363 smbace.who.special_id = SMB_ACE4_WHO_EVERYONE;
364 break;
366 default:
367 DBG_ERR("Unknown special id [%d]\n", nace->who);
368 continue;
370 } else {
371 if (nace->flag & ACE4_IDENTIFIER_GROUP) {
372 smbace.who.gid = nace->who;
373 } else {
374 smbace.who.uid = nace->who;
378 smb_add_ace4(smb4acl, &smbace);
381 *_smb4acl = smb4acl;
382 return NT_STATUS_OK;
385 NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
386 TALLOC_CTX *mem_ctx,
387 DATA_BLOB *blob,
388 struct SMB4ACL_T **_smb4acl)
390 struct nfs4acl_config *config = NULL;
391 nfsacl41 *nacl = NULL;
392 struct SMB4ACL_T *smb4acl = NULL;
393 NTSTATUS status;
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)) {
401 return status;
404 status = nfs4acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
405 TALLOC_FREE(nacl);
406 if (!NT_STATUS_IS_OK(status)) {
407 return status;
410 *_smb4acl = smb4acl;
411 return NT_STATUS_OK;
414 #else /* !HAVE_RPC_XDR_H */
415 #include "nfs4acl_xattr_xdr.h"
416 NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
417 TALLOC_CTX *mem_ctx,
418 DATA_BLOB *blob,
419 struct SMB4ACL_T **_smb4acl)
421 return NT_STATUS_NOT_SUPPORTED;
424 NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
425 TALLOC_CTX *mem_ctx,
426 struct SMB4ACL_T *smbacl,
427 DATA_BLOB *blob)
429 return NT_STATUS_NOT_SUPPORTED;
431 #endif /* HAVE_RPC_XDR_H */