Line data Source code
1 : /*
2 : * Copyright (C) Ralph Boehme 2018
3 : *
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.
8 : *
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.
13 : *
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/>.
16 : *
17 : */
18 :
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"
24 :
25 : #ifdef HAVE_RPC_XDR_H
26 : /* <rpc/xdr.h> uses TRUE and FALSE */
27 : #ifdef TRUE
28 : #undef TRUE
29 : #endif
30 :
31 : #ifdef FALSE
32 : #undef FALSE
33 : #endif
34 :
35 : #ifdef HAVE_RPC_TYPES_H
36 : #include <rpc/types.h>
37 : #endif
38 : #include <rpc/xdr.h>
39 :
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"
45 :
46 : #undef DBGC_CLASS
47 : #define DBGC_CLASS DBGC_VFS
48 :
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))
53 :
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},
68 : };
69 :
70 3272 : static bool is_special_nfs4_id(const char *nfs4_id)
71 : {
72 3272 : char *at = NULL;
73 :
74 3272 : at = strchr(nfs4_id, '@');
75 3272 : if (at == NULL) {
76 404 : return false;
77 : }
78 2868 : if (at[1] != '\0') {
79 0 : return false;
80 : }
81 2868 : return true;
82 : }
83 :
84 2868 : static bool map_special_nfs4_to_smb4_id(const char *nfs4_id, uint32_t *smb4_id)
85 : {
86 : size_t i;
87 : int cmp;
88 :
89 4692 : for (i = 0; i < ARRAY_SIZE(nfs4_to_smb4_id_map); i++) {
90 4692 : cmp = strcmp(nfs4_to_smb4_id_map[i].nfs4_id, nfs4_id);
91 4692 : if (cmp != 0) {
92 1824 : continue;
93 : }
94 2868 : *smb4_id = nfs4_to_smb4_id_map[i].smb4_id;
95 2868 : return true;
96 : }
97 0 : return false;
98 : }
99 :
100 1480 : static bool map_special_smb4_to_nfs4_id(uint32_t smb4_id, const char **nfs4_id)
101 : {
102 : size_t i;
103 :
104 1856 : for (i = 0; i < ARRAY_SIZE(nfs4_to_smb4_id_map); i++) {
105 1856 : if (nfs4_to_smb4_id_map[i].smb4_id != smb4_id) {
106 376 : continue;
107 : }
108 1480 : *nfs4_id = nfs4_to_smb4_id_map[i].nfs4_id;
109 1480 : return true;
110 : }
111 0 : return false;
112 : }
113 :
114 2754 : static unsigned nfs40acl_get_naces(nfsacl40 *nacl)
115 : {
116 2754 : return nacl->na40_aces.na40_aces_len;
117 : }
118 :
119 2754 : static unsigned nfs41acl_get_naces(nfsacl41 *nacl)
120 : {
121 2754 : return nacl->na41_aces.na41_aces_len;
122 : }
123 :
124 2216 : static void nfs40acl_set_naces(nfsacl40 *nacl, unsigned naces)
125 : {
126 2216 : nacl->na40_aces.na40_aces_len = naces;
127 2216 : }
128 :
129 2216 : static void nfs41acl_set_naces(nfsacl41 *nacl, unsigned naces)
130 : {
131 2216 : nacl->na41_aces.na41_aces_len = naces;
132 2216 : }
133 :
134 1252 : static unsigned nfs41acl_get_flags(nfsacl41 *nacl)
135 : {
136 1252 : return nacl->na41_flag;
137 : }
138 :
139 714 : static void nfs41acl_set_flags(nfsacl41 *nacl, unsigned flags)
140 : {
141 714 : nacl->na41_flag = flags;
142 714 : }
143 :
144 3212 : static nfsace4 *nfs40acl_get_ace(nfsacl40 *nacl, size_t n)
145 : {
146 3212 : return &nacl->na40_aces.na40_aces_val[n];
147 : }
148 :
149 3212 : static nfsace4 *nfs41acl_get_ace(nfsacl41 *nacl, size_t n)
150 : {
151 3212 : return &nacl->na41_aces.na41_aces_val[n];
152 : }
153 :
154 714 : static size_t nfs40acl_get_xdrblob_size(nfsacl40 *nacl)
155 : {
156 : size_t acl_size;
157 : size_t aces_size;
158 : size_t identifier_size;
159 : unsigned i;
160 714 : unsigned naces = nfs40acl_get_naces(nacl);
161 :
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;
168 : };
169 :
170 : /*
171 : * acl_size =
172 : * sizeof(ace_count) +
173 : * (ace_count * (sizeof(nfsace4_size)) +
174 : * length of all identifiers strings
175 : */
176 :
177 714 : acl_size = sizeof(unsigned);
178 :
179 714 : if (naces > NFS4ACL_XDR_MAX_ACES) {
180 0 : DBG_ERR("Too many ACEs: %u\n", naces);
181 0 : return 0;
182 : }
183 :
184 714 : aces_size = naces * sizeof(struct nfsace4_size);
185 :
186 714 : if (OVERFLOW_CHECK(acl_size, aces_size)) {
187 0 : DBG_ERR("Integer Overflow error\n");
188 0 : return 0;
189 : }
190 714 : acl_size += aces_size;
191 :
192 714 : identifier_size = 0;
193 1502 : for (i = 0; i < naces; i++) {
194 788 : nfsace4 *nace = nfs40acl_get_ace(nacl, i);
195 788 : size_t string_size = nace->who.utf8string_len;
196 : size_t id_size;
197 :
198 788 : id_size = XDR_UTF8STR_ALIGN(string_size);
199 :
200 788 : if (OVERFLOW_CHECK(identifier_size, id_size)) {
201 0 : DBG_ERR("Integer Overflow error\n");
202 0 : return 0;
203 : }
204 788 : identifier_size += id_size;
205 : }
206 :
207 714 : if (OVERFLOW_CHECK(acl_size, identifier_size)) {
208 0 : DBG_ERR("Integer Overflow error\n");
209 0 : return 0;
210 : }
211 714 : acl_size += identifier_size;
212 :
213 714 : DBG_DEBUG("acl_size: %zd\n", acl_size);
214 714 : return acl_size;
215 : }
216 :
217 714 : static size_t nfs41acl_get_xdrblob_size(nfsacl41 *nacl)
218 : {
219 : size_t acl_size;
220 : size_t aces_size;
221 : size_t identifier_size;
222 : unsigned i;
223 714 : unsigned naces = nfs41acl_get_naces(nacl);
224 :
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;
231 : };
232 :
233 : /*
234 : * acl_size =
235 : * sizeof(acl_flag) +
236 : * sizeof(ace_count) +
237 : * (ace_count * (sizeof(nfsace4_size)) +
238 : * length of all identifiers strings
239 : */
240 :
241 714 : acl_size = 2 * sizeof(unsigned);
242 :
243 714 : if (naces > NFS4ACL_XDR_MAX_ACES) {
244 0 : DBG_ERR("Too many ACEs: %u\n", naces);
245 0 : return 0;
246 : }
247 :
248 714 : aces_size = naces * sizeof(struct nfsace4_size);
249 :
250 714 : if (OVERFLOW_CHECK(acl_size, aces_size)) {
251 0 : DBG_ERR("Integer Overflow error\n");
252 0 : return 0;
253 : }
254 714 : acl_size += aces_size;
255 :
256 714 : identifier_size = 0;
257 1502 : for (i = 0; i < naces; i++) {
258 788 : nfsace4 *nace = nfs41acl_get_ace(nacl, i);
259 788 : size_t string_size = nace->who.utf8string_len;
260 : size_t id_size;
261 :
262 788 : id_size = XDR_UTF8STR_ALIGN(string_size);
263 :
264 788 : if (OVERFLOW_CHECK(identifier_size, id_size)) {
265 0 : DBG_ERR("Integer Overflow error\n");
266 0 : return 0;
267 : }
268 788 : identifier_size += id_size;
269 : }
270 :
271 714 : if (OVERFLOW_CHECK(acl_size, identifier_size)) {
272 0 : DBG_ERR("Integer Overflow error\n");
273 0 : return 0;
274 : }
275 714 : acl_size += identifier_size;
276 :
277 714 : DBG_DEBUG("acl_size: %zd\n", acl_size);
278 714 : return acl_size;
279 : }
280 :
281 714 : static nfsacl40 *nfs40acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
282 : {
283 : size_t acl_size;
284 : size_t aces_size;
285 714 : nfsacl40 *nacl = NULL;
286 :
287 714 : if (naces > NFS4ACL_XDR_MAX_ACES) {
288 0 : DBG_ERR("Too many ACEs: %d\n", naces);
289 0 : return NULL;
290 : }
291 :
292 714 : acl_size = sizeof(nfsacl40);
293 714 : aces_size = (naces * sizeof(struct nfsace4));
294 :
295 714 : if (OVERFLOW_CHECK(acl_size, aces_size)) {
296 0 : DBG_ERR("Integer Overflow error\n");
297 0 : return NULL;
298 : }
299 714 : acl_size += aces_size;
300 :
301 714 : nacl = talloc_zero_size(mem_ctx, acl_size);
302 714 : if (nacl == NULL) {
303 0 : DBG_ERR("talloc_zero_size failed\n");
304 0 : return NULL;
305 : }
306 :
307 714 : nfs40acl_set_naces(nacl, naces);
308 714 : nacl->na40_aces.na40_aces_val =
309 714 : (nfsace4 *)((uint8_t *)nacl + sizeof(nfsacl40));
310 :
311 714 : return nacl;
312 : }
313 :
314 714 : static nfsacl41 *nfs41acl_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
315 : {
316 : size_t acl_size;
317 : size_t aces_size;
318 714 : nfsacl41 *nacl = NULL;
319 :
320 714 : if (naces > NFS4ACL_XDR_MAX_ACES) {
321 0 : DBG_ERR("Too many ACEs: %d\n", naces);
322 0 : return NULL;
323 : }
324 :
325 714 : acl_size = sizeof(nfsacl41);
326 714 : aces_size = (naces * sizeof(struct nfsace4));
327 :
328 714 : if (OVERFLOW_CHECK(acl_size, aces_size)) {
329 0 : DBG_ERR("Integer Overflow error\n");
330 0 : return NULL;
331 : }
332 714 : acl_size += aces_size;
333 :
334 714 : nacl = talloc_zero_size(mem_ctx, acl_size);
335 714 : if (nacl == NULL) {
336 0 : DBG_ERR("talloc_zero_size failed\n");
337 0 : return NULL;
338 : }
339 :
340 714 : nfs41acl_set_naces(nacl, naces);
341 714 : nacl->na41_aces.na41_aces_val =
342 714 : (nfsace4 *)((uint8_t *)nacl + sizeof(nfsacl41));
343 :
344 714 : return nacl;
345 : }
346 :
347 1480 : static bool create_special_id(TALLOC_CTX *mem_ctx,
348 : nfsace4 *nace,
349 : const char *id)
350 : {
351 1480 : char *s = talloc_strdup(mem_ctx, id);
352 :
353 1480 : if (s == NULL) {
354 0 : DBG_ERR("talloc_strdup failed\n");
355 0 : return false;
356 : }
357 1480 : nace->who.utf8string_val = s;
358 1480 : nace->who.utf8string_len = talloc_get_size(s) - 1;
359 1480 : return true;
360 : }
361 :
362 1576 : static bool map_smb4_to_nfs4_id(TALLOC_CTX *mem_ctx,
363 : struct nfs4acl_config *config,
364 : nfsace4 *nace,
365 : SMB_ACE4PROP_T *sace)
366 : {
367 1576 : const char *nfs4_id = NULL;
368 1576 : const char *name = NULL;
369 1576 : char *ace_name = NULL;
370 : uid_t id;
371 : bool ok;
372 :
373 1576 : if (sace->flags & SMB_ACE4_ID_SPECIAL) {
374 1480 : ok = map_special_smb4_to_nfs4_id(sace->who.special_id,
375 : &nfs4_id);
376 1480 : if (!ok) {
377 0 : DBG_ERR("Unsupported special id [%"PRIu32"]\n",
378 : sace->who.special_id);
379 0 : return false;
380 : }
381 :
382 1480 : ok = create_special_id(mem_ctx, nace, nfs4_id);
383 1480 : if (!ok) {
384 0 : return false;
385 : }
386 1480 : DBG_DEBUG("Special id [%s]\n", nace->who.utf8string_val);
387 1480 : return true;
388 : }
389 :
390 96 : if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
391 20 : nace->flag |= ACE4_IDENTIFIER_GROUP;
392 : }
393 :
394 96 : if (config->nfs4_id_numeric) {
395 0 : char *strid = NULL;
396 :
397 0 : if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
398 0 : id = sace->who.gid;
399 : } else {
400 0 : id = sace->who.uid;
401 : }
402 :
403 0 : strid = talloc_asprintf(mem_ctx, "%jd", (intmax_t)id);
404 0 : if (strid == NULL) {
405 0 : DBG_ERR("talloc_asprintf failed\n");
406 0 : return false;
407 : }
408 0 : nace->who.utf8string_val = strid;
409 0 : nace->who.utf8string_len = talloc_get_size(strid) - 1;
410 0 : DBG_DEBUG("Numeric id [%s]\n", nace->who.utf8string_val);
411 0 : return true;
412 : }
413 :
414 96 : if (sace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
415 20 : struct group *grp = NULL;
416 :
417 20 : grp = getgrgid(sace->who.gid);
418 20 : if (grp == NULL) {
419 0 : DBG_ERR("Unknown gid [%jd]\n", (intmax_t)sace->who.gid);
420 0 : return false;
421 : }
422 20 : name = grp->gr_name;
423 : } else {
424 76 : struct passwd *pwd = NULL;
425 :
426 76 : pwd = getpwuid(sace->who.uid);
427 76 : if (pwd == NULL) {
428 0 : DBG_ERR("Unknown uid [%jd]\n", (intmax_t)sace->who.uid);
429 0 : return false;
430 : }
431 76 : name = pwd->pw_name;
432 : }
433 :
434 96 : ace_name = talloc_strdup(mem_ctx, name);
435 96 : if (ace_name == NULL) {
436 0 : DBG_ERR("talloc_asprintf failed\n");
437 0 : return false;
438 : }
439 96 : nace->who.utf8string_val = ace_name;
440 96 : nace->who.utf8string_len = talloc_get_size(ace_name) - 1;
441 :
442 96 : DBG_DEBUG("id [%s]\n", nace->who.utf8string_val);
443 96 : return true;
444 : }
445 :
446 714 : static bool smb4acl_to_nfs40acl(vfs_handle_struct *handle,
447 : TALLOC_CTX *mem_ctx,
448 : struct SMB4ACL_T *smb4acl,
449 : nfsacl40 **_nacl)
450 : {
451 714 : struct nfs4acl_config *config = NULL;
452 714 : struct SMB4ACE_T *smb4ace = NULL;
453 714 : nfsacl40 *nacl = NULL;
454 714 : size_t naces = smb_get_naces(smb4acl);
455 : bool ok;
456 :
457 714 : SMB_VFS_HANDLE_GET_DATA(handle, config,
458 : struct nfs4acl_config,
459 : return false);
460 :
461 714 : nacl = nfs40acl_alloc(mem_ctx, naces);
462 714 : nfs40acl_set_naces(nacl, 0);
463 :
464 714 : smb4ace = smb_first_ace4(smb4acl);
465 1502 : while (smb4ace != NULL) {
466 788 : SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
467 788 : size_t nace_count = nfs40acl_get_naces(nacl);
468 788 : nfsace4 *nace = nfs40acl_get_ace(nacl, nace_count);
469 :
470 788 : nace->type = ace4prop->aceType;
471 788 : nace->flag = ace4prop->aceFlags;
472 788 : nace->access_mask = ace4prop->aceMask;
473 :
474 788 : ok = map_smb4_to_nfs4_id(nacl, config, nace, ace4prop);
475 788 : if (!ok) {
476 0 : smb4ace = smb_next_ace4(smb4ace);
477 0 : continue;
478 : }
479 :
480 788 : nace_count++;
481 788 : nfs40acl_set_naces(nacl, nace_count);
482 788 : smb4ace = smb_next_ace4(smb4ace);
483 : }
484 :
485 714 : *_nacl = nacl;
486 714 : return true;
487 : }
488 :
489 714 : static bool smb4acl_to_nfs41acl(vfs_handle_struct *handle,
490 : TALLOC_CTX *mem_ctx,
491 : struct SMB4ACL_T *smb4acl,
492 : nfsacl41 **_nacl)
493 : {
494 714 : struct nfs4acl_config *config = NULL;
495 714 : struct SMB4ACE_T *smb4ace = NULL;
496 714 : nfsacl41 *nacl = NULL;
497 714 : size_t naces = smb_get_naces(smb4acl);
498 : uint16_t smb4acl_flags;
499 : unsigned nacl_flags;
500 : bool ok;
501 :
502 714 : SMB_VFS_HANDLE_GET_DATA(handle, config,
503 : struct nfs4acl_config,
504 : return false);
505 :
506 714 : nacl = nfs41acl_alloc(mem_ctx, naces);
507 714 : nfs41acl_set_naces(nacl, 0);
508 :
509 714 : smb4acl_flags = smbacl4_get_controlflags(smb4acl);
510 714 : nacl_flags = smb4acl_to_nfs4acl_flags(smb4acl_flags);
511 714 : nfs41acl_set_flags(nacl, nacl_flags);
512 :
513 714 : smb4ace = smb_first_ace4(smb4acl);
514 1502 : while (smb4ace != NULL) {
515 788 : SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
516 788 : size_t nace_count = nfs41acl_get_naces(nacl);
517 788 : nfsace4 *nace = nfs41acl_get_ace(nacl, nace_count);
518 :
519 788 : nace->type = ace4prop->aceType;
520 788 : nace->flag = ace4prop->aceFlags;
521 788 : nace->access_mask = ace4prop->aceMask;
522 :
523 788 : ok = map_smb4_to_nfs4_id(nacl, config, nace, ace4prop);
524 788 : if (!ok) {
525 0 : smb4ace = smb_next_ace4(smb4ace);
526 0 : continue;
527 : }
528 :
529 788 : nace_count++;
530 788 : nfs41acl_set_naces(nacl, nace_count);
531 788 : smb4ace = smb_next_ace4(smb4ace);
532 : }
533 :
534 714 : *_nacl = nacl;
535 714 : return true;
536 : }
537 :
538 1428 : NTSTATUS nfs4acl_smb4acl_to_nfs_blob(vfs_handle_struct *handle,
539 : TALLOC_CTX *mem_ctx,
540 : struct SMB4ACL_T *smb4acl,
541 : DATA_BLOB *_blob)
542 : {
543 1428 : struct nfs4acl_config *config = NULL;
544 1428 : nfsacl40 *nacl40 = NULL;
545 1428 : nfsacl41 *nacl41 = NULL;
546 1428 : XDR xdr = {0};
547 : size_t aclblobsize;
548 : DATA_BLOB blob;
549 : bool ok;
550 :
551 1428 : SMB_VFS_HANDLE_GET_DATA(handle, config,
552 : struct nfs4acl_config,
553 : return NT_STATUS_INTERNAL_ERROR);
554 :
555 1428 : if (config->nfs_version == ACL4_XATTR_VERSION_40) {
556 714 : ok = smb4acl_to_nfs40acl(handle, mem_ctx, smb4acl, &nacl40);
557 714 : if (!ok) {
558 0 : DBG_ERR("smb4acl_to_nfs4acl failed\n");
559 0 : return NT_STATUS_INTERNAL_ERROR;
560 : }
561 :
562 714 : aclblobsize = nfs40acl_get_xdrblob_size(nacl40);
563 714 : if (aclblobsize == 0) {
564 0 : DBG_ERR("Error calculating XDR blob size\n");
565 0 : return NT_STATUS_INTERNAL_ERROR;
566 : }
567 : } else {
568 714 : ok = smb4acl_to_nfs41acl(handle, mem_ctx, smb4acl, &nacl41);
569 714 : if (!ok) {
570 0 : DBG_ERR("smb4acl_to_nfs4acl failed\n");
571 0 : return NT_STATUS_INTERNAL_ERROR;
572 : }
573 :
574 714 : aclblobsize = nfs41acl_get_xdrblob_size(nacl41);
575 714 : if (aclblobsize == 0) {
576 0 : DBG_ERR("Error calculating XDR blob size\n");
577 0 : return NT_STATUS_INTERNAL_ERROR;
578 : }
579 : }
580 :
581 1428 : blob = data_blob_talloc(mem_ctx, NULL, aclblobsize);
582 1428 : if (blob.data == NULL) {
583 0 : TALLOC_FREE(nacl40);
584 0 : TALLOC_FREE(nacl41);
585 0 : return NT_STATUS_NO_MEMORY;
586 : }
587 :
588 1428 : xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE);
589 :
590 1428 : if (config->nfs_version == ACL4_XATTR_VERSION_40) {
591 714 : ok = xdr_nfsacl40(&xdr, nacl40);
592 714 : TALLOC_FREE(nacl40);
593 714 : if (!ok) {
594 0 : DBG_ERR("xdr_nfs4acl40 failed\n");
595 0 : return NT_STATUS_NO_MEMORY;
596 : }
597 : } else {
598 714 : ok = xdr_nfsacl41(&xdr, nacl41);
599 714 : TALLOC_FREE(nacl41);
600 714 : if (!ok) {
601 0 : DBG_ERR("xdr_nfs4acl40 failed\n");
602 0 : return NT_STATUS_NO_MEMORY;
603 : }
604 : }
605 :
606 1428 : *_blob = blob;
607 1428 : return NT_STATUS_OK;
608 : }
609 :
610 1252 : static NTSTATUS nfs4acl_nfs_blob_to_nfs40acl(struct vfs_handle_struct *handle,
611 : TALLOC_CTX *mem_ctx,
612 : DATA_BLOB *blob,
613 : nfsacl40 **_nacl)
614 : {
615 1252 : nfsacl40 *nacl = NULL;
616 1252 : XDR xdr = {0};
617 : bool ok;
618 :
619 1252 : nacl = talloc_zero_size(mem_ctx, sizeof(nfsacl40));
620 1252 : if (nacl == NULL) {
621 0 : DBG_ERR("talloc_zero_size failed\n");
622 0 : return NT_STATUS_NO_MEMORY;
623 : }
624 :
625 1252 : xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
626 :
627 1252 : ok = xdr_nfsacl40(&xdr, nacl);
628 1252 : if (!ok) {
629 0 : DBG_ERR("xdr_nfsacl40 failed\n");
630 0 : return NT_STATUS_INTERNAL_ERROR;
631 : }
632 :
633 1252 : DBG_DEBUG("naces = %d \n", nacl->na40_aces.na40_aces_len);
634 :
635 1252 : *_nacl = nacl;
636 1252 : return NT_STATUS_OK;
637 : }
638 :
639 1252 : static NTSTATUS nfs4acl_nfs_blob_to_nfs41acl(struct vfs_handle_struct *handle,
640 : TALLOC_CTX *mem_ctx,
641 : DATA_BLOB *blob,
642 : nfsacl41 **_nacl)
643 : {
644 1252 : nfsacl41 *nacl = NULL;
645 1252 : XDR xdr = {0};
646 : bool ok;
647 :
648 1252 : nacl = talloc_zero_size(mem_ctx, sizeof(nfsacl41));
649 1252 : if (nacl == NULL) {
650 0 : DBG_ERR("talloc_zero_size failed\n");
651 0 : return NT_STATUS_NO_MEMORY;
652 : }
653 :
654 1252 : xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
655 :
656 1252 : ok = xdr_nfsacl41(&xdr, nacl);
657 1252 : if (!ok) {
658 0 : DBG_ERR("xdr_nfsacl40 failed\n");
659 0 : return NT_STATUS_INTERNAL_ERROR;
660 : }
661 :
662 1252 : DBG_DEBUG("naces = %d \n", nacl->na41_aces.na41_aces_len);
663 :
664 1252 : *_nacl = nacl;
665 1252 : return NT_STATUS_OK;
666 : }
667 :
668 3272 : static bool map_ace_nfs4_to_smb4(struct nfs4acl_config *config,
669 : const nfsace4 *nace,
670 : SMB_ACE4PROP_T *sace)
671 : {
672 3272 : char *name = NULL;
673 3272 : char *p = NULL;
674 : uint32_t smb4_id;
675 : bool ok;
676 :
677 3272 : name = talloc_strndup(talloc_tos(),
678 3272 : nace->who.utf8string_val,
679 3272 : nace->who.utf8string_len);
680 3272 : if (name == NULL) {
681 0 : return false;
682 : }
683 :
684 3272 : sace->aceType = nace->type;
685 3272 : sace->aceFlags = nace->flag;
686 3272 : sace->aceMask = nace->access_mask;
687 :
688 3272 : if (is_special_nfs4_id(name)) {
689 2868 : ok = map_special_nfs4_to_smb4_id(name, &smb4_id);
690 2868 : if (!ok) {
691 0 : DBG_WARNING("Unknown special id [%s]\n", name);
692 0 : return false;
693 : }
694 2868 : sace->flags |= SMB_ACE4_ID_SPECIAL;
695 2868 : sace->who.special_id = smb4_id;
696 2868 : return true;
697 : }
698 :
699 404 : p = strtok(name, "@");
700 404 : if (p == NULL && !config->nfs4_id_numeric) {
701 0 : DBG_ERR("Unqualified name [%s]\n", name);
702 0 : TALLOC_FREE(name);
703 0 : return false;
704 : }
705 :
706 : /*
707 : * nametouid() and nametogid() work with both names and numbers...
708 : */
709 :
710 404 : if (nace->flag & ACE4_IDENTIFIER_GROUP) {
711 36 : sace->who.gid = nametogid(name);
712 36 : if (sace->who.gid == (gid_t)-1) {
713 0 : DBG_ERR("converting id [%s] failed\n", name);
714 0 : TALLOC_FREE(name);
715 0 : return false;
716 : }
717 36 : TALLOC_FREE(name);
718 36 : return true;
719 : }
720 :
721 368 : sace->who.uid = nametouid(name);
722 368 : if (sace->who.uid == (gid_t)-1) {
723 0 : DBG_ERR("converting id [%s] failed\n", name);
724 0 : TALLOC_FREE(name);
725 0 : return false;
726 : }
727 368 : TALLOC_FREE(name);
728 368 : return true;
729 : }
730 :
731 1252 : static NTSTATUS nfs40acl_to_smb4acl(struct vfs_handle_struct *handle,
732 : TALLOC_CTX *mem_ctx,
733 : nfsacl40 *nacl,
734 : struct SMB4ACL_T **_smb4acl)
735 : {
736 1252 : struct nfs4acl_config *config = NULL;
737 1252 : struct SMB4ACL_T *smb4acl = NULL;
738 1252 : unsigned naces = nfs40acl_get_naces(nacl);
739 : unsigned int i;
740 : bool ok;
741 :
742 1252 : SMB_VFS_HANDLE_GET_DATA(handle, config,
743 : struct nfs4acl_config,
744 : return NT_STATUS_INTERNAL_ERROR);
745 :
746 1252 : smb4acl = smb_create_smb4acl(mem_ctx);
747 1252 : if (smb4acl == NULL) {
748 0 : return NT_STATUS_INTERNAL_ERROR;
749 : }
750 :
751 1252 : DBG_DEBUG("nace [%u]\n", naces);
752 :
753 2888 : for (i = 0; i < naces; i++) {
754 1636 : nfsace4 *nace = nfs40acl_get_ace(nacl, i);
755 1636 : SMB_ACE4PROP_T sace = { 0 };
756 :
757 1636 : 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);
762 :
763 1636 : ok = map_ace_nfs4_to_smb4(config, nace, &sace);
764 1636 : if (!ok) {
765 0 : continue;
766 : }
767 :
768 1636 : smb_add_ace4(smb4acl, &sace);
769 : }
770 :
771 1252 : *_smb4acl = smb4acl;
772 1252 : return NT_STATUS_OK;
773 : }
774 :
775 1252 : static NTSTATUS nfs41acl_to_smb4acl(struct vfs_handle_struct *handle,
776 : TALLOC_CTX *mem_ctx,
777 : nfsacl41 *nacl,
778 : struct SMB4ACL_T **_smb4acl)
779 : {
780 1252 : struct nfs4acl_config *config = NULL;
781 1252 : struct SMB4ACL_T *smb4acl = NULL;
782 1252 : unsigned nfsacl41_flag = 0;
783 1252 : uint16_t smb4acl_flags = 0;
784 1252 : unsigned naces = nfs41acl_get_naces(nacl);
785 : unsigned int i;
786 : bool ok;
787 :
788 1252 : SMB_VFS_HANDLE_GET_DATA(handle, config,
789 : struct nfs4acl_config,
790 : return NT_STATUS_INTERNAL_ERROR);
791 :
792 1252 : smb4acl = smb_create_smb4acl(mem_ctx);
793 1252 : if (smb4acl == NULL) {
794 0 : return NT_STATUS_INTERNAL_ERROR;
795 : }
796 :
797 1252 : nfsacl41_flag = nfs41acl_get_flags(nacl);
798 1252 : smb4acl_flags = nfs4acl_to_smb4acl_flags(nfsacl41_flag);
799 1252 : smbacl4_set_controlflags(smb4acl, smb4acl_flags);
800 :
801 1252 : DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags, naces);
802 :
803 2888 : for (i = 0; i < naces; i++) {
804 1636 : nfsace4 *nace = nfs41acl_get_ace(nacl, i);
805 1636 : SMB_ACE4PROP_T sace = { 0 };
806 :
807 1636 : 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);
812 :
813 1636 : ok = map_ace_nfs4_to_smb4(config, nace, &sace);
814 1636 : if (!ok) {
815 0 : continue;
816 : }
817 :
818 1636 : smb_add_ace4(smb4acl, &sace);
819 : }
820 :
821 1252 : *_smb4acl = smb4acl;
822 1252 : return NT_STATUS_OK;
823 : }
824 :
825 2504 : 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)
829 : {
830 2504 : struct nfs4acl_config *config = NULL;
831 2504 : struct SMB4ACL_T *smb4acl = NULL;
832 : NTSTATUS status;
833 :
834 2504 : SMB_VFS_HANDLE_GET_DATA(handle, config,
835 : struct nfs4acl_config,
836 : return NT_STATUS_INTERNAL_ERROR);
837 :
838 2504 : if (config->nfs_version == ACL4_XATTR_VERSION_40) {
839 1252 : nfsacl40 *nacl = NULL;
840 :
841 1252 : status = nfs4acl_nfs_blob_to_nfs40acl(handle,
842 : talloc_tos(),
843 : blob,
844 : &nacl);
845 1252 : if (!NT_STATUS_IS_OK(status)) {
846 0 : return status;
847 : }
848 :
849 1252 : status = nfs40acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
850 1252 : TALLOC_FREE(nacl);
851 1252 : if (!NT_STATUS_IS_OK(status)) {
852 0 : return status;
853 : }
854 : } else {
855 1252 : nfsacl41 *nacl = NULL;
856 :
857 1252 : status = nfs4acl_nfs_blob_to_nfs41acl(handle,
858 : talloc_tos(),
859 : blob,
860 : &nacl);
861 1252 : if (!NT_STATUS_IS_OK(status)) {
862 0 : return status;
863 : }
864 :
865 1252 : status = nfs41acl_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
866 1252 : TALLOC_FREE(nacl);
867 1252 : if (!NT_STATUS_IS_OK(status)) {
868 0 : return status;
869 : }
870 : }
871 :
872 2504 : *_smb4acl = smb4acl;
873 2504 : return NT_STATUS_OK;
874 : }
875 :
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)
883 : {
884 : return NT_STATUS_NOT_SUPPORTED;
885 : }
886 :
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)
891 : {
892 : return NT_STATUS_NOT_SUPPORTED;
893 : }
894 : #endif /* HAVE_RPC_XDR_H */
|