rpc_server3: Use fdopen_keepfd()
[Samba.git] / source3 / modules / nfs4acl_xattr_nfs.c
blobdf3c0f5269796c2c2b251b181873341cffabfdd0
1 /*
2 * Copyright (C) Ralph Boehme 2018
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 "system/passwd.h"
22 #include "libcli/security/security_descriptor.h"
23 #include "libcli/security/security_token.h"
25 #ifdef HAVE_RPC_XDR_H
26 /* <rpc/xdr.h> uses TRUE and FALSE */
27 #ifdef TRUE
28 #undef TRUE
29 #endif
31 #ifdef FALSE
32 #undef FALSE
33 #endif
35 #ifdef HAVE_RPC_TYPES_H
36 #include <rpc/types.h>
37 #endif
38 #include <rpc/xdr.h>
40 #include "nfs4_acls.h"
41 #include "nfs41acl.h"
42 #include "nfs4acl_xattr.h"
43 #include "nfs4acl_xattr_nfs.h"
44 #include "nfs4acl_xattr_util.h"
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_VFS
49 #define OVERFLOW_CHECK(val1, val2) ((val1) + (val2) < (val1))
50 #define XDR_UTF8STR_ALIGNMENT 4
51 #define XDR_UTF8STR_ALIGN(l) \
52 (((l) + ((XDR_UTF8STR_ALIGNMENT) - 1)) & ~((XDR_UTF8STR_ALIGNMENT) - 1))
54 static struct nfs4_to_smb4_id_map {
55 const char *nfs4_id;
56 uint32_t smb4_id;
57 } nfs4_to_smb4_id_map[] = {
58 {"OWNER@", SMB_ACE4_WHO_OWNER},
59 {"GROUP@", SMB_ACE4_WHO_GROUP},
60 {"EVERYONE@", SMB_ACE4_WHO_EVERYONE},
61 {"INTERACTIVE@", SMB_ACE4_WHO_INTERACTIVE},
62 {"NETWORK@", SMB_ACE4_WHO_NETWORK},
63 {"DIALUP@", SMB_ACE4_WHO_DIALUP},
64 {"BATCH@", SMB_ACE4_WHO_BATCH},
65 {"ANONYMOUS@", SMB_ACE4_WHO_ANONYMOUS},
66 {"AUTHENTICATED@", SMB_ACE4_WHO_AUTHENTICATED},
67 {"SERVICE@", SMB_ACE4_WHO_SERVICE},
70 static bool is_special_nfs4_id(const char *nfs4_id)
72 char *at = NULL;
74 at = strchr(nfs4_id, '@');
75 if (at == NULL) {
76 return false;
78 if (at[1] != '\0') {
79 return false;
81 return true;
84 static bool map_special_nfs4_to_smb4_id(const char *nfs4_id, uint32_t *smb4_id)
86 size_t i;
87 int cmp;
89 for (i = 0; i < ARRAY_SIZE(nfs4_to_smb4_id_map); i++) {
90 cmp = strcmp(nfs4_to_smb4_id_map[i].nfs4_id, nfs4_id);
91 if (cmp != 0) {
92 continue;
94 *smb4_id = nfs4_to_smb4_id_map[i].smb4_id;
95 return true;
97 return false;
100 static bool map_special_smb4_to_nfs4_id(uint32_t smb4_id, const char **nfs4_id)
102 size_t i;
104 for (i = 0; i < ARRAY_SIZE(nfs4_to_smb4_id_map); i++) {
105 if (nfs4_to_smb4_id_map[i].smb4_id != smb4_id) {
106 continue;
108 *nfs4_id = nfs4_to_smb4_id_map[i].nfs4_id;
109 return true;
111 return false;
114 static unsigned nfs40acl_get_naces(nfsacl40 *nacl)
116 return nacl->na40_aces.na40_aces_len;
119 static unsigned nfs41acl_get_naces(nfsacl41 *nacl)
121 return nacl->na41_aces.na41_aces_len;
124 static void nfs40acl_set_naces(nfsacl40 *nacl, unsigned naces)
126 nacl->na40_aces.na40_aces_len = naces;
129 static void nfs41acl_set_naces(nfsacl41 *nacl, unsigned naces)
131 nacl->na41_aces.na41_aces_len = naces;
134 static unsigned nfs41acl_get_flags(nfsacl41 *nacl)
136 return nacl->na41_flag;
139 static void nfs41acl_set_flags(nfsacl41 *nacl, unsigned flags)
141 nacl->na41_flag = flags;
144 static nfsace4 *nfs40acl_get_ace(nfsacl40 *nacl, size_t n)
146 return &nacl->na40_aces.na40_aces_val[n];
149 static nfsace4 *nfs41acl_get_ace(nfsacl41 *nacl, size_t n)
151 return &nacl->na41_aces.na41_aces_val[n];
154 static size_t nfs40acl_get_xdrblob_size(nfsacl40 *nacl)
156 size_t acl_size;
157 size_t aces_size;
158 size_t identifier_size;
159 unsigned i;
160 unsigned naces = nfs40acl_get_naces(nacl);
162 /* ACE structure minus actual identifier strings */
163 struct nfsace4_size {
164 acetype4 type;
165 aceflag4 flag;
166 acemask4 access_mask;
167 u_int who_length;
171 * acl_size =
172 * sizeof(ace_count) +
173 * (ace_count * (sizeof(nfsace4_size)) +
174 * length of all identifiers strings
177 acl_size = sizeof(unsigned);
179 if (naces > NFS4ACL_XDR_MAX_ACES) {
180 DBG_ERR("Too many ACEs: %u\n", naces);
181 return 0;
184 aces_size = naces * sizeof(struct nfsace4_size);
186 if (OVERFLOW_CHECK(acl_size, aces_size)) {
187 DBG_ERR("Integer Overflow error\n");
188 return 0;
190 acl_size += aces_size;
192 identifier_size = 0;
193 for (i = 0; i < naces; i++) {
194 nfsace4 *nace = nfs40acl_get_ace(nacl, i);
195 size_t string_size = nace->who.utf8string_len;
196 size_t id_size;
198 id_size = XDR_UTF8STR_ALIGN(string_size);
200 if (OVERFLOW_CHECK(identifier_size, id_size)) {
201 DBG_ERR("Integer Overflow error\n");
202 return 0;
204 identifier_size += id_size;
207 if (OVERFLOW_CHECK(acl_size, identifier_size)) {
208 DBG_ERR("Integer Overflow error\n");
209 return 0;
211 acl_size += identifier_size;
213 DBG_DEBUG("acl_size: %zd\n", acl_size);
214 return acl_size;
217 static size_t nfs41acl_get_xdrblob_size(nfsacl41 *nacl)
219 size_t acl_size;
220 size_t aces_size;
221 size_t identifier_size;
222 unsigned i;
223 unsigned naces = nfs41acl_get_naces(nacl);
225 /* ACE structure minus actual identifier strings */
226 struct nfsace4_size {
227 acetype4 type;
228 aceflag4 flag;
229 acemask4 access_mask;
230 u_int who_length;
234 * acl_size =
235 * sizeof(acl_flag) +
236 * sizeof(ace_count) +
237 * (ace_count * (sizeof(nfsace4_size)) +
238 * length of all identifiers strings
241 acl_size = 2 * sizeof(unsigned);
243 if (naces > NFS4ACL_XDR_MAX_ACES) {
244 DBG_ERR("Too many ACEs: %u\n", naces);
245 return 0;
248 aces_size = naces * sizeof(struct nfsace4_size);
250 if (OVERFLOW_CHECK(acl_size, aces_size)) {
251 DBG_ERR("Integer Overflow error\n");
252 return 0;
254 acl_size += aces_size;
256 identifier_size = 0;
257 for (i = 0; i < naces; i++) {
258 nfsace4 *nace = nfs41acl_get_ace(nacl, i);
259 size_t string_size = nace->who.utf8string_len;
260 size_t id_size;
262 id_size = XDR_UTF8STR_ALIGN(string_size);
264 if (OVERFLOW_CHECK(identifier_size, id_size)) {
265 DBG_ERR("Integer Overflow error\n");
266 return 0;
268 identifier_size += id_size;
271 if (OVERFLOW_CHECK(acl_size, identifier_size)) {
272 DBG_ERR("Integer Overflow error\n");
273 return 0;
275 acl_size += identifier_size;
277 DBG_DEBUG("acl_size: %zd\n", acl_size);
278 return acl_size;
281 static nfsacl40 *nfs40acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
283 size_t acl_size;
284 size_t aces_size;
285 nfsacl40 *nacl = NULL;
287 if (naces > NFS4ACL_XDR_MAX_ACES) {
288 DBG_ERR("Too many ACEs: %d\n", naces);
289 return NULL;
292 acl_size = sizeof(nfsacl40);
293 aces_size = (naces * sizeof(struct nfsace4));
295 if (OVERFLOW_CHECK(acl_size, aces_size)) {
296 DBG_ERR("Integer Overflow error\n");
297 return NULL;
299 acl_size += aces_size;
301 nacl = talloc_zero_size(mem_ctx, acl_size);
302 if (nacl == NULL) {
303 DBG_ERR("talloc_zero_size failed\n");
304 return NULL;
307 nfs40acl_set_naces(nacl, naces);
308 nacl->na40_aces.na40_aces_val =
309 (nfsace4 *)((uint8_t *)nacl + sizeof(nfsacl40));
311 return nacl;
314 static nfsacl41 *nfs41acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
316 size_t acl_size;
317 size_t aces_size;
318 nfsacl41 *nacl = NULL;
320 if (naces > NFS4ACL_XDR_MAX_ACES) {
321 DBG_ERR("Too many ACEs: %d\n", naces);
322 return NULL;
325 acl_size = sizeof(nfsacl41);
326 aces_size = (naces * sizeof(struct nfsace4));
328 if (OVERFLOW_CHECK(acl_size, aces_size)) {
329 DBG_ERR("Integer Overflow error\n");
330 return NULL;
332 acl_size += aces_size;
334 nacl = talloc_zero_size(mem_ctx, acl_size);
335 if (nacl == NULL) {
336 DBG_ERR("talloc_zero_size failed\n");
337 return NULL;
340 nfs41acl_set_naces(nacl, naces);
341 nacl->na41_aces.na41_aces_val =
342 (nfsace4 *)((uint8_t *)nacl + sizeof(nfsacl41));
344 return nacl;
347 static bool create_special_id(TALLOC_CTX *mem_ctx,
348 nfsace4 *nace,
349 const char *id)
351 char *s = talloc_strdup(mem_ctx, id);
353 if (s == NULL) {
354 DBG_ERR("talloc_strdup failed\n");
355 return false;
357 nace->who.utf8string_val = s;
358 nace->who.utf8string_len = talloc_get_size(s) - 1;
359 return true;
362 static bool map_smb4_to_nfs4_id(TALLOC_CTX *mem_ctx,
363 struct nfs4acl_config *config,
364 nfsace4 *nace,
365 SMB_ACE4PROP_T *sace)
367 const char *nfs4_id = NULL;
368 const char *name = NULL;
369 char *ace_name = NULL;
370 uid_t id;
371 bool ok;
373 if (sace->flags & SMB_ACE4_ID_SPECIAL) {
374 ok = map_special_smb4_to_nfs4_id(sace->who.special_id,
375 &nfs4_id);
376 if (!ok) {
377 DBG_ERR("Unsupported special id [%"PRIu32"]\n",
378 sace->who.special_id);
379 return false;
382 ok = create_special_id(mem_ctx, nace, nfs4_id);
383 if (!ok) {
384 return false;
386 DBG_DEBUG("Special id [%s]\n", nace->who.utf8string_val);
387 return true;
390 if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
391 nace->flag |= ACE4_IDENTIFIER_GROUP;
394 if (config->nfs4_id_numeric) {
395 char *strid = NULL;
397 if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
398 id = sace->who.gid;
399 } else {
400 id = sace->who.uid;
403 strid = talloc_asprintf(mem_ctx, "%jd", (intmax_t)id);
404 if (strid == NULL) {
405 DBG_ERR("talloc_asprintf failed\n");
406 return false;
408 nace->who.utf8string_val = strid;
409 nace->who.utf8string_len = talloc_get_size(strid) - 1;
410 DBG_DEBUG("Numeric id [%s]\n", nace->who.utf8string_val);
411 return true;
414 if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
415 struct group *grp = NULL;
417 grp = getgrgid(sace->who.gid);
418 if (grp == NULL) {
419 DBG_ERR("Unknown gid [%jd]\n", (intmax_t)sace->who.gid);
420 return false;
422 name = grp->gr_name;
423 } else {
424 struct passwd *pwd = NULL;
426 pwd = getpwuid(sace->who.uid);
427 if (pwd == NULL) {
428 DBG_ERR("Unknown uid [%jd]\n", (intmax_t)sace->who.uid);
429 return false;
431 name = pwd->pw_name;
434 ace_name = talloc_strdup(mem_ctx, name);
435 if (ace_name == NULL) {
436 DBG_ERR("talloc_asprintf failed\n");
437 return false;
439 nace->who.utf8string_val = ace_name;
440 nace->who.utf8string_len = talloc_get_size(ace_name) - 1;
442 DBG_DEBUG("id [%s]\n", nace->who.utf8string_val);
443 return true;
446 static bool smb4acl_to_nfs40acl(vfs_handle_struct *handle,
447 TALLOC_CTX *mem_ctx,
448 struct SMB4ACL_T *smb4acl,
449 nfsacl40 **_nacl)
451 struct nfs4acl_config *config = NULL;
452 struct SMB4ACE_T *smb4ace = NULL;
453 nfsacl40 *nacl = NULL;
454 size_t naces = smb_get_naces(smb4acl);
455 bool ok;
457 SMB_VFS_HANDLE_GET_DATA(handle, config,
458 struct nfs4acl_config,
459 return false);
461 nacl = nfs40acl_alloc(mem_ctx, naces);
462 nfs40acl_set_naces(nacl, 0);
464 smb4ace = smb_first_ace4(smb4acl);
465 while (smb4ace != NULL) {
466 SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
467 size_t nace_count = nfs40acl_get_naces(nacl);
468 nfsace4 *nace = nfs40acl_get_ace(nacl, nace_count);
470 nace->type = ace4prop->aceType;
471 nace->flag = ace4prop->aceFlags;
472 nace->access_mask = ace4prop->aceMask;
474 ok = map_smb4_to_nfs4_id(nacl, config, nace, ace4prop);
475 if (!ok) {
476 smb4ace = smb_next_ace4(smb4ace);
477 continue;
480 nace_count++;
481 nfs40acl_set_naces(nacl, nace_count);
482 smb4ace = smb_next_ace4(smb4ace);
485 *_nacl = nacl;
486 return true;
489 static bool smb4acl_to_nfs41acl(vfs_handle_struct *handle,
490 TALLOC_CTX *mem_ctx,
491 struct SMB4ACL_T *smb4acl,
492 nfsacl41 **_nacl)
494 struct nfs4acl_config *config = NULL;
495 struct SMB4ACE_T *smb4ace = NULL;
496 nfsacl41 *nacl = NULL;
497 size_t naces = smb_get_naces(smb4acl);
498 uint16_t smb4acl_flags;
499 unsigned nacl_flags;
500 bool ok;
502 SMB_VFS_HANDLE_GET_DATA(handle, config,
503 struct nfs4acl_config,
504 return false);
506 nacl = nfs41acl_alloc(mem_ctx, naces);
507 nfs41acl_set_naces(nacl, 0);
509 smb4acl_flags = smbacl4_get_controlflags(smb4acl);
510 nacl_flags = smb4acl_to_nfs4acl_flags(smb4acl_flags);
511 nfs41acl_set_flags(nacl, nacl_flags);
513 smb4ace = smb_first_ace4(smb4acl);
514 while (smb4ace != NULL) {
515 SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
516 size_t nace_count = nfs41acl_get_naces(nacl);
517 nfsace4 *nace = nfs41acl_get_ace(nacl, nace_count);
519 nace->type = ace4prop->aceType;
520 nace->flag = ace4prop->aceFlags;
521 nace->access_mask = ace4prop->aceMask;
523 ok = map_smb4_to_nfs4_id(nacl, config, nace, ace4prop);
524 if (!ok) {
525 smb4ace = smb_next_ace4(smb4ace);
526 continue;
529 nace_count++;
530 nfs41acl_set_naces(nacl, nace_count);
531 smb4ace = smb_next_ace4(smb4ace);
534 *_nacl = nacl;
535 return true;
538 NTSTATUS nfs4acl_smb4acl_to_nfs_blob(vfs_handle_struct *handle,
539 TALLOC_CTX *mem_ctx,
540 struct SMB4ACL_T *smb4acl,
541 DATA_BLOB *_blob)
543 struct nfs4acl_config *config = NULL;
544 nfsacl40 *nacl40 = NULL;
545 nfsacl41 *nacl41 = NULL;
546 XDR xdr = {0};
547 size_t aclblobsize;
548 DATA_BLOB blob;
549 bool ok;
551 SMB_VFS_HANDLE_GET_DATA(handle, config,
552 struct nfs4acl_config,
553 return NT_STATUS_INTERNAL_ERROR);
555 if (config->nfs_version == ACL4_XATTR_VERSION_40) {
556 ok = smb4acl_to_nfs40acl(handle, mem_ctx, smb4acl, &nacl40);
557 if (!ok) {
558 DBG_ERR("smb4acl_to_nfs4acl failed\n");
559 return NT_STATUS_INTERNAL_ERROR;
562 aclblobsize = nfs40acl_get_xdrblob_size(nacl40);
563 if (aclblobsize == 0) {
564 DBG_ERR("Error calculating XDR blob size\n");
565 return NT_STATUS_INTERNAL_ERROR;
567 } else {
568 ok = smb4acl_to_nfs41acl(handle, mem_ctx, smb4acl, &nacl41);
569 if (!ok) {
570 DBG_ERR("smb4acl_to_nfs4acl failed\n");
571 return NT_STATUS_INTERNAL_ERROR;
574 aclblobsize = nfs41acl_get_xdrblob_size(nacl41);
575 if (aclblobsize == 0) {
576 DBG_ERR("Error calculating XDR blob size\n");
577 return NT_STATUS_INTERNAL_ERROR;
581 blob = data_blob_talloc(mem_ctx, NULL, aclblobsize);
582 if (blob.data == NULL) {
583 TALLOC_FREE(nacl40);
584 TALLOC_FREE(nacl41);
585 return NT_STATUS_NO_MEMORY;
588 xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE);
590 if (config->nfs_version == ACL4_XATTR_VERSION_40) {
591 ok = xdr_nfsacl40(&xdr, nacl40);
592 TALLOC_FREE(nacl40);
593 if (!ok) {
594 DBG_ERR("xdr_nfs4acl40 failed\n");
595 return NT_STATUS_NO_MEMORY;
597 } else {
598 ok = xdr_nfsacl41(&xdr, nacl41);
599 TALLOC_FREE(nacl41);
600 if (!ok) {
601 DBG_ERR("xdr_nfs4acl40 failed\n");
602 return NT_STATUS_NO_MEMORY;
606 *_blob = blob;
607 return NT_STATUS_OK;
610 static NTSTATUS nfs4acl_nfs_blob_to_nfs40acl(struct vfs_handle_struct *handle,
611 TALLOC_CTX *mem_ctx,
612 DATA_BLOB *blob,
613 nfsacl40 **_nacl)
615 nfsacl40 *nacl = NULL;
616 XDR xdr = {0};
617 bool ok;
619 nacl = talloc_zero_size(mem_ctx, sizeof(nfsacl40));
620 if (nacl == NULL) {
621 DBG_ERR("talloc_zero_size failed\n");
622 return NT_STATUS_NO_MEMORY;
625 xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
627 ok = xdr_nfsacl40(&xdr, nacl);
628 if (!ok) {
629 DBG_ERR("xdr_nfsacl40 failed\n");
630 return NT_STATUS_INTERNAL_ERROR;
633 DBG_DEBUG("naces = %d \n", nacl->na40_aces.na40_aces_len);
635 *_nacl = nacl;
636 return NT_STATUS_OK;
639 static NTSTATUS nfs4acl_nfs_blob_to_nfs41acl(struct vfs_handle_struct *handle,
640 TALLOC_CTX *mem_ctx,
641 DATA_BLOB *blob,
642 nfsacl41 **_nacl)
644 nfsacl41 *nacl = NULL;
645 XDR xdr = {0};
646 bool ok;
648 nacl = talloc_zero_size(mem_ctx, sizeof(nfsacl41));
649 if (nacl == NULL) {
650 DBG_ERR("talloc_zero_size failed\n");
651 return NT_STATUS_NO_MEMORY;
654 xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
656 ok = xdr_nfsacl41(&xdr, nacl);
657 if (!ok) {
658 DBG_ERR("xdr_nfsacl40 failed\n");
659 return NT_STATUS_INTERNAL_ERROR;
662 DBG_DEBUG("naces = %d \n", nacl->na41_aces.na41_aces_len);
664 *_nacl = nacl;
665 return NT_STATUS_OK;
668 static bool map_ace_nfs4_to_smb4(struct nfs4acl_config *config,
669 const nfsace4 *nace,
670 SMB_ACE4PROP_T *sace)
672 char *name = NULL;
673 char *p = NULL;
674 uint32_t smb4_id;
675 bool ok;
677 name = talloc_strndup(talloc_tos(),
678 nace->who.utf8string_val,
679 nace->who.utf8string_len);
680 if (name == NULL) {
681 return false;
684 sace->aceType = nace->type;
685 sace->aceFlags = nace->flag;
686 sace->aceMask = nace->access_mask;
688 if (is_special_nfs4_id(name)) {
689 ok = map_special_nfs4_to_smb4_id(name, &smb4_id);
690 if (!ok) {
691 DBG_WARNING("Unknown special id [%s]\n", name);
692 return false;
694 sace->flags |= SMB_ACE4_ID_SPECIAL;
695 sace->who.special_id = smb4_id;
696 return true;
699 p = strtok(name, "@");
700 if (p == NULL && !config->nfs4_id_numeric) {
701 DBG_ERR("Unqualified name [%s]\n", name);
702 TALLOC_FREE(name);
703 return false;
707 * nametouid() and nametogid() work with both names and numbers...
710 if (nace->flag & ACE4_IDENTIFIER_GROUP) {
711 sace->who.gid = nametogid(name);
712 if (sace->who.gid == (gid_t)-1) {
713 DBG_ERR("converting id [%s] failed\n", name);
714 TALLOC_FREE(name);
715 return false;
717 TALLOC_FREE(name);
718 return true;
721 sace->who.uid = nametouid(name);
722 if (sace->who.uid == (gid_t)-1) {
723 DBG_ERR("converting id [%s] failed\n", name);
724 TALLOC_FREE(name);
725 return false;
727 TALLOC_FREE(name);
728 return true;
731 static NTSTATUS nfs40acl_to_smb4acl(struct vfs_handle_struct *handle,
732 TALLOC_CTX *mem_ctx,
733 nfsacl40 *nacl,
734 struct SMB4ACL_T **_smb4acl)
736 struct nfs4acl_config *config = NULL;
737 struct SMB4ACL_T *smb4acl = NULL;
738 unsigned naces = nfs40acl_get_naces(nacl);
739 unsigned int i;
740 bool ok;
742 SMB_VFS_HANDLE_GET_DATA(handle, config,
743 struct nfs4acl_config,
744 return NT_STATUS_INTERNAL_ERROR);
746 smb4acl = smb_create_smb4acl(mem_ctx);
747 if (smb4acl == NULL) {
748 return NT_STATUS_INTERNAL_ERROR;
751 DBG_DEBUG("nace [%u]\n", naces);
753 for (i = 0; i < naces; i++) {
754 nfsace4 *nace = nfs40acl_get_ace(nacl, i);
755 SMB_ACE4PROP_T sace = { 0 };
757 DBG_DEBUG("type [%d] flag [%x] mask [%x] who [%*s]\n",
758 nace->type, nace->flag,
759 nace->access_mask,
760 nace->who.utf8string_len,
761 nace->who.utf8string_val);
763 ok = map_ace_nfs4_to_smb4(config, nace, &sace);
764 if (!ok) {
765 continue;
768 smb_add_ace4(smb4acl, &sace);
771 *_smb4acl = smb4acl;
772 return NT_STATUS_OK;
775 static NTSTATUS nfs41acl_to_smb4acl(struct vfs_handle_struct *handle,
776 TALLOC_CTX *mem_ctx,
777 nfsacl41 *nacl,
778 struct SMB4ACL_T **_smb4acl)
780 struct nfs4acl_config *config = NULL;
781 struct SMB4ACL_T *smb4acl = NULL;
782 unsigned nfsacl41_flag = 0;
783 uint16_t smb4acl_flags = 0;
784 unsigned naces = nfs41acl_get_naces(nacl);
785 unsigned int i;
786 bool ok;
788 SMB_VFS_HANDLE_GET_DATA(handle, config,
789 struct nfs4acl_config,
790 return NT_STATUS_INTERNAL_ERROR);
792 smb4acl = smb_create_smb4acl(mem_ctx);
793 if (smb4acl == NULL) {
794 return NT_STATUS_INTERNAL_ERROR;
797 nfsacl41_flag = nfs41acl_get_flags(nacl);
798 smb4acl_flags = nfs4acl_to_smb4acl_flags(nfsacl41_flag);
799 smbacl4_set_controlflags(smb4acl, smb4acl_flags);
801 DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags, naces);
803 for (i = 0; i < naces; i++) {
804 nfsace4 *nace = nfs41acl_get_ace(nacl, i);
805 SMB_ACE4PROP_T sace = { 0 };
807 DBG_DEBUG("type [%d] flag [%x] mask [%x] who [%*s]\n",
808 nace->type, nace->flag,
809 nace->access_mask,
810 nace->who.utf8string_len,
811 nace->who.utf8string_val);
813 ok = map_ace_nfs4_to_smb4(config, nace, &sace);
814 if (!ok) {
815 continue;
818 smb_add_ace4(smb4acl, &sace);
821 *_smb4acl = smb4acl;
822 return NT_STATUS_OK;
825 NTSTATUS nfs4acl_nfs_blob_to_smb4(struct vfs_handle_struct *handle,
826 TALLOC_CTX *mem_ctx,
827 DATA_BLOB *blob,
828 struct SMB4ACL_T **_smb4acl)
830 struct nfs4acl_config *config = NULL;
831 struct SMB4ACL_T *smb4acl = NULL;
832 NTSTATUS status;
834 SMB_VFS_HANDLE_GET_DATA(handle, config,
835 struct nfs4acl_config,
836 return NT_STATUS_INTERNAL_ERROR);
838 if (config->nfs_version == ACL4_XATTR_VERSION_40) {
839 nfsacl40 *nacl = NULL;
841 status = nfs4acl_nfs_blob_to_nfs40acl(handle,
842 talloc_tos(),
843 blob,
844 &nacl);
845 if (!NT_STATUS_IS_OK(status)) {
846 return status;
849 status = nfs40acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
850 TALLOC_FREE(nacl);
851 if (!NT_STATUS_IS_OK(status)) {
852 return status;
854 } else {
855 nfsacl41 *nacl = NULL;
857 status = nfs4acl_nfs_blob_to_nfs41acl(handle,
858 talloc_tos(),
859 blob,
860 &nacl);
861 if (!NT_STATUS_IS_OK(status)) {
862 return status;
865 status = nfs41acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
866 TALLOC_FREE(nacl);
867 if (!NT_STATUS_IS_OK(status)) {
868 return status;
872 *_smb4acl = smb4acl;
873 return NT_STATUS_OK;
876 #else /* !HAVE_RPC_XDR_H */
877 #include "nfs4_acls.h"
878 #include "nfs4acl_xattr_nfs.h"
879 NTSTATUS nfs4acl_nfs_blob_to_smb4(struct vfs_handle_struct *handle,
880 TALLOC_CTX *mem_ctx,
881 DATA_BLOB *blob,
882 struct SMB4ACL_T **_smb4acl)
884 return NT_STATUS_NOT_SUPPORTED;
887 NTSTATUS nfs4acl_smb4acl_to_nfs_blob(vfs_handle_struct *handle,
888 TALLOC_CTX *mem_ctx,
889 struct SMB4ACL_T *smbacl,
890 DATA_BLOB *blob)
892 return NT_STATUS_NOT_SUPPORTED;
894 #endif /* HAVE_RPC_XDR_H */