Line data Source code
1 : /*
2 : * NFS4 ACL handling
3 : *
4 : * Copyright (C) Jim McDonough, 2006
5 : * Copyright (C) Christof Schmitt 2019
6 : *
7 : * This program is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * This program is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "smbd/smbd.h"
23 : #include "nfs4_acls.h"
24 : #include "librpc/gen_ndr/ndr_security.h"
25 : #include "librpc/gen_ndr/idmap.h"
26 : #include "../libcli/security/dom_sid.h"
27 : #include "../libcli/security/security.h"
28 : #include "dbwrap/dbwrap.h"
29 : #include "dbwrap/dbwrap_open.h"
30 : #include "system/filesys.h"
31 : #include "passdb/lookup_sid.h"
32 : #include "util_tdb.h"
33 : #include "lib/param/loadparm.h"
34 :
35 : #undef DBGC_CLASS
36 : #define DBGC_CLASS DBGC_ACLS
37 :
38 : #define SMBACL4_PARAM_TYPE_NAME "nfs4"
39 :
40 : extern const struct generic_mapping file_generic_mapping;
41 :
42 : struct SMB4ACE_T
43 : {
44 : SMB_ACE4PROP_T prop;
45 : struct SMB4ACE_T *next;
46 : };
47 :
48 : struct SMB4ACL_T
49 : {
50 : uint16_t controlflags;
51 : uint32_t naces;
52 : struct SMB4ACE_T *first;
53 : struct SMB4ACE_T *last;
54 : };
55 :
56 : /*
57 : * Gather special parameters for NFS4 ACL handling
58 : */
59 8976 : int smbacl4_get_vfs_params(struct connection_struct *conn,
60 : struct smbacl4_vfs_params *params)
61 : {
62 0 : static const struct enum_list enum_smbacl4_modes[] = {
63 : { e_simple, "simple" },
64 : { e_special, "special" },
65 : { -1 , NULL }
66 : };
67 0 : static const struct enum_list enum_smbacl4_acedups[] = {
68 : { e_dontcare, "dontcare" },
69 : { e_reject, "reject" },
70 : { e_ignore, "ignore" },
71 : { e_merge, "merge" },
72 : { -1 , NULL }
73 : };
74 0 : int enumval;
75 :
76 8976 : *params = (struct smbacl4_vfs_params) { 0 };
77 :
78 8976 : enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "mode",
79 : enum_smbacl4_modes, e_simple);
80 8976 : if (enumval == -1) {
81 0 : DEBUG(10, ("value for %s:mode unknown\n",
82 : SMBACL4_PARAM_TYPE_NAME));
83 0 : return -1;
84 : }
85 8976 : params->mode = (enum smbacl4_mode_enum)enumval;
86 8976 : if (params->mode == e_special) {
87 1282 : DBG_WARNING("nfs4:mode special is deprecated.\n");
88 : }
89 :
90 8976 : params->do_chown = lp_parm_bool(SNUM(conn), SMBACL4_PARAM_TYPE_NAME,
91 : "chown", true);
92 :
93 8976 : enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "acedup",
94 : enum_smbacl4_acedups, e_merge);
95 8976 : if (enumval == -1) {
96 0 : DEBUG(10, ("value for %s:acedup unknown\n",
97 : SMBACL4_PARAM_TYPE_NAME));
98 0 : return -1;
99 : }
100 8976 : params->acedup = (enum smbacl4_acedup_enum)enumval;
101 8976 : if (params->acedup == e_ignore) {
102 0 : DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
103 : }
104 8976 : if (params->acedup == e_reject) {
105 0 : DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
106 : }
107 :
108 8976 : params->map_full_control = lp_acl_map_full_control(SNUM(conn));
109 :
110 8976 : DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s map full control:%s\n",
111 : enum_smbacl4_modes[params->mode].name,
112 : params->do_chown ? "true" : "false",
113 : enum_smbacl4_acedups[params->acedup].name,
114 : params->map_full_control ? "true" : "false"));
115 :
116 8976 : return 0;
117 : }
118 :
119 0 : static int fstatat_with_cap_dac_override(int fd,
120 : const char *pathname,
121 : SMB_STRUCT_STAT *sbuf,
122 : int flags,
123 : bool fake_dir_create_times)
124 : {
125 0 : int ret;
126 :
127 0 : set_effective_capability(DAC_OVERRIDE_CAPABILITY);
128 0 : ret = sys_fstatat(fd,
129 : pathname,
130 : sbuf,
131 : flags,
132 : fake_dir_create_times);
133 0 : drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
134 :
135 0 : return ret;
136 : }
137 :
138 0 : static int stat_with_cap_dac_override(struct vfs_handle_struct *handle,
139 : struct smb_filename *smb_fname, int flag)
140 : {
141 0 : bool fake_dctime = lp_fake_directory_create_times(SNUM(handle->conn));
142 0 : int fd = -1;
143 0 : NTSTATUS status;
144 0 : struct smb_filename *dir_name = NULL;
145 0 : struct smb_filename *rel_name = NULL;
146 0 : int ret = -1;
147 : #ifdef O_PATH
148 0 : int open_flags = O_PATH;
149 : #else
150 0 : int open_flags = O_RDONLY;
151 : #endif
152 :
153 0 : status = SMB_VFS_PARENT_PATHNAME(handle->conn,
154 : talloc_tos(),
155 : smb_fname,
156 : &dir_name,
157 : &rel_name);
158 0 : if (!NT_STATUS_IS_OK(status)) {
159 0 : errno = map_errno_from_nt_status(status);
160 0 : return -1;
161 : }
162 :
163 0 : fd = open(dir_name->base_name, open_flags, 0);
164 0 : if (fd == -1) {
165 0 : TALLOC_FREE(dir_name);
166 0 : return -1;
167 : }
168 :
169 0 : ret = fstatat_with_cap_dac_override(fd,
170 0 : rel_name->base_name,
171 : &smb_fname->st,
172 : flag,
173 : fake_dctime);
174 :
175 0 : TALLOC_FREE(dir_name);
176 0 : close(fd);
177 :
178 0 : return ret;
179 : }
180 :
181 0 : int nfs4_acl_stat(struct vfs_handle_struct *handle,
182 : struct smb_filename *smb_fname)
183 : {
184 0 : int ret;
185 :
186 0 : ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
187 0 : if (ret == -1 && errno == EACCES) {
188 0 : DEBUG(10, ("Trying stat with capability for %s\n",
189 : smb_fname->base_name));
190 0 : ret = stat_with_cap_dac_override(handle, smb_fname, 0);
191 : }
192 0 : return ret;
193 : }
194 :
195 0 : static int fstat_with_cap_dac_override(int fd, SMB_STRUCT_STAT *sbuf,
196 : bool fake_dir_create_times)
197 : {
198 0 : int ret;
199 :
200 0 : set_effective_capability(DAC_OVERRIDE_CAPABILITY);
201 0 : ret = sys_fstat(fd, sbuf, fake_dir_create_times);
202 0 : drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
203 :
204 0 : return ret;
205 : }
206 :
207 0 : int nfs4_acl_fstat(struct vfs_handle_struct *handle,
208 : struct files_struct *fsp,
209 : SMB_STRUCT_STAT *sbuf)
210 : {
211 0 : int ret;
212 :
213 0 : ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
214 0 : if (ret == -1 && errno == EACCES) {
215 0 : bool fake_dctime =
216 0 : lp_fake_directory_create_times(SNUM(handle->conn));
217 :
218 0 : DBG_DEBUG("fstat for %s failed with EACCES. Trying with "
219 : "CAP_DAC_OVERRIDE.\n", fsp->fsp_name->base_name);
220 0 : ret = fstat_with_cap_dac_override(fsp_get_pathref_fd(fsp),
221 : sbuf,
222 : fake_dctime);
223 : }
224 :
225 0 : return ret;
226 : }
227 :
228 0 : int nfs4_acl_lstat(struct vfs_handle_struct *handle,
229 : struct smb_filename *smb_fname)
230 : {
231 0 : int ret;
232 :
233 0 : ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
234 0 : if (ret == -1 && errno == EACCES) {
235 0 : DEBUG(10, ("Trying lstat with capability for %s\n",
236 : smb_fname->base_name));
237 0 : ret = stat_with_cap_dac_override(handle, smb_fname,
238 : AT_SYMLINK_NOFOLLOW);
239 : }
240 0 : return ret;
241 : }
242 :
243 0 : int nfs4_acl_fstatat(struct vfs_handle_struct *handle,
244 : const struct files_struct *dirfsp,
245 : const struct smb_filename *smb_fname,
246 : SMB_STRUCT_STAT *sbuf,
247 : int flags)
248 : {
249 0 : int ret;
250 :
251 0 : ret = SMB_VFS_NEXT_FSTATAT(handle, dirfsp, smb_fname, sbuf, flags);
252 0 : if (ret == -1 && errno == EACCES) {
253 0 : bool fake_dctime =
254 0 : lp_fake_directory_create_times(SNUM(handle->conn));
255 :
256 0 : DBG_DEBUG("fstatat for %s failed with EACCES. Trying with "
257 : "CAP_DAC_OVERRIDE.\n", dirfsp->fsp_name->base_name);
258 0 : ret = fstatat_with_cap_dac_override(fsp_get_pathref_fd(dirfsp),
259 0 : smb_fname->base_name,
260 : sbuf,
261 : flags,
262 : fake_dctime);
263 : }
264 :
265 0 : return ret;
266 : }
267 :
268 : /************************************************
269 : Split the ACE flag mapping between nfs4 and Windows
270 : into two separate functions rather than trying to do
271 : it inline. Allows us to carefully control what flags
272 : are mapped to what in one place.
273 : ************************************************/
274 :
275 11569 : static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
276 : uint32_t nfs4_ace_flags)
277 : {
278 11569 : uint32_t win_ace_flags = 0;
279 :
280 : /* The nfs4 flags <= 0xf map perfectly. */
281 11569 : win_ace_flags = nfs4_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
282 : SEC_ACE_FLAG_CONTAINER_INHERIT|
283 : SEC_ACE_FLAG_NO_PROPAGATE_INHERIT|
284 : SEC_ACE_FLAG_INHERIT_ONLY);
285 :
286 : /* flags greater than 0xf have diverged :-(. */
287 : /* See the nfs4 ace flag definitions here:
288 : http://www.ietf.org/rfc/rfc3530.txt.
289 : And the Windows ace flag definitions here:
290 : librpc/idl/security.idl. */
291 11569 : if (nfs4_ace_flags & SMB_ACE4_INHERITED_ACE) {
292 2112 : win_ace_flags |= SEC_ACE_FLAG_INHERITED_ACE;
293 : }
294 :
295 11569 : return win_ace_flags;
296 : }
297 :
298 5676 : static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags)
299 : {
300 5676 : uint32_t nfs4_ace_flags = 0;
301 :
302 : /* The windows flags <= 0xf map perfectly. */
303 5676 : nfs4_ace_flags = win_ace_flags & (SMB_ACE4_FILE_INHERIT_ACE|
304 : SMB_ACE4_DIRECTORY_INHERIT_ACE|
305 : SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
306 : SMB_ACE4_INHERIT_ONLY_ACE);
307 :
308 : /* flags greater than 0xf have diverged :-(. */
309 : /* See the nfs4 ace flag definitions here:
310 : http://www.ietf.org/rfc/rfc3530.txt.
311 : And the Windows ace flag definitions here:
312 : librpc/idl/security.idl. */
313 5676 : if (win_ace_flags & SEC_ACE_FLAG_INHERITED_ACE) {
314 1692 : nfs4_ace_flags |= SMB_ACE4_INHERITED_ACE;
315 : }
316 :
317 5676 : return nfs4_ace_flags;
318 : }
319 :
320 13881 : struct SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx)
321 : {
322 119 : struct SMB4ACL_T *theacl;
323 :
324 13881 : theacl = talloc_zero(mem_ctx, struct SMB4ACL_T);
325 13881 : if (theacl==NULL)
326 : {
327 0 : DEBUG(0, ("TALLOC_SIZE failed\n"));
328 0 : errno = ENOMEM;
329 0 : return NULL;
330 : }
331 13881 : theacl->controlflags = SEC_DESC_SELF_RELATIVE;
332 : /* theacl->first, last = NULL not needed */
333 13881 : return theacl;
334 : }
335 :
336 17183 : struct SMB4ACE_T *smb_add_ace4(struct SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
337 : {
338 149 : struct SMB4ACE_T *ace;
339 :
340 17183 : ace = talloc_zero(acl, struct SMB4ACE_T);
341 17183 : if (ace==NULL)
342 : {
343 0 : DBG_ERR("talloc_zero failed\n");
344 0 : errno = ENOMEM;
345 0 : return NULL;
346 : }
347 17183 : ace->prop = *prop;
348 :
349 17183 : if (acl->first==NULL)
350 : {
351 13817 : acl->first = ace;
352 13817 : acl->last = ace;
353 : } else {
354 3366 : acl->last->next = ace;
355 3366 : acl->last = ace;
356 : }
357 17183 : acl->naces++;
358 :
359 17183 : return ace;
360 : }
361 :
362 5606 : SMB_ACE4PROP_T *smb_get_ace4(struct SMB4ACE_T *ace)
363 : {
364 5606 : if (ace == NULL) {
365 0 : return NULL;
366 : }
367 :
368 5606 : return &ace->prop;
369 : }
370 :
371 5602 : struct SMB4ACE_T *smb_next_ace4(struct SMB4ACE_T *ace)
372 : {
373 5602 : if (ace == NULL) {
374 0 : return NULL;
375 : }
376 :
377 5602 : return ace->next;
378 : }
379 :
380 5060 : struct SMB4ACE_T *smb_first_ace4(struct SMB4ACL_T *acl)
381 : {
382 5060 : if (acl == NULL) {
383 0 : return NULL;
384 : }
385 :
386 5060 : return acl->first;
387 : }
388 :
389 5058 : uint32_t smb_get_naces(struct SMB4ACL_T *acl)
390 : {
391 5058 : if (acl == NULL) {
392 0 : return 0;
393 : }
394 :
395 5058 : return acl->naces;
396 : }
397 :
398 10968 : uint16_t smbacl4_get_controlflags(struct SMB4ACL_T *acl)
399 : {
400 10968 : if (acl == NULL) {
401 0 : return 0;
402 : }
403 :
404 10968 : return acl->controlflags;
405 : }
406 :
407 8754 : bool smbacl4_set_controlflags(struct SMB4ACL_T *acl, uint16_t controlflags)
408 : {
409 8754 : if (acl == NULL) {
410 0 : return false;
411 : }
412 :
413 8754 : acl->controlflags = controlflags;
414 8754 : return true;
415 : }
416 :
417 3897 : bool nfs_ace_is_inherit(SMB_ACE4PROP_T *ace)
418 : {
419 3897 : return ace->aceFlags & (SMB_ACE4_INHERIT_ONLY_ACE|
420 : SMB_ACE4_FILE_INHERIT_ACE|
421 : SMB_ACE4_DIRECTORY_INHERIT_ACE);
422 : }
423 :
424 0 : static int smbacl4_GetFileOwner(struct connection_struct *conn,
425 : const struct smb_filename *smb_fname,
426 : SMB_STRUCT_STAT *psbuf)
427 : {
428 0 : ZERO_STRUCTP(psbuf);
429 :
430 : /* Get the stat struct for the owner info. */
431 0 : if (vfs_stat_smb_basename(conn, smb_fname, psbuf) != 0)
432 : {
433 0 : DEBUG(8, ("vfs_stat_smb_basename failed with error %s\n",
434 : strerror(errno)));
435 0 : return -1;
436 : }
437 :
438 0 : return 0;
439 : }
440 :
441 11569 : static void check_for_duplicate_sec_ace(struct security_ace *nt_ace_list,
442 : int *good_aces)
443 : {
444 11569 : struct security_ace *last = NULL;
445 61 : int i;
446 :
447 11569 : if (*good_aces < 2) {
448 8716 : return;
449 : }
450 :
451 2804 : last = &nt_ace_list[(*good_aces) - 1];
452 :
453 5609 : for (i = 0; i < (*good_aces) - 1; i++) {
454 2805 : struct security_ace *cur = &nt_ace_list[i];
455 :
456 2805 : if (cur->type == last->type &&
457 2797 : cur->flags == last->flags &&
458 145 : cur->access_mask == last->access_mask &&
459 2 : dom_sid_equal(&cur->trustee, &last->trustee))
460 : {
461 2 : struct dom_sid_buf sid_buf;
462 :
463 2 : DBG_INFO("Removing duplicate entry for SID %s.\n",
464 : dom_sid_str_buf(&last->trustee, &sid_buf));
465 2 : (*good_aces)--;
466 : }
467 : }
468 : }
469 :
470 8820 : static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
471 : const struct smbacl4_vfs_params *params,
472 : struct SMB4ACL_T *acl, /* in */
473 : struct dom_sid *psid_owner, /* in */
474 : struct dom_sid *psid_group, /* in */
475 : bool is_directory, /* in */
476 : struct security_ace **ppnt_ace_list, /* out */
477 : int *pgood_aces /* out */
478 : )
479 : {
480 56 : struct SMB4ACE_T *aceint;
481 8820 : struct security_ace *nt_ace_list = NULL;
482 8820 : int good_aces = 0;
483 :
484 8820 : DEBUG(10, ("%s entered\n", __func__));
485 :
486 8820 : nt_ace_list = talloc_zero_array(mem_ctx, struct security_ace,
487 : 2 * acl->naces);
488 8820 : if (nt_ace_list==NULL)
489 : {
490 0 : DEBUG(10, ("talloc error with %d aces\n", acl->naces));
491 0 : errno = ENOMEM;
492 0 : return false;
493 : }
494 :
495 20396 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
496 68 : uint32_t mask;
497 68 : struct dom_sid sid;
498 68 : struct dom_sid_buf buf;
499 11576 : SMB_ACE4PROP_T *ace = &aceint->prop;
500 68 : uint32_t win_ace_flags;
501 :
502 11576 : DEBUG(10, ("type: %d, iflags: %x, flags: %x, "
503 : "mask: %x, who: %d\n",
504 : ace->aceType, ace->flags,
505 : ace->aceFlags, ace->aceMask, ace->who.id));
506 :
507 11576 : if (ace->flags & SMB_ACE4_ID_SPECIAL) {
508 10036 : switch (ace->who.special_id) {
509 6831 : case SMB_ACE4_WHO_OWNER:
510 6831 : sid_copy(&sid, psid_owner);
511 6831 : break;
512 5 : case SMB_ACE4_WHO_GROUP:
513 5 : sid_copy(&sid, psid_group);
514 5 : break;
515 3193 : case SMB_ACE4_WHO_EVERYONE:
516 3193 : sid_copy(&sid, &global_sid_World);
517 3193 : break;
518 7 : default:
519 7 : DEBUG(8, ("invalid special who id %d "
520 : "ignored\n", ace->who.special_id));
521 7 : continue;
522 : }
523 : } else {
524 1540 : if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
525 391 : gid_to_sid(&sid, ace->who.gid);
526 : } else {
527 1149 : uid_to_sid(&sid, ace->who.uid);
528 : }
529 : }
530 11569 : DEBUG(10, ("mapped %d to %s\n", ace->who.id,
531 : dom_sid_str_buf(&sid, &buf)));
532 :
533 11569 : if (!is_directory && params->map_full_control) {
534 : /*
535 : * Do we have all access except DELETE_CHILD
536 : * (not caring about the delete bit).
537 : */
538 5269 : uint32_t test_mask = ((ace->aceMask|SMB_ACE4_DELETE|SMB_ACE4_DELETE_CHILD) &
539 : SMB_ACE4_ALL_MASKS);
540 5269 : if (test_mask == SMB_ACE4_ALL_MASKS) {
541 183 : ace->aceMask |= SMB_ACE4_DELETE_CHILD;
542 : }
543 : }
544 :
545 11569 : win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(
546 : ace->aceFlags);
547 11569 : if (!is_directory &&
548 5270 : (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
549 : SEC_ACE_FLAG_CONTAINER_INHERIT))) {
550 : /*
551 : * GPFS sets inherits dir_inherit and file_inherit flags
552 : * to files, too, which confuses windows, and seems to
553 : * be wrong anyways. ==> Map these bits away for files.
554 : */
555 2 : DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
556 2 : win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
557 : SEC_ACE_FLAG_CONTAINER_INHERIT);
558 : }
559 11569 : DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
560 : ace->aceFlags, win_ace_flags));
561 :
562 11569 : mask = ace->aceMask;
563 :
564 : /* Mapping of owner@ and group@ to creator owner and
565 : creator group. Keep old behavior in mode special. */
566 11569 : if (params->mode != e_special &&
567 9875 : ace->flags & SMB_ACE4_ID_SPECIAL &&
568 8613 : (ace->who.special_id == SMB_ACE4_WHO_OWNER ||
569 2736 : ace->who.special_id == SMB_ACE4_WHO_GROUP)) {
570 5876 : DEBUG(10, ("Map special entry\n"));
571 5876 : if (!(win_ace_flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
572 8 : uint32_t win_ace_flags_current;
573 4652 : DEBUG(10, ("Map current sid\n"));
574 4652 : win_ace_flags_current = win_ace_flags &
575 : ~(SEC_ACE_FLAG_OBJECT_INHERIT |
576 : SEC_ACE_FLAG_CONTAINER_INHERIT);
577 4652 : init_sec_ace(&nt_ace_list[good_aces++], &sid,
578 4652 : ace->aceType, mask,
579 : win_ace_flags_current);
580 : }
581 5876 : if (ace->who.special_id == SMB_ACE4_WHO_OWNER &&
582 5872 : win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
583 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
584 3 : uint32_t win_ace_flags_creator;
585 1227 : DEBUG(10, ("Map creator owner\n"));
586 1227 : win_ace_flags_creator = win_ace_flags |
587 : SMB_ACE4_INHERIT_ONLY_ACE;
588 1227 : init_sec_ace(&nt_ace_list[good_aces++],
589 : &global_sid_Creator_Owner,
590 1227 : ace->aceType, mask,
591 : win_ace_flags_creator);
592 : }
593 5876 : if (ace->who.special_id == SMB_ACE4_WHO_GROUP &&
594 4 : win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
595 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
596 3 : uint32_t win_ace_flags_creator;
597 3 : DEBUG(10, ("Map creator owner group\n"));
598 3 : win_ace_flags_creator = win_ace_flags |
599 : SMB_ACE4_INHERIT_ONLY_ACE;
600 3 : init_sec_ace(&nt_ace_list[good_aces++],
601 : &global_sid_Creator_Group,
602 3 : ace->aceType, mask,
603 : win_ace_flags_creator);
604 : }
605 : } else {
606 5693 : DEBUG(10, ("Map normal sid\n"));
607 5693 : init_sec_ace(&nt_ace_list[good_aces++], &sid,
608 5693 : ace->aceType, mask,
609 : win_ace_flags);
610 : }
611 :
612 11569 : check_for_duplicate_sec_ace(nt_ace_list, &good_aces);
613 : }
614 :
615 8820 : nt_ace_list = talloc_realloc(mem_ctx, nt_ace_list, struct security_ace,
616 : good_aces);
617 :
618 : /* returns a NULL ace list when good_aces is zero. */
619 8820 : if (good_aces && nt_ace_list == NULL) {
620 0 : DEBUG(10, ("realloc error with %d aces\n", good_aces));
621 0 : errno = ENOMEM;
622 0 : return false;
623 : }
624 :
625 8820 : *ppnt_ace_list = nt_ace_list;
626 8820 : *pgood_aces = good_aces;
627 :
628 8820 : return true;
629 : }
630 :
631 8764 : static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
632 : const struct smbacl4_vfs_params *params,
633 : uint32_t security_info,
634 : TALLOC_CTX *mem_ctx,
635 : struct security_descriptor **ppdesc,
636 : struct SMB4ACL_T *theacl)
637 : {
638 8764 : int good_aces = 0;
639 0 : struct dom_sid sid_owner, sid_group;
640 8764 : size_t sd_size = 0;
641 8764 : struct security_ace *nt_ace_list = NULL;
642 8764 : struct security_acl *psa = NULL;
643 8764 : TALLOC_CTX *frame = talloc_stackframe();
644 0 : bool ok;
645 :
646 8764 : if (theacl==NULL) {
647 0 : TALLOC_FREE(frame);
648 0 : return NT_STATUS_ACCESS_DENIED; /* special because we
649 : * need to think through
650 : * the null case.*/
651 : }
652 :
653 8764 : uid_to_sid(&sid_owner, sbuf->st_ex_uid);
654 8764 : gid_to_sid(&sid_group, sbuf->st_ex_gid);
655 :
656 8764 : ok = smbacl4_nfs42win(frame, params, theacl, &sid_owner, &sid_group,
657 8764 : S_ISDIR(sbuf->st_ex_mode),
658 : &nt_ace_list, &good_aces);
659 8764 : if (!ok) {
660 0 : DEBUG(8,("smbacl4_nfs42win failed\n"));
661 0 : TALLOC_FREE(frame);
662 0 : return map_nt_error_from_unix(errno);
663 : }
664 :
665 8764 : psa = make_sec_acl(frame, NT4_ACL_REVISION, good_aces, nt_ace_list);
666 8764 : if (psa == NULL) {
667 0 : DEBUG(2,("make_sec_acl failed\n"));
668 0 : TALLOC_FREE(frame);
669 0 : return NT_STATUS_NO_MEMORY;
670 : }
671 :
672 8764 : DEBUG(10,("after make sec_acl\n"));
673 26292 : *ppdesc = make_sec_desc(
674 8764 : mem_ctx, SD_REVISION, smbacl4_get_controlflags(theacl),
675 8764 : (security_info & SECINFO_OWNER) ? &sid_owner : NULL,
676 8764 : (security_info & SECINFO_GROUP) ? &sid_group : NULL,
677 : NULL, psa, &sd_size);
678 8764 : if (*ppdesc==NULL) {
679 0 : DEBUG(2,("make_sec_desc failed\n"));
680 0 : TALLOC_FREE(frame);
681 0 : return NT_STATUS_NO_MEMORY;
682 : }
683 :
684 8764 : DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
685 : "sd_size %d\n",
686 : (int)ndr_size_security_descriptor(*ppdesc, 0)));
687 :
688 8764 : TALLOC_FREE(frame);
689 8764 : return NT_STATUS_OK;
690 : }
691 :
692 8764 : NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
693 : const struct smbacl4_vfs_params *pparams,
694 : uint32_t security_info,
695 : TALLOC_CTX *mem_ctx,
696 : struct security_descriptor **ppdesc,
697 : struct SMB4ACL_T *theacl)
698 : {
699 0 : struct smbacl4_vfs_params params;
700 :
701 8764 : DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
702 :
703 8764 : if (!VALID_STAT(fsp->fsp_name->st)) {
704 0 : NTSTATUS status;
705 :
706 0 : status = vfs_stat_fsp(fsp);
707 0 : if (!NT_STATUS_IS_OK(status)) {
708 0 : return status;
709 : }
710 : }
711 :
712 8764 : if (pparams == NULL) {
713 : /* Special behaviours */
714 8764 : if (smbacl4_get_vfs_params(fsp->conn, ¶ms)) {
715 0 : return NT_STATUS_NO_MEMORY;
716 : }
717 8764 : pparams = ¶ms;
718 : }
719 :
720 8764 : return smb_get_nt_acl_nfs4_common(&fsp->fsp_name->st, pparams,
721 : security_info,
722 : mem_ctx, ppdesc, theacl);
723 : }
724 :
725 0 : NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
726 : const struct smb_filename *smb_fname,
727 : const struct smbacl4_vfs_params *pparams,
728 : uint32_t security_info,
729 : TALLOC_CTX *mem_ctx,
730 : struct security_descriptor **ppdesc,
731 : struct SMB4ACL_T *theacl)
732 : {
733 0 : SMB_STRUCT_STAT sbuf;
734 0 : struct smbacl4_vfs_params params;
735 0 : const SMB_STRUCT_STAT *psbuf = NULL;
736 :
737 0 : DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n",
738 : smb_fname->base_name));
739 :
740 0 : if (VALID_STAT(smb_fname->st)) {
741 0 : psbuf = &smb_fname->st;
742 : }
743 :
744 0 : if (psbuf == NULL) {
745 0 : if (smbacl4_GetFileOwner(conn, smb_fname, &sbuf)) {
746 0 : return map_nt_error_from_unix(errno);
747 : }
748 0 : psbuf = &sbuf;
749 : }
750 :
751 0 : if (pparams == NULL) {
752 : /* Special behaviours */
753 0 : if (smbacl4_get_vfs_params(conn, ¶ms)) {
754 0 : return NT_STATUS_NO_MEMORY;
755 : }
756 0 : pparams = ¶ms;
757 : }
758 :
759 0 : return smb_get_nt_acl_nfs4_common(psbuf, pparams, security_info,
760 : mem_ctx, ppdesc, theacl);
761 : }
762 :
763 4998 : static void smbacl4_dump_nfs4acl(int level, struct SMB4ACL_T *acl)
764 : {
765 0 : struct SMB4ACE_T *aceint;
766 :
767 4998 : DEBUG(level, ("NFS4ACL: size=%d\n", acl->naces));
768 :
769 10524 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
770 5526 : SMB_ACE4PROP_T *ace = &aceint->prop;
771 :
772 5526 : DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
773 : "mask=0x%x, id=%d\n",
774 : ace->aceType,
775 : ace->aceFlags, ace->flags,
776 : ace->aceMask,
777 : ace->who.id));
778 : }
779 4998 : }
780 :
781 : /*
782 : * Find 2 NFS4 who-special ACE property (non-copy!!!)
783 : * match nonzero if "special" and who is equal
784 : * return ace if found matching; otherwise NULL
785 : */
786 5599 : static SMB_ACE4PROP_T *smbacl4_find_equal_special(
787 : struct SMB4ACL_T *acl,
788 : SMB_ACE4PROP_T *aceNew)
789 : {
790 73 : struct SMB4ACE_T *aceint;
791 :
792 6150 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
793 556 : SMB_ACE4PROP_T *ace = &aceint->prop;
794 :
795 556 : DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
796 : "new type:0x%x flags:0x%x aceFlags:0x%x\n",
797 : ace->aceType, ace->flags, ace->aceFlags,
798 : aceNew->aceType, aceNew->flags,aceNew->aceFlags));
799 :
800 556 : if (ace->flags == aceNew->flags &&
801 168 : ace->aceType==aceNew->aceType &&
802 167 : ace->aceFlags==aceNew->aceFlags)
803 : {
804 : /* keep type safety; e.g. gid is an u.short */
805 11 : if (ace->flags & SMB_ACE4_ID_SPECIAL)
806 : {
807 6 : if (ace->who.special_id ==
808 6 : aceNew->who.special_id)
809 0 : return ace;
810 : } else {
811 5 : if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
812 : {
813 0 : if (ace->who.gid==aceNew->who.gid)
814 0 : return ace;
815 : } else {
816 5 : if (ace->who.uid==aceNew->who.uid)
817 5 : return ace;
818 : }
819 : }
820 : }
821 : }
822 :
823 5526 : return NULL;
824 : }
825 :
826 5599 : static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup,
827 : struct SMB4ACL_T *theacl,
828 : SMB_ACE4PROP_T *ace,
829 : bool *paddNewACE)
830 : {
831 5599 : int result = 0;
832 5599 : SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
833 5599 : if (ace4found)
834 : {
835 5 : switch(acedup)
836 : {
837 1 : case e_merge: /* "merge" flags */
838 1 : *paddNewACE = false;
839 1 : ace4found->aceFlags |= ace->aceFlags;
840 1 : ace4found->aceMask |= ace->aceMask;
841 1 : break;
842 3 : case e_ignore: /* leave out this record */
843 3 : *paddNewACE = false;
844 3 : break;
845 1 : case e_reject: /* do an error */
846 1 : DBG_INFO("ACL rejected by duplicate nt ace.\n");
847 1 : errno = EINVAL; /* SHOULD be set on any _real_ error */
848 1 : result = -1;
849 1 : break;
850 0 : default:
851 0 : break;
852 : }
853 : }
854 5599 : return result;
855 : }
856 :
857 5612 : static int nfs4_acl_add_ace(enum smbacl4_acedup_enum acedup,
858 : struct SMB4ACL_T *nfs4_acl,
859 : SMB_ACE4PROP_T *nfs4_ace)
860 : {
861 5612 : bool add_ace = true;
862 :
863 5612 : if (acedup != e_dontcare) {
864 73 : int ret;
865 :
866 5599 : ret = smbacl4_MergeIgnoreReject(acedup, nfs4_acl,
867 : nfs4_ace, &add_ace);
868 5599 : if (ret == -1) {
869 0 : return -1;
870 : }
871 : }
872 :
873 5611 : if (add_ace) {
874 5607 : smb_add_ace4(nfs4_acl, nfs4_ace);
875 : }
876 :
877 5526 : return 0;
878 : }
879 :
880 5676 : static int nfs4_acl_add_sec_ace(bool is_directory,
881 : const struct smbacl4_vfs_params *params,
882 : uid_t ownerUID,
883 : gid_t ownerGID,
884 : const struct security_ace *ace_nt,
885 : struct SMB4ACL_T *nfs4_acl)
886 : {
887 90 : struct dom_sid_buf buf;
888 5676 : SMB_ACE4PROP_T nfs4_ace = { 0 };
889 5676 : SMB_ACE4PROP_T nfs4_ace_2 = { 0 };
890 5676 : bool add_ace2 = false;
891 90 : int ret;
892 :
893 5676 : DEBUG(10, ("got ace for %s\n",
894 : dom_sid_str_buf(&ace_nt->trustee, &buf)));
895 :
896 : /* only ACCESS|DENY supported right now */
897 5676 : nfs4_ace.aceType = ace_nt->type;
898 :
899 5766 : nfs4_ace.aceFlags =
900 5676 : map_windows_ace_flags_to_nfs4_ace_flags(ace_nt->flags);
901 :
902 : /* remove inheritance flags on files */
903 5676 : if (!is_directory) {
904 4287 : DEBUG(10, ("Removing inheritance flags from a file\n"));
905 4287 : nfs4_ace.aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE|
906 : SMB_ACE4_DIRECTORY_INHERIT_ACE|
907 : SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
908 : SMB_ACE4_INHERIT_ONLY_ACE);
909 : }
910 :
911 5676 : nfs4_ace.aceMask = ace_nt->access_mask & (SEC_STD_ALL | SEC_FILE_ALL);
912 :
913 5676 : se_map_generic(&nfs4_ace.aceMask, &file_generic_mapping);
914 :
915 5676 : if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
916 659 : nfs4_ace.who.special_id = SMB_ACE4_WHO_EVERYONE;
917 659 : nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
918 9324 : } else if (params->mode!=e_special &&
919 4307 : dom_sid_equal(&ace_nt->trustee,
920 : &global_sid_Creator_Owner)) {
921 284 : DEBUG(10, ("Map creator owner\n"));
922 284 : nfs4_ace.who.special_id = SMB_ACE4_WHO_OWNER;
923 284 : nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
924 : /* A non inheriting creator owner entry has no effect. */
925 284 : nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
926 284 : if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
927 140 : && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
928 60 : return 0;
929 : }
930 8756 : } else if (params->mode!=e_special &&
931 4023 : dom_sid_equal(&ace_nt->trustee,
932 : &global_sid_Creator_Group)) {
933 8 : DEBUG(10, ("Map creator owner group\n"));
934 8 : nfs4_ace.who.special_id = SMB_ACE4_WHO_GROUP;
935 8 : nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
936 : /* A non inheriting creator group entry has no effect. */
937 8 : nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
938 8 : if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
939 8 : && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
940 0 : return 0;
941 : }
942 : } else {
943 73 : struct unixid unixid;
944 73 : bool ok;
945 :
946 4725 : ok = sids_to_unixids(&ace_nt->trustee, 1, &unixid);
947 4725 : if (!ok) {
948 0 : DBG_WARNING("Could not convert %s to uid or gid.\n",
949 : dom_sid_str_buf(&ace_nt->trustee, &buf));
950 1 : return 0;
951 : }
952 :
953 4725 : if (dom_sid_compare_domain(&ace_nt->trustee,
954 : &global_sid_Unix_NFS) == 0) {
955 0 : return 0;
956 : }
957 :
958 4724 : switch (unixid.type) {
959 4 : case ID_TYPE_BOTH:
960 4 : nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
961 4 : nfs4_ace.who.gid = unixid.id;
962 :
963 6 : if (ownerUID == unixid.id &&
964 2 : !nfs_ace_is_inherit(&nfs4_ace))
965 : {
966 : /*
967 : * IDMAP_TYPE_BOTH for owner. Add
968 : * additional user entry, which can be
969 : * mapped to special:owner to reflect
970 : * the permissions in the modebits.
971 : *
972 : * This only applies to non-inheriting
973 : * entries as only these are replaced
974 : * with SPECIAL_OWNER in nfs4:mode=simple.
975 : */
976 1 : nfs4_ace_2 = (SMB_ACE4PROP_T) {
977 1 : .who.uid = unixid.id,
978 1 : .aceFlags = (nfs4_ace.aceFlags &
979 : ~SMB_ACE4_IDENTIFIER_GROUP),
980 1 : .aceMask = nfs4_ace.aceMask,
981 1 : .aceType = nfs4_ace.aceType,
982 : };
983 1 : add_ace2 = true;
984 : }
985 0 : break;
986 123 : case ID_TYPE_GID:
987 123 : nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
988 123 : nfs4_ace.who.gid = unixid.id;
989 123 : break;
990 4597 : case ID_TYPE_UID:
991 4597 : nfs4_ace.who.uid = unixid.id;
992 4597 : break;
993 0 : case ID_TYPE_NOT_SPECIFIED:
994 : default:
995 0 : DBG_WARNING("Could not convert %s to uid or gid.\n",
996 : dom_sid_str_buf(&ace_nt->trustee, &buf));
997 0 : return 0;
998 : }
999 : }
1000 :
1001 5611 : ret = nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace);
1002 5611 : if (ret != 0) {
1003 0 : return -1;
1004 : }
1005 :
1006 5610 : if (!add_ace2) {
1007 5526 : return 0;
1008 : }
1009 :
1010 1 : return nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace_2);
1011 : }
1012 :
1013 715 : static void smbacl4_substitute_special(struct SMB4ACL_T *acl,
1014 : uid_t ownerUID,
1015 : gid_t ownerGID)
1016 : {
1017 1 : struct SMB4ACE_T *aceint;
1018 :
1019 1519 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
1020 804 : SMB_ACE4PROP_T *ace = &aceint->prop;
1021 :
1022 804 : DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
1023 : "mask: %x, who: %d\n",
1024 : ace->aceType, ace->flags, ace->aceFlags,
1025 : ace->aceMask, ace->who.id));
1026 :
1027 804 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1028 710 : !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
1029 651 : ace->who.uid == ownerUID) {
1030 650 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1031 650 : ace->who.special_id = SMB_ACE4_WHO_OWNER;
1032 650 : DEBUG(10,("replaced with special owner ace\n"));
1033 : }
1034 :
1035 804 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1036 60 : ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
1037 59 : ace->who.uid == ownerGID) {
1038 2 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1039 2 : ace->who.special_id = SMB_ACE4_WHO_GROUP;
1040 2 : DEBUG(10,("replaced with special group ace\n"));
1041 : }
1042 : }
1043 715 : }
1044 :
1045 4345 : static void smbacl4_substitute_simple(struct SMB4ACL_T *acl,
1046 : uid_t ownerUID,
1047 : gid_t ownerGID)
1048 : {
1049 61 : struct SMB4ACE_T *aceint;
1050 :
1051 9147 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
1052 4802 : SMB_ACE4PROP_T *ace = &aceint->prop;
1053 :
1054 4802 : DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
1055 : "mask: %x, who: %d\n",
1056 : ace->aceType, ace->flags, ace->aceFlags,
1057 : ace->aceMask, ace->who.id));
1058 :
1059 4802 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1060 4009 : !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
1061 3944 : ace->who.uid == ownerUID &&
1062 3891 : !nfs_ace_is_inherit(ace)) {
1063 3661 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1064 3661 : ace->who.special_id = SMB_ACE4_WHO_OWNER;
1065 3661 : DEBUG(10,("replaced with special owner ace\n"));
1066 : }
1067 :
1068 4802 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1069 348 : ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
1070 72 : ace->who.gid == ownerGID &&
1071 4 : !nfs_ace_is_inherit(ace)) {
1072 1 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1073 1 : ace->who.special_id = SMB_ACE4_WHO_GROUP;
1074 1 : DEBUG(10,("replaced with special group ace\n"));
1075 : }
1076 : }
1077 4345 : }
1078 :
1079 5061 : static struct SMB4ACL_T *smbacl4_win2nfs4(
1080 : TALLOC_CTX *mem_ctx,
1081 : bool is_directory,
1082 : const struct security_acl *dacl,
1083 : const struct smbacl4_vfs_params *pparams,
1084 : uid_t ownerUID,
1085 : gid_t ownerGID
1086 : )
1087 : {
1088 63 : struct SMB4ACL_T *theacl;
1089 63 : uint32_t i;
1090 :
1091 5061 : DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
1092 :
1093 5061 : theacl = smb_create_smb4acl(mem_ctx);
1094 5061 : if (theacl==NULL)
1095 0 : return NULL;
1096 :
1097 10736 : for(i=0; i<dacl->num_aces; i++) {
1098 90 : int ret;
1099 :
1100 5766 : ret = nfs4_acl_add_sec_ace(is_directory, pparams,
1101 : ownerUID, ownerGID,
1102 5676 : dacl->aces + i, theacl);
1103 5676 : if (ret == -1) {
1104 0 : return NULL;
1105 : }
1106 : }
1107 :
1108 5060 : if (pparams->mode==e_simple) {
1109 4345 : smbacl4_substitute_simple(theacl, ownerUID, ownerGID);
1110 : }
1111 :
1112 5060 : if (pparams->mode==e_special) {
1113 715 : smbacl4_substitute_special(theacl, ownerUID, ownerGID);
1114 : }
1115 :
1116 4998 : return theacl;
1117 : }
1118 :
1119 5012 : NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
1120 : const struct smbacl4_vfs_params *pparams,
1121 : uint32_t security_info_sent,
1122 : const struct security_descriptor *psd,
1123 : set_nfs4acl_native_fn_t set_nfs4_native)
1124 : {
1125 0 : struct smbacl4_vfs_params params;
1126 5012 : struct SMB4ACL_T *theacl = NULL;
1127 0 : bool result, is_directory;
1128 :
1129 5012 : bool set_acl_as_root = false;
1130 0 : int saved_errno;
1131 0 : NTSTATUS status;
1132 5012 : TALLOC_CTX *frame = talloc_stackframe();
1133 :
1134 5012 : DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
1135 :
1136 5012 : if ((security_info_sent & (SECINFO_DACL |
1137 : SECINFO_GROUP | SECINFO_OWNER)) == 0)
1138 : {
1139 0 : DEBUG(9, ("security_info_sent (0x%x) ignored\n",
1140 : security_info_sent));
1141 0 : TALLOC_FREE(frame);
1142 0 : return NT_STATUS_OK; /* won't show error - later to be
1143 : * refined... */
1144 : }
1145 :
1146 5012 : if (security_descriptor_with_ms_nfs(psd)) {
1147 0 : TALLOC_FREE(frame);
1148 0 : return NT_STATUS_OK;
1149 : }
1150 :
1151 5012 : if (pparams == NULL) {
1152 : /* Special behaviours */
1153 0 : if (smbacl4_get_vfs_params(fsp->conn, ¶ms)) {
1154 0 : TALLOC_FREE(frame);
1155 0 : return NT_STATUS_NO_MEMORY;
1156 : }
1157 0 : pparams = ¶ms;
1158 : }
1159 :
1160 5012 : status = vfs_stat_fsp(fsp);
1161 5012 : if (!NT_STATUS_IS_OK(status)) {
1162 0 : TALLOC_FREE(frame);
1163 0 : return status;
1164 : }
1165 :
1166 5012 : is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
1167 :
1168 5012 : if (pparams->do_chown) {
1169 : /*
1170 : * When the chown succeeds, the special entries in the
1171 : * file system ACL refer to the new owner. In order to
1172 : * apply the complete information from the DACL,
1173 : * setting the ACL then has to succeed. Track this
1174 : * case with set_acl_as_root and set the ACL as root
1175 : * accordingly.
1176 : */
1177 5012 : status = chown_if_needed(fsp, security_info_sent, psd,
1178 : &set_acl_as_root);
1179 5012 : if (!NT_STATUS_IS_OK(status)) {
1180 0 : TALLOC_FREE(frame);
1181 0 : return status;
1182 : }
1183 : }
1184 :
1185 5012 : if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
1186 14 : DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
1187 : security_info_sent));
1188 14 : TALLOC_FREE(frame);
1189 14 : return NT_STATUS_OK;
1190 : }
1191 :
1192 4998 : theacl = smbacl4_win2nfs4(frame, is_directory, psd->dacl, pparams,
1193 4998 : fsp->fsp_name->st.st_ex_uid,
1194 4998 : fsp->fsp_name->st.st_ex_gid);
1195 4998 : if (!theacl) {
1196 0 : TALLOC_FREE(frame);
1197 0 : return map_nt_error_from_unix(errno);
1198 : }
1199 :
1200 4998 : smbacl4_set_controlflags(theacl, psd->type);
1201 4998 : smbacl4_dump_nfs4acl(10, theacl);
1202 :
1203 4998 : if (set_acl_as_root) {
1204 532 : become_root();
1205 : }
1206 4998 : result = set_nfs4_native(handle, fsp, theacl);
1207 4998 : saved_errno = errno;
1208 4998 : if (set_acl_as_root) {
1209 532 : unbecome_root();
1210 : }
1211 :
1212 4998 : TALLOC_FREE(frame);
1213 :
1214 4998 : if (result!=true) {
1215 0 : errno = saved_errno;
1216 0 : DEBUG(10, ("set_nfs4_native failed with %s\n",
1217 : strerror(errno)));
1218 0 : return map_nt_error_from_unix(errno);
1219 : }
1220 :
1221 4998 : DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
1222 4998 : return NT_STATUS_OK;
1223 : }
|