4 * Copyright (C) Jim McDonough, 2006
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "smbd/smbd.h"
22 #include "nfs4_acls.h"
23 #include "librpc/gen_ndr/ndr_security.h"
24 #include "../libcli/security/dom_sid.h"
25 #include "../libcli/security/security.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_open.h"
28 #include "system/filesys.h"
29 #include "passdb/lookup_sid.h"
31 #include "lib/param/loadparm.h"
34 #define DBGC_CLASS DBGC_ACLS
36 #define SMBACL4_PARAM_TYPE_NAME "nfs4"
38 extern const struct generic_mapping file_generic_mapping
;
40 #define SMB_ACE4_INT_MAGIC 0x76F8A967
41 typedef struct _SMB_ACE4_INT_T
48 #define SMB_ACL4_INT_MAGIC 0x29A3E792
49 typedef struct _SMB_ACL4_INT_T
53 SMB_ACE4_INT_T
*first
;
57 /************************************************
58 Split the ACE flag mapping between nfs4 and Windows
59 into two separate functions rather than trying to do
60 it inline. Allows us to carefully control what flags
61 are mapped to what in one place.
62 ************************************************/
64 static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(uint32_t nfs4_ace_flags
)
66 uint32_t win_ace_flags
= 0;
68 /* The nfs4 flags <= 0xf map perfectly. */
69 win_ace_flags
= nfs4_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|
70 SEC_ACE_FLAG_CONTAINER_INHERIT
|
71 SEC_ACE_FLAG_NO_PROPAGATE_INHERIT
|
72 SEC_ACE_FLAG_INHERIT_ONLY
);
74 /* flags greater than 0xf have diverged :-(. */
75 /* See the nfs4 ace flag definitions here:
76 http://www.ietf.org/rfc/rfc3530.txt.
77 And the Windows ace flag definitions here:
78 librpc/idl/security.idl. */
79 if (nfs4_ace_flags
& SMB_ACE4_INHERITED_ACE
) {
80 win_ace_flags
|= SEC_ACE_FLAG_INHERITED_ACE
;
86 static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags
)
88 uint32_t nfs4_ace_flags
= 0;
90 /* The windows flags <= 0xf map perfectly. */
91 nfs4_ace_flags
= win_ace_flags
& (SMB_ACE4_FILE_INHERIT_ACE
|
92 SMB_ACE4_DIRECTORY_INHERIT_ACE
|
93 SMB_ACE4_NO_PROPAGATE_INHERIT_ACE
|
94 SMB_ACE4_INHERIT_ONLY_ACE
);
96 /* flags greater than 0xf have diverged :-(. */
97 /* See the nfs4 ace flag definitions here:
98 http://www.ietf.org/rfc/rfc3530.txt.
99 And the Windows ace flag definitions here:
100 librpc/idl/security.idl. */
101 if (win_ace_flags
& SEC_ACE_FLAG_INHERITED_ACE
) {
102 nfs4_ace_flags
|= SMB_ACE4_INHERITED_ACE
;
105 return nfs4_ace_flags
;
108 static SMB_ACL4_INT_T
*get_validated_aclint(SMB4ACL_T
*theacl
)
110 SMB_ACL4_INT_T
*aclint
= (SMB_ACL4_INT_T
*)theacl
;
113 DEBUG(2, ("acl is NULL\n"));
117 if (aclint
->magic
!=SMB_ACL4_INT_MAGIC
)
119 DEBUG(2, ("aclint bad magic 0x%x\n", aclint
->magic
));
126 static SMB_ACE4_INT_T
*get_validated_aceint(SMB4ACE_T
*ace
)
128 SMB_ACE4_INT_T
*aceint
= (SMB_ACE4_INT_T
*)ace
;
131 DEBUG(2, ("ace is NULL\n"));
135 if (aceint
->magic
!=SMB_ACE4_INT_MAGIC
)
137 DEBUG(2, ("aceint bad magic 0x%x\n", aceint
->magic
));
144 SMB4ACL_T
*smb_create_smb4acl(void)
146 TALLOC_CTX
*mem_ctx
= talloc_tos();
147 SMB_ACL4_INT_T
*theacl
= (SMB_ACL4_INT_T
*)TALLOC_ZERO_SIZE(mem_ctx
, sizeof(SMB_ACL4_INT_T
));
150 DEBUG(0, ("TALLOC_SIZE failed\n"));
154 theacl
->magic
= SMB_ACL4_INT_MAGIC
;
155 /* theacl->first, last = NULL not needed */
156 return (SMB4ACL_T
*)theacl
;
159 SMB4ACE_T
*smb_add_ace4(SMB4ACL_T
*theacl
, SMB_ACE4PROP_T
*prop
)
161 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
162 TALLOC_CTX
*mem_ctx
= talloc_tos();
165 ace
= (SMB_ACE4_INT_T
*)TALLOC_ZERO_SIZE(mem_ctx
, sizeof(SMB_ACE4_INT_T
));
168 DEBUG(0, ("TALLOC_SIZE failed\n"));
172 ace
->magic
= SMB_ACE4_INT_MAGIC
;
173 /* ace->next = NULL not needed */
174 memcpy(&ace
->prop
, prop
, sizeof(SMB_ACE4PROP_T
));
176 if (aclint
->first
==NULL
)
181 aclint
->last
->next
= (void *)ace
;
186 return (SMB4ACE_T
*)ace
;
189 SMB_ACE4PROP_T
*smb_get_ace4(SMB4ACE_T
*ace
)
191 SMB_ACE4_INT_T
*aceint
= get_validated_aceint(ace
);
195 return &aceint
->prop
;
198 SMB4ACE_T
*smb_next_ace4(SMB4ACE_T
*ace
)
200 SMB_ACE4_INT_T
*aceint
= get_validated_aceint(ace
);
204 return (SMB4ACE_T
*)aceint
->next
;
207 SMB4ACE_T
*smb_first_ace4(SMB4ACL_T
*theacl
)
209 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
213 return (SMB4ACE_T
*)aclint
->first
;
216 uint32
smb_get_naces(SMB4ACL_T
*theacl
)
218 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
222 return aclint
->naces
;
225 static int smbacl4_GetFileOwner(struct connection_struct
*conn
,
226 const char *filename
,
227 SMB_STRUCT_STAT
*psbuf
)
229 memset(psbuf
, 0, sizeof(SMB_STRUCT_STAT
));
231 /* Get the stat struct for the owner info. */
232 if (vfs_stat_smb_fname(conn
, filename
, psbuf
) != 0)
234 DEBUG(8, ("vfs_stat_smb_fname failed with error %s\n",
242 static int smbacl4_fGetFileOwner(files_struct
*fsp
, SMB_STRUCT_STAT
*psbuf
)
244 memset(psbuf
, 0, sizeof(SMB_STRUCT_STAT
));
246 if (fsp
->fh
->fd
== -1) {
247 return smbacl4_GetFileOwner(fsp
->conn
,
248 fsp
->fsp_name
->base_name
, psbuf
);
250 if (SMB_VFS_FSTAT(fsp
, psbuf
) != 0)
252 DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n",
260 static bool smbacl4_nfs42win(TALLOC_CTX
*mem_ctx
, SMB4ACL_T
*theacl
, /* in */
261 struct dom_sid
*psid_owner
, /* in */
262 struct dom_sid
*psid_group
, /* in */
263 bool is_directory
, /* in */
264 struct security_ace
**ppnt_ace_list
, /* out */
265 int *pgood_aces
/* out */
268 SMB_ACL4_INT_T
*aclint
= (SMB_ACL4_INT_T
*)theacl
;
269 SMB_ACE4_INT_T
*aceint
;
270 struct security_ace
*nt_ace_list
= NULL
;
273 DEBUG(10, ("smbacl_nfs42win entered\n"));
275 aclint
= get_validated_aclint(theacl
);
276 /* We do not check for naces being 0 or theacl being NULL here because it is done upstream */
277 /* in smb_get_nt_acl_nfs4(). */
278 nt_ace_list
= (struct security_ace
*)TALLOC_ZERO_SIZE(mem_ctx
, aclint
->naces
* sizeof(struct security_ace
));
279 if (nt_ace_list
==NULL
)
281 DEBUG(10, ("talloc error"));
286 for (aceint
=aclint
->first
; aceint
!=NULL
; aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
289 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
290 uint32_t win_ace_flags
;
292 DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, "
293 "who: %d\n", aceint
->magic
, ace
->aceType
, ace
->flags
,
294 ace
->aceFlags
, ace
->aceMask
, ace
->who
.id
));
296 SMB_ASSERT(aceint
->magic
==SMB_ACE4_INT_MAGIC
);
298 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
) {
299 switch (ace
->who
.special_id
) {
300 case SMB_ACE4_WHO_OWNER
:
301 sid_copy(&sid
, psid_owner
);
303 case SMB_ACE4_WHO_GROUP
:
304 sid_copy(&sid
, psid_group
);
306 case SMB_ACE4_WHO_EVERYONE
:
307 sid_copy(&sid
, &global_sid_World
);
310 DEBUG(8, ("invalid special who id %d "
311 "ignored\n", ace
->who
.special_id
));
314 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
) {
315 gid_to_sid(&sid
, ace
->who
.gid
);
317 uid_to_sid(&sid
, ace
->who
.uid
);
320 DEBUG(10, ("mapped %d to %s\n", ace
->who
.id
,
321 sid_string_dbg(&sid
)));
323 if (is_directory
&& (ace
->aceMask
& SMB_ACE4_ADD_FILE
)) {
324 ace
->aceMask
|= SMB_ACE4_DELETE_CHILD
;
327 win_ace_flags
= map_nfs4_ace_flags_to_windows_ace_flags(ace
->aceFlags
);
328 if (!is_directory
&& (win_ace_flags
& (SEC_ACE_FLAG_OBJECT_INHERIT
|SEC_ACE_FLAG_CONTAINER_INHERIT
))) {
330 * GPFS sets inherits dir_inhert and file_inherit flags
331 * to files, too, which confuses windows, and seems to
332 * be wrong anyways. ==> Map these bits away for files.
334 DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
335 win_ace_flags
&= ~(SEC_ACE_FLAG_OBJECT_INHERIT
|SEC_ACE_FLAG_CONTAINER_INHERIT
);
337 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
338 ace
->aceFlags
, win_ace_flags
));
340 /* Windows clients expect SYNC on acls to
341 correctly allow rename. See bug #7909. */
342 if(ace
->aceType
& SMB_ACE4_ACCESS_DENIED_ACE_TYPE
) {
343 /* But not on DENY ace entries. See
347 mask
= ace
->aceMask
| SMB_ACE4_SYNCHRONIZE
;
349 init_sec_ace(&nt_ace_list
[good_aces
++], &sid
,
354 *ppnt_ace_list
= nt_ace_list
;
355 *pgood_aces
= good_aces
;
360 static NTSTATUS
smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT
*sbuf
,
361 uint32 security_info
,
362 struct security_descriptor
**ppdesc
, SMB4ACL_T
*theacl
)
365 struct dom_sid sid_owner
, sid_group
;
367 struct security_ace
*nt_ace_list
= NULL
;
368 struct security_acl
*psa
= NULL
;
369 TALLOC_CTX
*mem_ctx
= talloc_tos();
371 if (theacl
==NULL
|| smb_get_naces(theacl
)==0)
372 return NT_STATUS_ACCESS_DENIED
; /* special because we
373 * shouldn't alloc 0 for
376 uid_to_sid(&sid_owner
, sbuf
->st_ex_uid
);
377 gid_to_sid(&sid_group
, sbuf
->st_ex_gid
);
379 if (smbacl4_nfs42win(mem_ctx
, theacl
, &sid_owner
, &sid_group
,
380 S_ISDIR(sbuf
->st_ex_mode
),
381 &nt_ace_list
, &good_aces
)==False
) {
382 DEBUG(8,("smbacl4_nfs42win failed\n"));
383 return map_nt_error_from_unix(errno
);
386 psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, good_aces
, nt_ace_list
);
388 DEBUG(2,("make_sec_acl failed\n"));
389 return NT_STATUS_NO_MEMORY
;
392 DEBUG(10,("after make sec_acl\n"));
393 *ppdesc
= make_sec_desc(mem_ctx
, SD_REVISION
, SEC_DESC_SELF_RELATIVE
,
394 (security_info
& SECINFO_OWNER
) ? &sid_owner
: NULL
,
395 (security_info
& SECINFO_GROUP
) ? &sid_group
: NULL
,
396 NULL
, psa
, &sd_size
);
398 DEBUG(2,("make_sec_desc failed\n"));
399 return NT_STATUS_NO_MEMORY
;
402 DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n",
403 (int)ndr_size_security_descriptor(*ppdesc
, 0)));
408 NTSTATUS
smb_fget_nt_acl_nfs4(files_struct
*fsp
,
409 uint32 security_info
,
410 struct security_descriptor
**ppdesc
, SMB4ACL_T
*theacl
)
412 SMB_STRUCT_STAT sbuf
;
414 DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
416 if (smbacl4_fGetFileOwner(fsp
, &sbuf
)) {
417 return map_nt_error_from_unix(errno
);
420 return smb_get_nt_acl_nfs4_common(&sbuf
, security_info
, ppdesc
, theacl
);
423 NTSTATUS
smb_get_nt_acl_nfs4(struct connection_struct
*conn
,
425 uint32 security_info
,
426 struct security_descriptor
**ppdesc
, SMB4ACL_T
*theacl
)
428 SMB_STRUCT_STAT sbuf
;
430 DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name
));
432 if (smbacl4_GetFileOwner(conn
, name
, &sbuf
)) {
433 return map_nt_error_from_unix(errno
);
436 return smb_get_nt_acl_nfs4_common(&sbuf
, security_info
, ppdesc
, theacl
);
439 enum smbacl4_mode_enum
{e_simple
=0, e_special
=1};
440 enum smbacl4_acedup_enum
{e_dontcare
=0, e_reject
=1, e_ignore
=2, e_merge
=3};
442 typedef struct _smbacl4_vfs_params
{
443 enum smbacl4_mode_enum mode
;
445 enum smbacl4_acedup_enum acedup
;
446 struct db_context
*sid_mapping_table
;
447 } smbacl4_vfs_params
;
450 * Gather special parameters for NFS4 ACL handling
452 static int smbacl4_get_vfs_params(
453 const char *type_name
,
455 smbacl4_vfs_params
*params
458 static const struct enum_list enum_smbacl4_modes
[] = {
459 { e_simple
, "simple" },
460 { e_special
, "special" },
463 static const struct enum_list enum_smbacl4_acedups
[] = {
464 { e_dontcare
, "dontcare" },
465 { e_reject
, "reject" },
466 { e_ignore
, "ignore" },
467 { e_merge
, "merge" },
471 memset(params
, 0, sizeof(smbacl4_vfs_params
));
472 params
->mode
= (enum smbacl4_mode_enum
)lp_parm_enum(
473 SNUM(fsp
->conn
), type_name
,
474 "mode", enum_smbacl4_modes
, e_simple
);
475 params
->do_chown
= lp_parm_bool(SNUM(fsp
->conn
), type_name
,
477 params
->acedup
= (enum smbacl4_acedup_enum
)lp_parm_enum(
478 SNUM(fsp
->conn
), type_name
,
479 "acedup", enum_smbacl4_acedups
, e_dontcare
);
481 DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n",
482 enum_smbacl4_modes
[params
->mode
].name
,
483 params
->do_chown
? "true" : "false",
484 enum_smbacl4_acedups
[params
->acedup
].name
));
489 static void smbacl4_dump_nfs4acl(int level
, SMB4ACL_T
*theacl
)
491 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
492 SMB_ACE4_INT_T
*aceint
;
494 DEBUG(level
, ("NFS4ACL: size=%d\n", aclint
->naces
));
496 for(aceint
= aclint
->first
; aceint
!=NULL
; aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
497 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
499 DEBUG(level
, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n",
501 ace
->aceFlags
, ace
->flags
,
508 * Find 2 NFS4 who-special ACE property (non-copy!!!)
509 * match nonzero if "special" and who is equal
510 * return ace if found matching; otherwise NULL
512 static SMB_ACE4PROP_T
*smbacl4_find_equal_special(
514 SMB_ACE4PROP_T
*aceNew
)
516 SMB_ACL4_INT_T
*aclint
= get_validated_aclint(theacl
);
517 SMB_ACE4_INT_T
*aceint
;
519 for(aceint
= aclint
->first
; aceint
!=NULL
; aceint
=(SMB_ACE4_INT_T
*)aceint
->next
) {
520 SMB_ACE4PROP_T
*ace
= &aceint
->prop
;
522 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
523 "new type:0x%x flags:0x%x aceFlags:0x%x\n",
524 ace
->aceType
, ace
->flags
, ace
->aceFlags
,
525 aceNew
->aceType
, aceNew
->flags
,aceNew
->aceFlags
));
527 if (ace
->flags
== aceNew
->flags
&&
528 ace
->aceType
==aceNew
->aceType
&&
529 ace
->aceFlags
==aceNew
->aceFlags
)
531 /* keep type safety; e.g. gid is an u.short */
532 if (ace
->flags
& SMB_ACE4_ID_SPECIAL
)
534 if (ace
->who
.special_id
==aceNew
->who
.special_id
)
537 if (ace
->aceFlags
& SMB_ACE4_IDENTIFIER_GROUP
)
539 if (ace
->who
.gid
==aceNew
->who
.gid
)
542 if (ace
->who
.uid
==aceNew
->who
.uid
)
552 static bool nfs4_map_sid(smbacl4_vfs_params
*params
, const struct dom_sid
*src
,
555 static struct db_context
*mapping_db
= NULL
;
558 if (mapping_db
== NULL
) {
559 const char *dbname
= lp_parm_const_string(
560 -1, SMBACL4_PARAM_TYPE_NAME
, "sidmap", NULL
);
562 if (dbname
== NULL
) {
563 DEBUG(10, ("%s:sidmap not defined\n",
564 SMBACL4_PARAM_TYPE_NAME
));
569 mapping_db
= db_open(NULL
, dbname
, 0, TDB_DEFAULT
,
573 if (mapping_db
== NULL
) {
574 DEBUG(1, ("could not open sidmap: %s\n",
580 if (mapping_db
->fetch(mapping_db
, NULL
,
581 string_term_tdb_data(sid_string_tos(src
)),
583 DEBUG(10, ("could not find mapping for SID %s\n",
584 sid_string_dbg(src
)));
588 if ((data
.dptr
== NULL
) || (data
.dsize
<= 0)
589 || (data
.dptr
[data
.dsize
-1] != '\0')) {
590 DEBUG(5, ("invalid mapping for SID %s\n",
591 sid_string_dbg(src
)));
592 TALLOC_FREE(data
.dptr
);
596 if (!string_to_sid(dst
, (char *)data
.dptr
)) {
597 DEBUG(1, ("invalid mapping %s for SID %s\n",
598 (char *)data
.dptr
, sid_string_dbg(src
)));
599 TALLOC_FREE(data
.dptr
);
603 TALLOC_FREE(data
.dptr
);
608 static bool smbacl4_fill_ace4(
610 const char *filename
,
611 smbacl4_vfs_params
*params
,
614 const struct security_ace
*ace_nt
, /* input */
615 SMB_ACE4PROP_T
*ace_v4
/* output */
618 DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt
->trustee
)));
620 memset(ace_v4
, 0, sizeof(SMB_ACE4PROP_T
));
621 ace_v4
->aceType
= ace_nt
->type
; /* only ACCESS|DENY supported right now */
622 ace_v4
->aceFlags
= map_windows_ace_flags_to_nfs4_ace_flags(ace_nt
->flags
);
623 ace_v4
->aceMask
= ace_nt
->access_mask
&
624 (SEC_STD_ALL
| SEC_FILE_ALL
);
626 se_map_generic(&ace_v4
->aceMask
, &file_generic_mapping
);
628 if (ace_v4
->aceFlags
!=ace_nt
->flags
)
629 DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n",
630 ace_v4
->aceFlags
, ace_nt
->flags
));
632 if (ace_v4
->aceMask
!=ace_nt
->access_mask
)
633 DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n",
634 ace_v4
->aceMask
, ace_nt
->access_mask
));
636 if (dom_sid_equal(&ace_nt
->trustee
, &global_sid_World
)) {
637 ace_v4
->who
.special_id
= SMB_ACE4_WHO_EVERYONE
;
638 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
640 const char *dom
, *name
;
641 enum lsa_SidType type
;
646 sid_copy(&sid
, &ace_nt
->trustee
);
648 if (!lookup_sid(mem_ctx
, &sid
, &dom
, &name
, &type
)) {
650 struct dom_sid mapped
;
652 if (!nfs4_map_sid(params
, &sid
, &mapped
)) {
653 DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s "
654 "unknown\n", filename
, sid_string_dbg(&sid
)));
659 DEBUG(2, ("nfs4_acls.c: file [%s]: mapped SID %s "
660 "to %s\n", filename
, sid_string_dbg(&sid
), sid_string_dbg(&mapped
)));
662 if (!lookup_sid(mem_ctx
, &mapped
, &dom
,
664 DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s "
665 "mapped from %s is unknown\n",
666 filename
, sid_string_dbg(&mapped
), sid_string_dbg(&sid
)));
671 sid_copy(&sid
, &mapped
);
674 if (type
== SID_NAME_USER
) {
675 if (!sid_to_uid(&sid
, &uid
)) {
676 DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
677 "convert %s to uid\n", filename
,
678 sid_string_dbg(&sid
)));
682 if (params
->mode
==e_special
&& uid
==ownerUID
) {
683 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
684 ace_v4
->who
.special_id
= SMB_ACE4_WHO_OWNER
;
686 ace_v4
->who
.uid
= uid
;
688 } else { /* else group? - TODO check it... */
689 if (!sid_to_gid(&sid
, &gid
)) {
690 DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
691 "convert %s to gid\n", filename
,
692 sid_string_dbg(&sid
)));
696 ace_v4
->aceFlags
|= SMB_ACE4_IDENTIFIER_GROUP
;
698 if (params
->mode
==e_special
&& gid
==ownerGID
) {
699 ace_v4
->flags
|= SMB_ACE4_ID_SPECIAL
;
700 ace_v4
->who
.special_id
= SMB_ACE4_WHO_GROUP
;
702 ace_v4
->who
.gid
= gid
;
707 return True
; /* OK */
710 static int smbacl4_MergeIgnoreReject(
711 enum smbacl4_acedup_enum acedup
,
712 SMB4ACL_T
*theacl
, /* may modify it */
713 SMB_ACE4PROP_T
*ace
, /* the "new" ACE */
719 SMB_ACE4PROP_T
*ace4found
= smbacl4_find_equal_special(theacl
, ace
);
724 case e_merge
: /* "merge" flags */
726 ace4found
->aceFlags
|= ace
->aceFlags
;
727 ace4found
->aceMask
|= ace
->aceMask
;
729 case e_ignore
: /* leave out this record */
732 case e_reject
: /* do an error */
733 DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i
));
734 errno
= EINVAL
; /* SHOULD be set on any _real_ error */
744 static SMB4ACL_T
*smbacl4_win2nfs4(
745 const char *filename
,
746 const struct security_acl
*dacl
,
747 smbacl4_vfs_params
*pparams
,
754 TALLOC_CTX
*mem_ctx
= talloc_tos();
756 DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
758 theacl
= smb_create_smb4acl();
762 for(i
=0; i
<dacl
->num_aces
; i
++) {
763 SMB_ACE4PROP_T ace_v4
;
764 bool addNewACE
= True
;
766 if (!smbacl4_fill_ace4(mem_ctx
, filename
, pparams
,
768 dacl
->aces
+ i
, &ace_v4
)) {
769 DEBUG(3, ("Could not fill ace for file %s, SID %s\n",
771 sid_string_dbg(&((dacl
->aces
+i
)->trustee
))));
775 if (pparams
->acedup
!=e_dontcare
) {
776 if (smbacl4_MergeIgnoreReject(pparams
->acedup
, theacl
,
777 &ace_v4
, &addNewACE
, i
))
782 smb_add_ace4(theacl
, &ace_v4
);
788 NTSTATUS
smb_set_nt_acl_nfs4(files_struct
*fsp
,
789 uint32 security_info_sent
,
790 const struct security_descriptor
*psd
,
791 set_nfs4acl_native_fn_t set_nfs4_native
)
793 smbacl4_vfs_params params
;
794 SMB4ACL_T
*theacl
= NULL
;
797 SMB_STRUCT_STAT sbuf
;
798 bool set_acl_as_root
= false;
799 uid_t newUID
= (uid_t
)-1;
800 gid_t newGID
= (gid_t
)-1;
803 DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp
)));
805 if ((security_info_sent
& (SECINFO_DACL
|
806 SECINFO_GROUP
| SECINFO_OWNER
)) == 0)
808 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
809 security_info_sent
));
810 return NT_STATUS_OK
; /* won't show error - later to be refined... */
813 /* Special behaviours */
814 if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME
, fsp
, ¶ms
))
815 return NT_STATUS_NO_MEMORY
;
817 if (smbacl4_fGetFileOwner(fsp
, &sbuf
))
818 return map_nt_error_from_unix(errno
);
820 if (params
.do_chown
) {
821 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
822 NTSTATUS status
= unpack_nt_owners(fsp
->conn
, &newUID
, &newGID
, security_info_sent
, psd
);
823 if (!NT_STATUS_IS_OK(status
)) {
824 DEBUG(8, ("unpack_nt_owners failed"));
827 if (((newUID
!= (uid_t
)-1) && (sbuf
.st_ex_uid
!= newUID
)) ||
828 ((newGID
!= (gid_t
)-1) && (sbuf
.st_ex_gid
!= newGID
))) {
830 status
= try_chown(fsp
, newUID
, newGID
);
831 if (!NT_STATUS_IS_OK(status
)) {
832 DEBUG(3,("chown %s, %u, %u failed. Error = "
833 "%s.\n", fsp_str_dbg(fsp
),
834 (unsigned int)newUID
,
835 (unsigned int)newGID
,
840 DEBUG(10,("chown %s, %u, %u succeeded.\n",
841 fsp_str_dbg(fsp
), (unsigned int)newUID
,
842 (unsigned int)newGID
));
843 if (smbacl4_GetFileOwner(fsp
->conn
,
844 fsp
->fsp_name
->base_name
,
846 return map_nt_error_from_unix(errno
);
848 /* If we successfully chowned, we know we must
849 * be able to set the acl, so do it as root.
851 set_acl_as_root
= true;
855 if (!(security_info_sent
& SECINFO_DACL
) || psd
->dacl
==NULL
) {
856 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent
));
860 theacl
= smbacl4_win2nfs4(fsp
->fsp_name
->base_name
, psd
->dacl
, ¶ms
,
861 sbuf
.st_ex_uid
, sbuf
.st_ex_gid
);
863 return map_nt_error_from_unix(errno
);
865 smbacl4_dump_nfs4acl(10, theacl
);
867 if (set_acl_as_root
) {
870 result
= set_nfs4_native(fsp
, theacl
);
872 if (set_acl_as_root
) {
877 DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno
)));
878 return map_nt_error_from_unix(errno
);
881 DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));