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 0 : int smbacl4_get_vfs_params(struct connection_struct *conn,
60 : struct smbacl4_vfs_params *params)
61 : {
62 : static const struct enum_list enum_smbacl4_modes[] = {
63 : { e_simple, "simple" },
64 : { e_special, "special" },
65 : { -1 , NULL }
66 : };
67 : 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 : int enumval;
75 :
76 0 : *params = (struct smbacl4_vfs_params) { 0 };
77 :
78 0 : enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "mode",
79 : enum_smbacl4_modes, e_simple);
80 0 : if (enumval == -1) {
81 0 : DEBUG(10, ("value for %s:mode unknown\n",
82 : SMBACL4_PARAM_TYPE_NAME));
83 0 : return -1;
84 : }
85 0 : params->mode = (enum smbacl4_mode_enum)enumval;
86 0 : if (params->mode == e_special) {
87 0 : DBG_WARNING("nfs4:mode special is deprecated.\n");
88 : }
89 :
90 0 : params->do_chown = lp_parm_bool(SNUM(conn), SMBACL4_PARAM_TYPE_NAME,
91 : "chown", true);
92 :
93 0 : enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "acedup",
94 : enum_smbacl4_acedups, e_merge);
95 0 : if (enumval == -1) {
96 0 : DEBUG(10, ("value for %s:acedup unknown\n",
97 : SMBACL4_PARAM_TYPE_NAME));
98 0 : return -1;
99 : }
100 0 : params->acedup = (enum smbacl4_acedup_enum)enumval;
101 0 : if (params->acedup == e_ignore) {
102 0 : DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
103 : }
104 0 : if (params->acedup == e_reject) {
105 0 : DBG_WARNING("nfs4:acedup ignore is deprecated.\n");
106 : }
107 :
108 0 : params->map_full_control = lp_acl_map_full_control(SNUM(conn));
109 :
110 0 : 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 0 : 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 : 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 : 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 : 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 : 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 : 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 : int ret;
212 :
213 0 : ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
214 0 : if (ret == -1 && errno == EACCES) {
215 : 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 : 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 : int ret;
250 :
251 0 : ret = SMB_VFS_NEXT_FSTATAT(handle, dirfsp, smb_fname, sbuf, flags);
252 0 : if (ret == -1 && errno == EACCES) {
253 : 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 0 : static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
276 : uint32_t nfs4_ace_flags)
277 : {
278 0 : uint32_t win_ace_flags = 0;
279 :
280 : /* The nfs4 flags <= 0xf map perfectly. */
281 0 : 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 0 : if (nfs4_ace_flags & SMB_ACE4_INHERITED_ACE) {
292 0 : win_ace_flags |= SEC_ACE_FLAG_INHERITED_ACE;
293 : }
294 :
295 0 : return win_ace_flags;
296 : }
297 :
298 0 : static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags)
299 : {
300 0 : uint32_t nfs4_ace_flags = 0;
301 :
302 : /* The windows flags <= 0xf map perfectly. */
303 0 : 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 0 : if (win_ace_flags & SEC_ACE_FLAG_INHERITED_ACE) {
314 0 : nfs4_ace_flags |= SMB_ACE4_INHERITED_ACE;
315 : }
316 :
317 0 : return nfs4_ace_flags;
318 : }
319 :
320 0 : struct SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx)
321 : {
322 : struct SMB4ACL_T *theacl;
323 :
324 0 : theacl = talloc_zero(mem_ctx, struct SMB4ACL_T);
325 0 : if (theacl==NULL)
326 : {
327 0 : DEBUG(0, ("TALLOC_SIZE failed\n"));
328 0 : errno = ENOMEM;
329 0 : return NULL;
330 : }
331 0 : theacl->controlflags = SEC_DESC_SELF_RELATIVE;
332 : /* theacl->first, last = NULL not needed */
333 0 : return theacl;
334 : }
335 :
336 0 : struct SMB4ACE_T *smb_add_ace4(struct SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
337 : {
338 : struct SMB4ACE_T *ace;
339 :
340 0 : ace = talloc_zero(acl, struct SMB4ACE_T);
341 0 : if (ace==NULL)
342 : {
343 0 : DBG_ERR("talloc_zero failed\n");
344 0 : errno = ENOMEM;
345 0 : return NULL;
346 : }
347 0 : ace->prop = *prop;
348 :
349 0 : if (acl->first==NULL)
350 : {
351 0 : acl->first = ace;
352 0 : acl->last = ace;
353 : } else {
354 0 : acl->last->next = ace;
355 0 : acl->last = ace;
356 : }
357 0 : acl->naces++;
358 :
359 0 : return ace;
360 : }
361 :
362 0 : SMB_ACE4PROP_T *smb_get_ace4(struct SMB4ACE_T *ace)
363 : {
364 0 : if (ace == NULL) {
365 0 : return NULL;
366 : }
367 :
368 0 : return &ace->prop;
369 : }
370 :
371 0 : struct SMB4ACE_T *smb_next_ace4(struct SMB4ACE_T *ace)
372 : {
373 0 : if (ace == NULL) {
374 0 : return NULL;
375 : }
376 :
377 0 : return ace->next;
378 : }
379 :
380 0 : struct SMB4ACE_T *smb_first_ace4(struct SMB4ACL_T *acl)
381 : {
382 0 : if (acl == NULL) {
383 0 : return NULL;
384 : }
385 :
386 0 : return acl->first;
387 : }
388 :
389 0 : uint32_t smb_get_naces(struct SMB4ACL_T *acl)
390 : {
391 0 : if (acl == NULL) {
392 0 : return 0;
393 : }
394 :
395 0 : return acl->naces;
396 : }
397 :
398 0 : uint16_t smbacl4_get_controlflags(struct SMB4ACL_T *acl)
399 : {
400 0 : if (acl == NULL) {
401 0 : return 0;
402 : }
403 :
404 0 : return acl->controlflags;
405 : }
406 :
407 0 : bool smbacl4_set_controlflags(struct SMB4ACL_T *acl, uint16_t controlflags)
408 : {
409 0 : if (acl == NULL) {
410 0 : return false;
411 : }
412 :
413 0 : acl->controlflags = controlflags;
414 0 : return true;
415 : }
416 :
417 0 : bool nfs_ace_is_inherit(SMB_ACE4PROP_T *ace)
418 : {
419 0 : 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 0 : static void check_for_duplicate_sec_ace(struct security_ace *nt_ace_list,
442 : int *good_aces)
443 : {
444 0 : struct security_ace *last = NULL;
445 : int i;
446 :
447 0 : if (*good_aces < 2) {
448 0 : return;
449 : }
450 :
451 0 : last = &nt_ace_list[(*good_aces) - 1];
452 :
453 0 : for (i = 0; i < (*good_aces) - 1; i++) {
454 0 : struct security_ace *cur = &nt_ace_list[i];
455 :
456 0 : if (cur->type == last->type &&
457 0 : cur->flags == last->flags &&
458 0 : cur->access_mask == last->access_mask &&
459 0 : dom_sid_equal(&cur->trustee, &last->trustee))
460 : {
461 : struct dom_sid_buf sid_buf;
462 :
463 0 : DBG_INFO("Removing duplicate entry for SID %s.\n",
464 : dom_sid_str_buf(&last->trustee, &sid_buf));
465 0 : (*good_aces)--;
466 : }
467 : }
468 : }
469 :
470 0 : 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 : struct SMB4ACE_T *aceint;
481 0 : struct security_ace *nt_ace_list = NULL;
482 0 : int good_aces = 0;
483 :
484 0 : DEBUG(10, ("%s entered\n", __func__));
485 :
486 0 : nt_ace_list = talloc_zero_array(mem_ctx, struct security_ace,
487 : 2 * acl->naces);
488 0 : if (nt_ace_list==NULL)
489 : {
490 0 : DEBUG(10, ("talloc error with %d aces", acl->naces));
491 0 : errno = ENOMEM;
492 0 : return false;
493 : }
494 :
495 0 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
496 : uint32_t mask;
497 : struct dom_sid sid;
498 : struct dom_sid_buf buf;
499 0 : SMB_ACE4PROP_T *ace = &aceint->prop;
500 : uint32_t win_ace_flags;
501 :
502 0 : 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 0 : if (ace->flags & SMB_ACE4_ID_SPECIAL) {
508 0 : switch (ace->who.special_id) {
509 0 : case SMB_ACE4_WHO_OWNER:
510 0 : sid_copy(&sid, psid_owner);
511 0 : break;
512 0 : case SMB_ACE4_WHO_GROUP:
513 0 : sid_copy(&sid, psid_group);
514 0 : break;
515 0 : case SMB_ACE4_WHO_EVERYONE:
516 0 : sid_copy(&sid, &global_sid_World);
517 0 : break;
518 0 : default:
519 0 : DEBUG(8, ("invalid special who id %d "
520 : "ignored\n", ace->who.special_id));
521 0 : continue;
522 : }
523 : } else {
524 0 : if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
525 0 : gid_to_sid(&sid, ace->who.gid);
526 : } else {
527 0 : uid_to_sid(&sid, ace->who.uid);
528 : }
529 : }
530 0 : DEBUG(10, ("mapped %d to %s\n", ace->who.id,
531 : dom_sid_str_buf(&sid, &buf)));
532 :
533 0 : 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 0 : uint32_t test_mask = ((ace->aceMask|SMB_ACE4_DELETE|SMB_ACE4_DELETE_CHILD) &
539 : SMB_ACE4_ALL_MASKS);
540 0 : if (test_mask == SMB_ACE4_ALL_MASKS) {
541 0 : ace->aceMask |= SMB_ACE4_DELETE_CHILD;
542 : }
543 : }
544 :
545 0 : win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(
546 : ace->aceFlags);
547 0 : if (!is_directory &&
548 0 : (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
549 : SEC_ACE_FLAG_CONTAINER_INHERIT))) {
550 : /*
551 : * GPFS sets inherits dir_inhert 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 0 : DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
556 0 : win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
557 : SEC_ACE_FLAG_CONTAINER_INHERIT);
558 : }
559 0 : DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
560 : ace->aceFlags, win_ace_flags));
561 :
562 0 : mask = ace->aceMask;
563 :
564 : /* Mapping of owner@ and group@ to creator owner and
565 : creator group. Keep old behavior in mode special. */
566 0 : if (params->mode != e_special &&
567 0 : ace->flags & SMB_ACE4_ID_SPECIAL &&
568 0 : (ace->who.special_id == SMB_ACE4_WHO_OWNER ||
569 0 : ace->who.special_id == SMB_ACE4_WHO_GROUP)) {
570 0 : DEBUG(10, ("Map special entry\n"));
571 0 : if (!(win_ace_flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
572 : uint32_t win_ace_flags_current;
573 0 : DEBUG(10, ("Map current sid\n"));
574 0 : win_ace_flags_current = win_ace_flags &
575 : ~(SEC_ACE_FLAG_OBJECT_INHERIT |
576 : SEC_ACE_FLAG_CONTAINER_INHERIT);
577 0 : init_sec_ace(&nt_ace_list[good_aces++], &sid,
578 0 : ace->aceType, mask,
579 : win_ace_flags_current);
580 : }
581 0 : if (ace->who.special_id == SMB_ACE4_WHO_OWNER &&
582 0 : win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
583 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
584 : uint32_t win_ace_flags_creator;
585 0 : DEBUG(10, ("Map creator owner\n"));
586 0 : win_ace_flags_creator = win_ace_flags |
587 : SMB_ACE4_INHERIT_ONLY_ACE;
588 0 : init_sec_ace(&nt_ace_list[good_aces++],
589 : &global_sid_Creator_Owner,
590 0 : ace->aceType, mask,
591 : win_ace_flags_creator);
592 : }
593 0 : if (ace->who.special_id == SMB_ACE4_WHO_GROUP &&
594 0 : win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
595 : SEC_ACE_FLAG_CONTAINER_INHERIT)) {
596 : uint32_t win_ace_flags_creator;
597 0 : DEBUG(10, ("Map creator owner group\n"));
598 0 : win_ace_flags_creator = win_ace_flags |
599 : SMB_ACE4_INHERIT_ONLY_ACE;
600 0 : init_sec_ace(&nt_ace_list[good_aces++],
601 : &global_sid_Creator_Group,
602 0 : ace->aceType, mask,
603 : win_ace_flags_creator);
604 : }
605 : } else {
606 0 : DEBUG(10, ("Map normal sid\n"));
607 0 : init_sec_ace(&nt_ace_list[good_aces++], &sid,
608 0 : ace->aceType, mask,
609 : win_ace_flags);
610 : }
611 :
612 0 : check_for_duplicate_sec_ace(nt_ace_list, &good_aces);
613 : }
614 :
615 0 : 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 0 : if (good_aces && nt_ace_list == NULL) {
620 0 : DEBUG(10, ("realloc error with %d aces", good_aces));
621 0 : errno = ENOMEM;
622 0 : return false;
623 : }
624 :
625 0 : *ppnt_ace_list = nt_ace_list;
626 0 : *pgood_aces = good_aces;
627 :
628 0 : return true;
629 : }
630 :
631 0 : 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 0 : int good_aces = 0;
639 : struct dom_sid sid_owner, sid_group;
640 0 : size_t sd_size = 0;
641 0 : struct security_ace *nt_ace_list = NULL;
642 0 : struct security_acl *psa = NULL;
643 0 : TALLOC_CTX *frame = talloc_stackframe();
644 : bool ok;
645 :
646 0 : 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 0 : uid_to_sid(&sid_owner, sbuf->st_ex_uid);
654 0 : gid_to_sid(&sid_group, sbuf->st_ex_gid);
655 :
656 0 : ok = smbacl4_nfs42win(frame, params, theacl, &sid_owner, &sid_group,
657 0 : S_ISDIR(sbuf->st_ex_mode),
658 : &nt_ace_list, &good_aces);
659 0 : 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 0 : psa = make_sec_acl(frame, NT4_ACL_REVISION, good_aces, nt_ace_list);
666 0 : 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 0 : DEBUG(10,("after make sec_acl\n"));
673 0 : *ppdesc = make_sec_desc(
674 0 : mem_ctx, SD_REVISION, smbacl4_get_controlflags(theacl),
675 0 : (security_info & SECINFO_OWNER) ? &sid_owner : NULL,
676 0 : (security_info & SECINFO_GROUP) ? &sid_group : NULL,
677 : NULL, psa, &sd_size);
678 0 : 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 0 : 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 0 : TALLOC_FREE(frame);
689 0 : return NT_STATUS_OK;
690 : }
691 :
692 0 : 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 : struct smbacl4_vfs_params params;
700 :
701 0 : DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
702 :
703 0 : if (!VALID_STAT(fsp->fsp_name->st)) {
704 : 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 0 : if (pparams == NULL) {
713 : /* Special behaviours */
714 0 : if (smbacl4_get_vfs_params(fsp->conn, ¶ms)) {
715 0 : return NT_STATUS_NO_MEMORY;
716 : }
717 0 : pparams = ¶ms;
718 : }
719 :
720 0 : 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 : SMB_STRUCT_STAT sbuf;
734 : 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 0 : static void smbacl4_dump_nfs4acl(int level, struct SMB4ACL_T *acl)
764 : {
765 : struct SMB4ACE_T *aceint;
766 :
767 0 : DEBUG(level, ("NFS4ACL: size=%d\n", acl->naces));
768 :
769 0 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
770 0 : SMB_ACE4PROP_T *ace = &aceint->prop;
771 :
772 0 : 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 0 : }
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 0 : static SMB_ACE4PROP_T *smbacl4_find_equal_special(
787 : struct SMB4ACL_T *acl,
788 : SMB_ACE4PROP_T *aceNew)
789 : {
790 : struct SMB4ACE_T *aceint;
791 :
792 0 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
793 0 : SMB_ACE4PROP_T *ace = &aceint->prop;
794 :
795 0 : 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 0 : if (ace->flags == aceNew->flags &&
801 0 : ace->aceType==aceNew->aceType &&
802 0 : ace->aceFlags==aceNew->aceFlags)
803 : {
804 : /* keep type safety; e.g. gid is an u.short */
805 0 : if (ace->flags & SMB_ACE4_ID_SPECIAL)
806 : {
807 0 : if (ace->who.special_id ==
808 0 : aceNew->who.special_id)
809 0 : return ace;
810 : } else {
811 0 : if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
812 : {
813 0 : if (ace->who.gid==aceNew->who.gid)
814 0 : return ace;
815 : } else {
816 0 : if (ace->who.uid==aceNew->who.uid)
817 0 : return ace;
818 : }
819 : }
820 : }
821 : }
822 :
823 0 : return NULL;
824 : }
825 :
826 0 : static int smbacl4_MergeIgnoreReject(enum smbacl4_acedup_enum acedup,
827 : struct SMB4ACL_T *theacl,
828 : SMB_ACE4PROP_T *ace,
829 : bool *paddNewACE)
830 : {
831 0 : int result = 0;
832 0 : SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
833 0 : if (ace4found)
834 : {
835 0 : switch(acedup)
836 : {
837 0 : case e_merge: /* "merge" flags */
838 0 : *paddNewACE = false;
839 0 : ace4found->aceFlags |= ace->aceFlags;
840 0 : ace4found->aceMask |= ace->aceMask;
841 0 : break;
842 0 : case e_ignore: /* leave out this record */
843 0 : *paddNewACE = false;
844 0 : break;
845 0 : case e_reject: /* do an error */
846 0 : DBG_INFO("ACL rejected by duplicate nt ace.\n");
847 0 : errno = EINVAL; /* SHOULD be set on any _real_ error */
848 0 : result = -1;
849 0 : break;
850 0 : default:
851 0 : break;
852 : }
853 : }
854 0 : return result;
855 : }
856 :
857 0 : 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 0 : bool add_ace = true;
862 :
863 0 : if (acedup != e_dontcare) {
864 : int ret;
865 :
866 0 : ret = smbacl4_MergeIgnoreReject(acedup, nfs4_acl,
867 : nfs4_ace, &add_ace);
868 0 : if (ret == -1) {
869 0 : return -1;
870 : }
871 : }
872 :
873 0 : if (add_ace) {
874 0 : smb_add_ace4(nfs4_acl, nfs4_ace);
875 : }
876 :
877 0 : return 0;
878 : }
879 :
880 0 : 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 : struct dom_sid_buf buf;
888 0 : SMB_ACE4PROP_T nfs4_ace = { 0 };
889 0 : SMB_ACE4PROP_T nfs4_ace_2 = { 0 };
890 0 : bool add_ace2 = false;
891 : int ret;
892 :
893 0 : 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 0 : nfs4_ace.aceType = ace_nt->type;
898 :
899 0 : nfs4_ace.aceFlags =
900 0 : map_windows_ace_flags_to_nfs4_ace_flags(ace_nt->flags);
901 :
902 : /* remove inheritance flags on files */
903 0 : if (!is_directory) {
904 0 : DEBUG(10, ("Removing inheritance flags from a file\n"));
905 0 : 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 0 : nfs4_ace.aceMask = ace_nt->access_mask & (SEC_STD_ALL | SEC_FILE_ALL);
912 :
913 0 : se_map_generic(&nfs4_ace.aceMask, &file_generic_mapping);
914 :
915 0 : if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
916 0 : nfs4_ace.who.special_id = SMB_ACE4_WHO_EVERYONE;
917 0 : nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
918 0 : } else if (params->mode!=e_special &&
919 0 : dom_sid_equal(&ace_nt->trustee,
920 : &global_sid_Creator_Owner)) {
921 0 : DEBUG(10, ("Map creator owner\n"));
922 0 : nfs4_ace.who.special_id = SMB_ACE4_WHO_OWNER;
923 0 : nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
924 : /* A non inheriting creator owner entry has no effect. */
925 0 : nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
926 0 : if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
927 0 : && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
928 0 : return 0;
929 : }
930 0 : } else if (params->mode!=e_special &&
931 0 : dom_sid_equal(&ace_nt->trustee,
932 : &global_sid_Creator_Group)) {
933 0 : DEBUG(10, ("Map creator owner group\n"));
934 0 : nfs4_ace.who.special_id = SMB_ACE4_WHO_GROUP;
935 0 : nfs4_ace.flags |= SMB_ACE4_ID_SPECIAL;
936 : /* A non inheriting creator group entry has no effect. */
937 0 : nfs4_ace.aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
938 0 : if (!(nfs4_ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
939 0 : && !(nfs4_ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
940 0 : return 0;
941 : }
942 : } else {
943 : struct unixid unixid;
944 : bool ok;
945 :
946 0 : ok = sids_to_unixids(&ace_nt->trustee, 1, &unixid);
947 0 : 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 0 : return 0;
951 : }
952 :
953 0 : if (dom_sid_compare_domain(&ace_nt->trustee,
954 : &global_sid_Unix_NFS) == 0) {
955 0 : return 0;
956 : }
957 :
958 0 : switch (unixid.type) {
959 0 : case ID_TYPE_BOTH:
960 0 : nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
961 0 : nfs4_ace.who.gid = unixid.id;
962 :
963 0 : if (ownerUID == unixid.id &&
964 0 : !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 0 : nfs4_ace_2 = (SMB_ACE4PROP_T) {
977 0 : .who.uid = unixid.id,
978 0 : .aceFlags = (nfs4_ace.aceFlags &
979 : ~SMB_ACE4_IDENTIFIER_GROUP),
980 0 : .aceMask = nfs4_ace.aceMask,
981 0 : .aceType = nfs4_ace.aceType,
982 : };
983 0 : add_ace2 = true;
984 : }
985 0 : break;
986 0 : case ID_TYPE_GID:
987 0 : nfs4_ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
988 0 : nfs4_ace.who.gid = unixid.id;
989 0 : break;
990 0 : case ID_TYPE_UID:
991 0 : nfs4_ace.who.uid = unixid.id;
992 0 : 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 0 : ret = nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace);
1002 0 : if (ret != 0) {
1003 0 : return -1;
1004 : }
1005 :
1006 0 : if (!add_ace2) {
1007 0 : return 0;
1008 : }
1009 :
1010 0 : return nfs4_acl_add_ace(params->acedup, nfs4_acl, &nfs4_ace_2);
1011 : }
1012 :
1013 0 : static void smbacl4_substitute_special(struct SMB4ACL_T *acl,
1014 : uid_t ownerUID,
1015 : gid_t ownerGID)
1016 : {
1017 : struct SMB4ACE_T *aceint;
1018 :
1019 0 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
1020 0 : SMB_ACE4PROP_T *ace = &aceint->prop;
1021 :
1022 0 : 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 0 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1028 0 : !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
1029 0 : ace->who.uid == ownerUID) {
1030 0 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1031 0 : ace->who.special_id = SMB_ACE4_WHO_OWNER;
1032 0 : DEBUG(10,("replaced with special owner ace\n"));
1033 : }
1034 :
1035 0 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1036 0 : ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
1037 0 : ace->who.uid == ownerGID) {
1038 0 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1039 0 : ace->who.special_id = SMB_ACE4_WHO_GROUP;
1040 0 : DEBUG(10,("replaced with special group ace\n"));
1041 : }
1042 : }
1043 0 : }
1044 :
1045 0 : static void smbacl4_substitute_simple(struct SMB4ACL_T *acl,
1046 : uid_t ownerUID,
1047 : gid_t ownerGID)
1048 : {
1049 : struct SMB4ACE_T *aceint;
1050 :
1051 0 : for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
1052 0 : SMB_ACE4PROP_T *ace = &aceint->prop;
1053 :
1054 0 : 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 0 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1060 0 : !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
1061 0 : ace->who.uid == ownerUID &&
1062 0 : !nfs_ace_is_inherit(ace)) {
1063 0 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1064 0 : ace->who.special_id = SMB_ACE4_WHO_OWNER;
1065 0 : DEBUG(10,("replaced with special owner ace\n"));
1066 : }
1067 :
1068 0 : if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
1069 0 : ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
1070 0 : ace->who.gid == ownerGID &&
1071 0 : !nfs_ace_is_inherit(ace)) {
1072 0 : ace->flags |= SMB_ACE4_ID_SPECIAL;
1073 0 : ace->who.special_id = SMB_ACE4_WHO_GROUP;
1074 0 : DEBUG(10,("replaced with special group ace\n"));
1075 : }
1076 : }
1077 0 : }
1078 :
1079 0 : 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 : struct SMB4ACL_T *theacl;
1089 : uint32_t i;
1090 :
1091 0 : DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
1092 :
1093 0 : theacl = smb_create_smb4acl(mem_ctx);
1094 0 : if (theacl==NULL)
1095 0 : return NULL;
1096 :
1097 0 : for(i=0; i<dacl->num_aces; i++) {
1098 : int ret;
1099 :
1100 0 : ret = nfs4_acl_add_sec_ace(is_directory, pparams,
1101 : ownerUID, ownerGID,
1102 0 : dacl->aces + i, theacl);
1103 0 : if (ret == -1) {
1104 0 : return NULL;
1105 : }
1106 : }
1107 :
1108 0 : if (pparams->mode==e_simple) {
1109 0 : smbacl4_substitute_simple(theacl, ownerUID, ownerGID);
1110 : }
1111 :
1112 0 : if (pparams->mode==e_special) {
1113 0 : smbacl4_substitute_special(theacl, ownerUID, ownerGID);
1114 : }
1115 :
1116 0 : return theacl;
1117 : }
1118 :
1119 0 : 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 : struct smbacl4_vfs_params params;
1126 0 : struct SMB4ACL_T *theacl = NULL;
1127 : bool result, is_directory;
1128 :
1129 0 : bool set_acl_as_root = false;
1130 : int saved_errno;
1131 : NTSTATUS status;
1132 0 : TALLOC_CTX *frame = talloc_stackframe();
1133 :
1134 0 : DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
1135 :
1136 0 : 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 0 : if (security_descriptor_with_ms_nfs(psd)) {
1147 0 : TALLOC_FREE(frame);
1148 0 : return NT_STATUS_OK;
1149 : }
1150 :
1151 0 : 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 0 : status = vfs_stat_fsp(fsp);
1161 0 : if (!NT_STATUS_IS_OK(status)) {
1162 0 : TALLOC_FREE(frame);
1163 0 : return status;
1164 : }
1165 :
1166 0 : is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
1167 :
1168 0 : 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 0 : status = chown_if_needed(fsp, security_info_sent, psd,
1178 : &set_acl_as_root);
1179 0 : if (!NT_STATUS_IS_OK(status)) {
1180 0 : TALLOC_FREE(frame);
1181 0 : return status;
1182 : }
1183 : }
1184 :
1185 0 : if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
1186 0 : DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
1187 : security_info_sent));
1188 0 : TALLOC_FREE(frame);
1189 0 : return NT_STATUS_OK;
1190 : }
1191 :
1192 0 : theacl = smbacl4_win2nfs4(frame, is_directory, psd->dacl, pparams,
1193 0 : fsp->fsp_name->st.st_ex_uid,
1194 0 : fsp->fsp_name->st.st_ex_gid);
1195 0 : if (!theacl) {
1196 0 : TALLOC_FREE(frame);
1197 0 : return map_nt_error_from_unix(errno);
1198 : }
1199 :
1200 0 : smbacl4_set_controlflags(theacl, psd->type);
1201 0 : smbacl4_dump_nfs4acl(10, theacl);
1202 :
1203 0 : if (set_acl_as_root) {
1204 0 : become_root();
1205 : }
1206 0 : result = set_nfs4_native(handle, fsp, theacl);
1207 0 : saved_errno = errno;
1208 0 : if (set_acl_as_root) {
1209 0 : unbecome_root();
1210 : }
1211 :
1212 0 : TALLOC_FREE(frame);
1213 :
1214 0 : 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 0 : DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
1222 0 : return NT_STATUS_OK;
1223 : }
|