diff options
Diffstat (limited to 'source3/modules/nfs4_acls.c')
-rw-r--r-- | source3/modules/nfs4_acls.c | 277 |
1 files changed, 214 insertions, 63 deletions
diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index edcc52261c..0c3d010dcd 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -20,6 +20,9 @@ #include "includes.h" #include "nfs4_acls.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ACLS + #define SMBACL4_PARAM_TYPE_NAME "nfs4" #define SMB_ACE4_INT_MAGIC 0x76F8A967 @@ -161,24 +164,35 @@ uint32 smb_get_naces(SMB4ACL_T *acl) return aclint->naces; } -static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) +static int smbacl4_GetFileOwner(struct connection_struct *conn, + const char *filename, + SMB_STRUCT_STAT *psbuf) { memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); + + /* Get the stat struct for the owner info. */ + if (SMB_VFS_STAT(conn, filename, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", + strerror(errno))); + return -1; + } + + return 0; +} + +static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) +{ + memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); + if (fsp->is_directory || fsp->fh->fd == -1) { - /* Get the stat struct for the owner info. */ - if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", - strerror(errno))); - return -1; - } - } else { - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", - strerror(errno))); - return -1; - } + return smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, psbuf); + } + if (SMB_VFS_FSTAT(fsp, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", + strerror(errno))); + return -1; } return 0; @@ -257,30 +271,24 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */ return True; } -NTSTATUS smb_get_nt_acl_nfs4(files_struct *fsp, +static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf, uint32 security_info, SEC_DESC **ppdesc, SMB4ACL_T *acl) { int good_aces = 0; - SMB_STRUCT_STAT sbuf; DOM_SID sid_owner, sid_group; size_t sd_size = 0; SEC_ACE *nt_ace_list = NULL; SEC_ACL *psa = NULL; TALLOC_CTX *mem_ctx = talloc_tos(); - DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); - if (acl==NULL || smb_get_naces(acl)==0) return NT_STATUS_ACCESS_DENIED; /* special because we * shouldn't alloc 0 for * win */ - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return map_nt_error_from_unix(errno); - - uid_to_sid(&sid_owner, sbuf.st_uid); - gid_to_sid(&sid_group, sbuf.st_gid); + uid_to_sid(&sid_owner, sbuf->st_uid); + gid_to_sid(&sid_group, sbuf->st_gid); if (smbacl4_nfs42win(mem_ctx, acl, &sid_owner, &sid_group, &nt_ace_list, &good_aces)==False) { DEBUG(8,("smbacl4_nfs42win failed\n")); @@ -303,12 +311,43 @@ NTSTATUS smb_get_nt_acl_nfs4(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", - sec_desc_size(*ppdesc))); + DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n", + ndr_size_security_descriptor(*ppdesc, 0))); return NT_STATUS_OK; } +NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp, + uint32 security_info, + SEC_DESC **ppdesc, SMB4ACL_T *acl) +{ + SMB_STRUCT_STAT sbuf; + + DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if (smbacl4_fGetFileOwner(fsp, &sbuf)) { + return map_nt_error_from_unix(errno); + } + + return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl); +} + +NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn, + const char *name, + uint32 security_info, + SEC_DESC **ppdesc, SMB4ACL_T *acl) +{ + SMB_STRUCT_STAT sbuf; + + DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name)); + + if (smbacl4_GetFileOwner(conn, name, &sbuf)) { + return map_nt_error_from_unix(errno); + } + + return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl); +} + enum smbacl4_mode_enum {e_simple=0, e_special=1}; enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; @@ -316,6 +355,7 @@ typedef struct _smbacl4_vfs_params { enum smbacl4_mode_enum mode; bool do_chown; enum smbacl4_acedup_enum acedup; + struct db_context *sid_mapping_table; } smbacl4_vfs_params; /* @@ -415,8 +455,65 @@ static SMB_ACE4PROP_T *smbacl4_find_equal_special( return NULL; } -static int smbacl4_fill_ace4( +static bool nfs4_map_sid(smbacl4_vfs_params *params, const DOM_SID *src, + DOM_SID *dst) +{ + static struct db_context *mapping_db = NULL; + TDB_DATA data; + + if (mapping_db == NULL) { + const char *dbname = lp_parm_const_string( + -1, SMBACL4_PARAM_TYPE_NAME, "sidmap", NULL); + + if (dbname == NULL) { + DEBUG(10, ("%s:sidmap not defined\n", + SMBACL4_PARAM_TYPE_NAME)); + return False; + } + + become_root(); + mapping_db = db_open(NULL, dbname, 0, TDB_DEFAULT, + O_RDONLY, 0600); + unbecome_root(); + + if (mapping_db == NULL) { + DEBUG(1, ("could not open sidmap: %s\n", + strerror(errno))); + return False; + } + } + + if (mapping_db->fetch(mapping_db, NULL, + string_term_tdb_data(sid_string_tos(src)), + &data) == -1) { + DEBUG(10, ("could not find mapping for SID %s\n", + sid_string_dbg(src))); + return False; + } + + if ((data.dptr == NULL) || (data.dsize <= 0) + || (data.dptr[data.dsize-1] != '\0')) { + DEBUG(5, ("invalid mapping for SID %s\n", + sid_string_dbg(src))); + TALLOC_FREE(data.dptr); + return False; + } + + if (!string_to_sid(dst, (char *)data.dptr)) { + DEBUG(1, ("invalid mapping %s for SID %s\n", + (char *)data.dptr, sid_string_dbg(src))); + TALLOC_FREE(data.dptr); + return False; + } + + TALLOC_FREE(data.dptr); + + return True; +} + +static bool smbacl4_fill_ace4( TALLOC_CTX *mem_ctx, + const char *filename, smbacl4_vfs_params *params, uid_t ownerUID, gid_t ownerGID, @@ -424,11 +521,6 @@ static int smbacl4_fill_ace4( SMB_ACE4PROP_T *ace_v4 /* output */ ) { - const char *dom, *name; - enum lsa_SidType type; - uid_t uid; - gid_t gid; - DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee))); memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); @@ -449,18 +541,46 @@ static int smbacl4_fill_ace4( ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; ace_v4->flags |= SMB_ACE4_ID_SPECIAL; } else { - if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { - DEBUG(8, ("Could not find %s' type\n", - sid_string_dbg(&ace_nt->trustee))); - errno = EINVAL; - return -1; + const char *dom, *name; + enum lsa_SidType type; + uid_t uid; + gid_t gid; + DOM_SID sid; + + sid_copy(&sid, &ace_nt->trustee); + + if (!lookup_sid(mem_ctx, &sid, &dom, &name, &type)) { + + DOM_SID mapped; + + if (!nfs4_map_sid(params, &sid, &mapped)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s " + "unknown\n", filename, sid_string_dbg(&sid))); + errno = EINVAL; + return False; + } + + DEBUG(2, ("nfs4_acls.c: file [%s]: mapped SID %s " + "to %s\n", filename, sid_string_dbg(&sid), sid_string_dbg(&mapped))); + + if (!lookup_sid(mem_ctx, &mapped, &dom, + &name, &type)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s " + "mapped from %s is unknown\n", + filename, sid_string_dbg(&mapped), sid_string_dbg(&sid))); + errno = EINVAL; + return False; + } + + sid_copy(&sid, &mapped); } - + if (type == SID_NAME_USER) { - if (!sid_to_uid(&ace_nt->trustee, &uid)) { - DEBUG(2, ("Could not convert %s to uid\n", - sid_string_dbg(&ace_nt->trustee))); - return -1; + if (!sid_to_uid(&sid, &uid)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: could not " + "convert %s to uid\n", filename, + sid_string_dbg(&sid))); + return False; } if (params->mode==e_special && uid==ownerUID) { @@ -470,11 +590,13 @@ static int smbacl4_fill_ace4( ace_v4->who.uid = uid; } } else { /* else group? - TODO check it... */ - if (!sid_to_gid(&ace_nt->trustee, &gid)) { - DEBUG(2, ("Could not convert %s to gid\n", - sid_string_dbg(&ace_nt->trustee))); - return -1; + if (!sid_to_gid(&sid, &gid)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: could not " + "convert %s to gid\n", filename, + sid_string_dbg(&sid))); + return False; } + ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; if (params->mode==e_special && gid==ownerGID) { @@ -486,7 +608,7 @@ static int smbacl4_fill_ace4( } } - return 0; /* OK */ + return True; /* OK */ } static int smbacl4_MergeIgnoreReject( @@ -524,6 +646,7 @@ static int smbacl4_MergeIgnoreReject( } static SMB4ACL_T *smbacl4_win2nfs4( + const char *filename, SEC_ACL *dacl, smbacl4_vfs_params *pparams, uid_t ownerUID, @@ -544,9 +667,14 @@ static SMB4ACL_T *smbacl4_win2nfs4( SMB_ACE4PROP_T ace_v4; bool addNewACE = True; - if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, - dacl->aces + i, &ace_v4)) - return NULL; + if (!smbacl4_fill_ace4(mem_ctx, filename, pparams, + ownerUID, ownerGID, + dacl->aces + i, &ace_v4)) { + DEBUG(3, ("Could not fill ace for file %s, SID %s\n", + filename, + sid_string_dbg(&((dacl->aces+i)->trustee)))); + continue; + } if (pparams->acedup!=e_dontcare) { if (smbacl4_MergeIgnoreReject(pparams->acedup, acl, @@ -571,6 +699,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, bool result; SMB_STRUCT_STAT sbuf; + bool need_chown = False; uid_t newUID = (uid_t)-1; gid_t newGID = (gid_t)-1; @@ -588,7 +717,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) return NT_STATUS_NO_MEMORY; - if (smbacl4_GetFileOwner(fsp, &sbuf)) + if (smbacl4_fGetFileOwner(fsp, &sbuf)) return map_nt_error_from_unix(errno); if (params.do_chown) { @@ -599,25 +728,33 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, return status; } if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { - if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); - if (errno == EPERM) { - return NT_STATUS_INVALID_OWNER; + ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + need_chown = True; + } + if (need_chown) { + if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { + if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + strerror(errno))); + return map_nt_error_from_unix(errno); } - return map_nt_error_from_unix(errno); + + DEBUG(10,("chown %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, &sbuf)) + return map_nt_error_from_unix(errno); + need_chown = False; + } else { /* chown is needed, but _after_ changing acl */ + sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ + sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ } - DEBUG(10,("chown %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return map_nt_error_from_unix(errno); } } if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL) { - acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); + acl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); if (!acl) return map_nt_error_from_unix(errno); @@ -632,6 +769,20 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, } else DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); + /* Any chown pending? */ + if (need_chown) { + DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + strerror(errno))); + return map_nt_error_from_unix(errno); + } + DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + } + DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); return NT_STATUS_OK; } |