#include "passdb/lookup_sid.h"
#include "auth.h"
#include "../librpc/gen_ndr/idmap.h"
+#include "../librpc/gen_ndr/ndr_smb_acl.h"
#include "lib/param/loadparm.h"
extern const struct generic_mapping file_generic_mapping;
};
/************************************************************************
- Return a uint32 of the pai_entry principal.
+ Return a uint32_t of the pai_entry principal.
************************************************************************/
static uint32_t get_pai_entry_val(struct pai_entry *paie)
}
/************************************************************************
- Return a uint32 of the entry principal.
+ Return a uint32_t of the entry principal.
************************************************************************/
static uint32_t get_entry_val(canon_ace *ace_entry)
ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, store_size, 0);
} else {
- ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name,
+ ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name,
SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, store_size, 0);
}
static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size)
{
- uint16 num_entries;
- uint16 num_def_entries;
+ uint16_t num_entries;
+ uint16_t num_def_entries;
if (pai_buf_data_size < PAI_V1_ENTRIES_BASE) {
/* Corrupted - too small. */
static bool check_pai_ok_v2(const char *pai_buf, size_t pai_buf_data_size)
{
- uint16 num_entries;
- uint16 num_def_entries;
+ uint16_t num_entries;
+ uint16_t num_def_entries;
if (pai_buf_data_size < PAI_V2_ENTRIES_BASE) {
/* Corrupted - too small. */
const char *entry_offset,
bool def_entry)
{
- int i;
+ unsigned int i;
for (i = 0; i < paiv->num_entries; i++) {
struct pai_entry *paie = talloc(talloc_tos(), struct pai_entry);
pai_buf, pai_buf_size);
} else {
ret = SMB_VFS_GETXATTR(fsp->conn,
- fsp->fsp_name->base_name,
+ fsp->fsp_name,
SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, pai_buf_size);
}
************************************************************************/
static struct pai_val *load_inherited_info(const struct connection_struct *conn,
- const char *fname)
+ const struct smb_filename *smb_fname)
{
char *pai_buf;
size_t pai_buf_size = 1024;
}
do {
- ret = SMB_VFS_GETXATTR(conn, fname,
+ ret = SMB_VFS_GETXATTR(conn, smb_fname,
SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, pai_buf_size);
}
} while (ret == -1);
- DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fname));
+ DEBUG(10,("load_inherited_info: ret = %lu for file %s\n",
+ (unsigned long)ret, smb_fname->base_name));
if (ret == -1) {
/* No attribute or not supported. */
if (paiv) {
DEBUG(10,("load_inherited_info: ACL type 0x%x for file %s\n",
(unsigned int)paiv->sd_type,
- fname));
+ smb_fname->base_name));
}
TALLOC_FREE(pai_buf);
dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
dbgtext( "SID = %s ", sid_string_dbg(&pace->trustee));
if (pace->owner_type == UID_ACE) {
- const char *u_name = uidtoname(pace->unix_ug.id);
- dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.id, u_name );
+ dbgtext( "uid %u ", (unsigned int)pace->unix_ug.id);
} else if (pace->owner_type == GID_ACE) {
- char *g_name = gidtoname(pace->unix_ug.id);
- dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.id, g_name );
+ dbgtext( "gid %u ", (unsigned int)pace->unix_ug.id);
} else
dbgtext( "other ");
switch (pace->type) {
Function to create owner and group SIDs from a SMB_STRUCT_STAT.
****************************************************************************/
-void create_file_sids(const SMB_STRUCT_STAT *psbuf, struct dom_sid *powner_sid, struct dom_sid *pgroup_sid)
+static void create_file_sids(const SMB_STRUCT_STAT *psbuf,
+ struct dom_sid *powner_sid,
+ struct dom_sid *pgroup_sid)
{
uid_to_sid( powner_sid, psbuf->st_ex_uid );
gid_to_sid( pgroup_sid, psbuf->st_ex_gid );
*pp_list_head = l_head;
}
-/****************************************************************************
- Check if we need to return NT4.x compatible ACL entries.
-****************************************************************************/
-
-bool nt4_compatible_acls(void)
-{
- int compat = lp_acl_compatibility();
-
- if (compat == ACL_COMPAT_AUTO) {
- enum remote_arch_types ra_type = get_remote_arch();
-
- /* Automatically adapt to client */
- return (ra_type <= RA_WINNT);
- } else
- return (compat == ACL_COMPAT_WINNT);
-}
-
-
/****************************************************************************
Map canon_ace perms to permission bits NT.
The attr element is not used here - we only process deny entries on set,
* to be changed in the future.
*/
- if (nt4_compatible_acls())
- nt_mask = UNIX_ACCESS_NONE;
- else
- nt_mask = 0;
+ nt_mask = 0;
} else {
if (directory_ace) {
nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA)
#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
-static mode_t map_nt_perms( uint32 *mask, int type)
+static mode_t map_nt_perms( uint32_t *mask, int type)
{
mode_t mode = 0;
NTSTATUS unpack_nt_owners(struct connection_struct *conn,
uid_t *puser, gid_t *pgrp,
- uint32 security_info_sent, const struct
+ uint32_t security_info_sent, const struct
security_descriptor *psd)
{
- struct dom_sid owner_sid;
- struct dom_sid grp_sid;
-
*puser = (uid_t)-1;
*pgrp = (gid_t)-1;
* Validate the owner and group SID's.
*/
- memset(&owner_sid, '\0', sizeof(owner_sid));
- memset(&grp_sid, '\0', sizeof(grp_sid));
-
DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));
/*
*/
if (security_info_sent & SECINFO_OWNER) {
- sid_copy(&owner_sid, psd->owner_sid);
- if (!sid_to_uid(&owner_sid, puser)) {
+ if (!sid_to_uid(psd->owner_sid, puser)) {
if (lp_force_unknown_acl_user(SNUM(conn))) {
/* this allows take ownership to work
* reasonably */
} else {
DEBUG(3,("unpack_nt_owners: unable to validate"
" owner sid for %s\n",
- sid_string_dbg(&owner_sid)));
+ sid_string_dbg(psd->owner_sid)));
return NT_STATUS_INVALID_OWNER;
}
}
*/
if (security_info_sent & SECINFO_GROUP) {
- sid_copy(&grp_sid, psd->group_sid);
- if (!sid_to_gid( &grp_sid, pgrp)) {
+ if (!sid_to_gid(psd->group_sid, pgrp)) {
if (lp_force_unknown_acl_user(SNUM(conn))) {
/* this allows take group ownership to work
* reasonably */
return NT_STATUS_OK;
}
-/****************************************************************************
- Ensure the enforced permissions for this share apply.
-****************************************************************************/
-static void apply_default_perms(const struct share_params *params,
- const bool is_directory, canon_ace *pace,
- mode_t type)
+static void trim_ace_perms(canon_ace *pace)
{
- mode_t and_bits = (mode_t)0;
- mode_t or_bits = (mode_t)0;
-
- /* Get the initial bits to apply. */
+ pace->perms = pace->perms & (S_IXUSR|S_IWUSR|S_IRUSR);
+}
+static void ensure_minimal_owner_ace_perms(const bool is_directory,
+ canon_ace *pace)
+{
+ pace->perms |= S_IRUSR;
if (is_directory) {
- and_bits = lp_dir_mask(params->service);
- or_bits = lp_force_dir_mode(params->service);
- } else {
- and_bits = lp_create_mask(params->service);
- or_bits = lp_force_create_mode(params->service);
+ pace->perms |= (S_IWUSR|S_IXUSR);
}
-
- /* Now bounce them into the S_USR space. */
- switch(type) {
- case S_IRUSR:
- /* Ensure owner has read access. */
- pace->perms |= S_IRUSR;
- if (is_directory)
- pace->perms |= (S_IWUSR|S_IXUSR);
- and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);
- or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);
- break;
- case S_IRGRP:
- and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP);
- or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP);
- break;
- case S_IROTH:
- and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH);
- or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH);
- break;
- }
-
- pace->perms = ((pace->perms & and_bits)|or_bits);
}
/****************************************************************************
bool got_duplicate_group = false;
for (pace = *pp_ace; pace; pace = pace->next) {
+ trim_ace_perms(pace);
if (pace->type == SMB_ACL_USER_OBJ) {
-
- if (!is_default_acl) {
- apply_default_perms(params, is_directory, pace, S_IRUSR);
- }
+ ensure_minimal_owner_ace_perms(is_directory, pace);
pace_user = pace;
-
} else if (pace->type == SMB_ACL_GROUP_OBJ) {
-
- /*
- * Ensure create mask/force create mode is respected on set.
- */
-
- if (!is_default_acl) {
- apply_default_perms(params, is_directory, pace, S_IRGRP);
- }
pace_group = pace;
-
} else if (pace->type == SMB_ACL_OTHER) {
-
- /*
- * Ensure create mask/force create mode is respected on set.
- */
-
- if (!is_default_acl) {
- apply_default_perms(params, is_directory, pace, S_IROTH);
- }
pace_other = pace;
-
- } else if (pace->type == SMB_ACL_USER || pace->type == SMB_ACL_GROUP) {
-
- /*
- * Ensure create mask/force create mode is respected on set.
- */
-
- if (!is_default_acl) {
- apply_default_perms(params, is_directory, pace, S_IRGRP);
- }
}
}
pace->perms = pace_other->perms;
}
- if (!is_default_acl) {
- apply_default_perms(params, is_directory, pace, S_IRUSR);
- }
+ /*
+ * Ensure we have default parameters for the
+ * user (owner) even on default ACLs.
+ */
+ ensure_minimal_owner_ace_perms(is_directory, pace);
DLIST_ADD(*pp_ace, pace);
pace_user = pace;
} else {
pace->perms = 0;
}
- if (!is_default_acl) {
- apply_default_perms(params, is_directory, pace, S_IRGRP);
- }
DLIST_ADD(*pp_ace, pace);
pace_group = pace;
pace->trustee = global_sid_World;
pace->attr = ALLOW_ACE;
pace->perms = 0;
- if (!is_default_acl) {
- apply_default_perms(params, is_directory, pace, S_IROTH);
- }
DLIST_ADD(*pp_ace, pace);
pace_other = pace;
/* Already got one. */
got_duplicate_user = true;
} else if (pace->type == SMB_ACL_GROUP &&
- pace->unix_ug.id == pace_user->unix_ug.id) {
+ pace->unix_ug.id == pace_group->unix_ug.id) {
/* Already got one. */
got_duplicate_group = true;
} else if ((pace->type == SMB_ACL_GROUP)
(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
canon_ace *current_dir_ace = current_ace;
- DLIST_ADD_END(*dir_ace, current_ace, canon_ace *);
+ DLIST_ADD_END(*dir_ace, current_ace);
/*
* Note if this was an allow ace. We can't process
*/
if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
- DLIST_ADD_END(*file_ace, current_ace, canon_ace *);
+ DLIST_ADD_END(*file_ace, current_ace);
/*
* Note if this was an allow ace. We can't process
if (current_ace->attr == ALLOW_ACE)
*got_file_allow = True;
- if ((current_ace->attr == DENY_ACE) && got_file_allow) {
+ if ((current_ace->attr == DENY_ACE) && *got_file_allow) {
DEBUG(0,("add_current_ace_to_acl: malformed "
"ACL in file ACL ! Deny entry after "
"Allow entry. Failing to set on file "
canon_ace *current_ace = NULL;
bool got_dir_allow = False;
bool got_file_allow = False;
- int i, j;
+ uint32_t i, j;
*ppfile_ace = NULL;
*ppdir_ace = NULL;
DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
return False;
}
-
- if (nt4_compatible_acls()) {
- /*
- * The security mask may be UNIX_ACCESS_NONE which should map into
- * no permissions (we overload the WRITE_OWNER bit for this) or it
- * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this
- * to be so. Any other bits override the UNIX_ACCESS_NONE bit.
- */
-
- /*
- * Convert GENERIC bits to specific bits.
- */
-
- se_map_generic(&psa->access_mask, &file_generic_mapping);
-
- psa->access_mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
-
- if(psa->access_mask != UNIX_ACCESS_NONE)
- psa->access_mask &= ~UNIX_ACCESS_NONE;
- }
}
/*
}
if (unixid.type == ID_TYPE_BOTH) {
- /* If it's the owning user, this is a
- * user_obj, not a user. This way, we
- * get a valid ACL for groups that own
- * files, without putting user ACL
- * entries in for groups otherwise */
- if (unixid.id == pst->st_ex_uid) {
- current_ace->owner_type = UID_ACE;
- current_ace->unix_ug.type = ID_TYPE_UID;
- current_ace->unix_ug.id = unixid.id;
- current_ace->type = SMB_ACL_USER_OBJ;
-
- /* Add the user object to the posix ACL,
- and proceed to the group mapping
- below. This handles the talloc_free
- of current_ace if not added for some
- reason */
- if (!add_current_ace_to_acl(fsp,
- psa,
- &file_ace,
- &dir_ace,
- &got_file_allow,
- &got_dir_allow,
- &all_aces_are_inherit_only,
- current_ace)) {
- free_canon_ace_list(file_ace);
- free_canon_ace_list(dir_ace);
- return false;
- }
-
- if ((current_ace = talloc(talloc_tos(),
- canon_ace)) == NULL) {
- free_canon_ace_list(file_ace);
- free_canon_ace_list(dir_ace);
- DEBUG(0,("create_canon_ace_lists: "
- "malloc fail.\n"));
- return False;
- }
+ /*
+ * We must add both a user and group
+ * entry POSIX_ACL.
+ * This is due to the fact that in POSIX
+ * user entries are more specific than
+ * groups.
+ */
+ current_ace->owner_type = UID_ACE;
+ current_ace->unix_ug.type = ID_TYPE_UID;
+ current_ace->unix_ug.id = unixid.id;
+ current_ace->type =
+ (unixid.id == pst->st_ex_uid) ?
+ SMB_ACL_USER_OBJ :
+ SMB_ACL_USER;
+
+ /* Add the user object to the posix ACL,
+ and proceed to the group mapping
+ below. This handles the talloc_free
+ of current_ace if not added for some
+ reason */
+ if (!add_current_ace_to_acl(fsp,
+ psa,
+ &file_ace,
+ &dir_ace,
+ &got_file_allow,
+ &got_dir_allow,
+ &all_aces_are_inherit_only,
+ current_ace)) {
+ free_canon_ace_list(file_ace);
+ free_canon_ace_list(dir_ace);
+ return false;
+ }
- ZERO_STRUCTP(current_ace);
+ if ((current_ace = talloc(talloc_tos(),
+ canon_ace)) == NULL) {
+ free_canon_ace_list(file_ace);
+ free_canon_ace_list(dir_ace);
+ DEBUG(0,("create_canon_ace_lists: "
+ "malloc fail.\n"));
+ return False;
}
+ ZERO_STRUCTP(current_ace);
+
sid_copy(¤t_ace->trustee, &psa->trustee);
current_ace->unix_ug.type = ID_TYPE_GID;
curr_ace->attr = ALLOW_ACE;
curr_ace->perms = (mode_t)0;
- DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
+ DLIST_DEMOTE(ace_list, curr_ace);
continue;
}
curr_ace->attr = ALLOW_ACE;
curr_ace->perms = (new_perms & ~curr_ace->perms);
- DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
+ DLIST_DEMOTE(ace_list, curr_ace);
}
/* Pass 3 above - deal with deny group entries. */
curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
else
curr_ace->perms = (mode_t)0;
- DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
+ DLIST_DEMOTE(ace_list, curr_ace);
}
/* Doing this fourth pass allows Windows semantics to be layered
struct dom_sid *pfile_grp_sid,
canon_ace **ppfile_ace,
canon_ace **ppdir_ace,
- uint32 security_info_sent,
+ uint32_t security_info_sent,
const struct security_descriptor *psd)
{
canon_ace *file_ace = NULL;
* Now go through the DACL and create the canon_ace lists.
*/
- if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid,
- &file_ace, &dir_ace, psd->dacl))
+ if (!create_canon_ace_lists(fsp, pst, pfile_owner_sid, pfile_grp_sid,
+ &file_ace, &dir_ace, psd->dacl)) {
return False;
+ }
if ((file_ace == NULL) && (dir_ace == NULL)) {
/* W2K traverse DACL set - ignore. */
}
if (other_ace) {
- DLIST_DEMOTE(l_head, other_ace, canon_ace *);
+ DLIST_DEMOTE(l_head, other_ace);
}
/* We have probably changed the head of the list. */
entry_id = SMB_ACL_NEXT_ENTRY;
- /* Is this a MASK entry ? */
if (sys_acl_get_tag_type(entry, &tagtype) == -1)
continue;
if ((ace = talloc(talloc_tos(), canon_ace)) == NULL)
goto fail;
- ZERO_STRUCTP(ace);
- ace->type = tagtype;
- ace->perms = convert_permset_to_mode_t(permset);
- ace->attr = ALLOW_ACE;
- ace->trustee = sid;
- ace->unix_ug = unix_ug;
- ace->owner_type = owner_type;
+ *ace = (canon_ace) {
+ .type = tagtype,
+ .perms = convert_permset_to_mode_t(permset),
+ .attr = ALLOW_ACE,
+ .trustee = sid,
+ .unix_ug = unix_ug,
+ .owner_type = owner_type
+ };
ace->ace_flags = get_pai_flags(pal, ace, is_default_acl);
DLIST_ADD(l_head, ace);
bool current_user_in_group(connection_struct *conn, gid_t gid)
{
- int i;
+ uint32_t i;
const struct security_unix_token *utok = get_current_utok(conn);
for (i = 0; i < utok->ngroups; i++) {
*/
if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
- if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name->base_name,
+ if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name,
the_acl_type, the_acl) == -1) {
/*
* Some systems allow all the above calls and only fail with no ACL support
become_root();
sret = SMB_VFS_SYS_ACL_SET_FILE(conn,
- fsp->fsp_name->base_name, the_acl_type,
+ fsp->fsp_name, the_acl_type,
the_acl);
unbecome_root();
if (sret == 0) {
return ret;
}
-/****************************************************************************
- Find a particular canon_ace entry.
-****************************************************************************/
-
-static struct canon_ace *canon_ace_entry_for(struct canon_ace *list, SMB_ACL_TAG_T type, struct unixid *id)
-{
- while (list) {
- if (list->type == type && ((type != SMB_ACL_USER && type != SMB_ACL_GROUP) ||
- (type == SMB_ACL_USER && id && id->id == list->unix_ug.id) ||
- (type == SMB_ACL_GROUP && id && id->id == list->unix_ug.id)))
- break;
- list = list->next;
- }
- return list;
-}
-
/****************************************************************************
****************************************************************************/
static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms)
{
- int snum = SNUM(fsp->conn);
size_t ace_count = count_canon_ace_list(file_ace_list);
canon_ace *ace_p;
canon_ace *owner_ace = NULL;
canon_ace *group_ace = NULL;
canon_ace *other_ace = NULL;
- mode_t and_bits;
- mode_t or_bits;
- if (ace_count != 3) {
+ if (ace_count > 5) {
DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE "
"entries for file %s to convert to posix perms.\n",
fsp_str_dbg(fsp)));
return False;
}
+ /*
+ * Ensure all ACE entries are owner, group or other.
+ * We can't set if there are any other SIDs.
+ */
+ for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
+ if (ace_p == owner_ace || ace_p == group_ace ||
+ ace_p == other_ace) {
+ continue;
+ }
+ if (ace_p->owner_type == UID_ACE) {
+ if (ace_p->unix_ug.id != owner_ace->unix_ug.id) {
+ DEBUG(3,("Invalid uid %u in ACE for file %s.\n",
+ (unsigned int)ace_p->unix_ug.id,
+ fsp_str_dbg(fsp)));
+ return false;
+ }
+ } else if (ace_p->owner_type == GID_ACE) {
+ if (ace_p->unix_ug.id != group_ace->unix_ug.id) {
+ DEBUG(3,("Invalid gid %u in ACE for file %s.\n",
+ (unsigned int)ace_p->unix_ug.id,
+ fsp_str_dbg(fsp)));
+ return false;
+ }
+ } else {
+ /*
+ * There should be no duplicate WORLD_ACE entries.
+ */
+
+ DEBUG(3,("Invalid type %u, uid %u in "
+ "ACE for file %s.\n",
+ (unsigned int)ace_p->owner_type,
+ (unsigned int)ace_p->unix_ug.id,
+ fsp_str_dbg(fsp)));
+ return false;
+ }
+ }
+
*posix_perms = (mode_t)0;
*posix_perms |= owner_ace->perms;
if (fsp->is_directory)
*posix_perms |= (S_IWUSR|S_IXUSR);
- /* If requested apply the masks. */
-
- /* Get the initial bits to apply. */
-
- if (fsp->is_directory) {
- and_bits = lp_dir_mask(snum);
- or_bits = lp_force_dir_mode(snum);
- } else {
- and_bits = lp_create_mask(snum);
- or_bits = lp_force_create_mode(snum);
- }
-
- *posix_perms = (((*posix_perms) & and_bits)|or_bits);
-
DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o "
"to perm=0%o for file %s.\n", (int)owner_ace->perms,
(int)group_ace->perms, (int)other_ace->perms,
for (i = 0; i < num_aces; i++) {
for (j = i+1; j < num_aces; j++) {
- uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
- uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
+ uint32_t i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
+ uint32_t j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
bool i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
bool j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
const struct dom_sid *sid, enum security_ace_type type,
uint32_t mask, uint8_t flags)
{
- int i;
+ size_t i;
/* first search for a duplicate */
for (i = 0; i < *num_aces; i++) {
if (i < *num_aces) { /* found */
nt_ace_list[i].type = type;
nt_ace_list[i].access_mask = mask;
- DEBUG(10, ("Replacing ACE %d with SID %s and flags %02x\n",
+ DEBUG(10, ("Replacing ACE %zu with SID %s and flags %02x\n",
i, sid_string_dbg(sid), flags));
return;
}
size_t num_profile_acls = 0;
struct dom_sid orig_owner_sid;
struct security_descriptor *psd = NULL;
- int i;
/*
* Get the owner, group and world SIDs.
num_profile_acls = 3;
}
- if ((security_info & SECINFO_DACL) && !(security_info & SECINFO_PROTECTED_DACL)) {
+ if (security_info & SECINFO_DACL) {
/*
* In the optimum case Creator Owner and Creator Group would be used for
* would lead to usability problems under Windows: The Creator entries
* are only available in browse lists of directories and not for files;
* additionally the identity of the owning group couldn't be determined.
- * We therefore use those identities only for Default ACLs.
+ * We therefore use those identities only for Default ACLs.
*/
/* Create the canon_ace lists. */
SMB_ACL_TYPE_ACCESS);
/* We must have *some* ACLS. */
-
+
if (count_canon_ace_list(file_ace) == 0) {
DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", name));
goto done;
canon_ace *ace;
enum security_ace_type nt_acl_type;
- if (nt4_compatible_acls() && dir_ace) {
- /*
- * NT 4 chokes if an ACL contains an INHERIT_ONLY entry
- * but no non-INHERIT_ONLY entry for one SID. So we only
- * remove entries from the Access ACL if the
- * corresponding Default ACL entries have also been
- * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP
- * are exceptions. We can do nothing
- * intelligent if the Default ACL contains entries that
- * are not also contained in the Access ACL, so this
- * case will still fail under NT 4.
- */
-
- ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL);
- if (ace && !ace->perms) {
- DLIST_REMOVE(dir_ace, ace);
- TALLOC_FREE(ace);
-
- ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL);
- if (ace && !ace->perms) {
- DLIST_REMOVE(file_ace, ace);
- TALLOC_FREE(ace);
- }
- }
-
- /*
- * WinNT doesn't usually have Creator Group
- * in browse lists, so we send this entry to
- * WinNT even if it contains no relevant
- * permissions. Once we can add
- * Creator Group to browse lists we can
- * re-enable this.
- */
-
-#if 0
- ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL);
- if (ace && !ace->perms) {
- DLIST_REMOVE(dir_ace, ace);
- TALLOC_FREE(ace);
- }
-#endif
-
- ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL);
- if (ace && !ace->perms) {
- DLIST_REMOVE(file_ace, ace);
- TALLOC_FREE(ace);
- }
- }
-
num_acls = count_canon_ace_list(file_ace);
num_def_acls = count_canon_ace_list(dir_ace);
- /* Allocate the ace list. */
- if ((nt_ace_list = talloc_array(talloc_tos(), struct security_ace,num_acls + num_profile_acls + num_def_acls)) == NULL) {
+ nt_ace_list = talloc_zero_array(
+ talloc_tos(), struct security_ace,
+ num_acls + num_profile_acls + num_def_acls);
+
+ if (nt_ace_list == NULL) {
DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n"));
goto done;
}
- memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(struct security_ace) );
-
/*
* Create the NT ACE list from the canonical ace lists.
*/
num_aces = merge_default_aces(nt_ace_list, num_aces);
if (lp_profile_acls(SNUM(conn))) {
+ size_t i;
+
for (i = 0; i < num_aces; i++) {
if (dom_sid_equal(&nt_ace_list[i].trustee, &owner_sid)) {
add_or_replace_ace(nt_ace_list, &num_aces,
/* can it happen that fsp_name == NULL ? */
if (fsp->is_directory || fsp->fh->fd == -1) {
- status = posix_get_nt_acl(fsp->conn, fsp->fsp_name->base_name,
+ status = posix_get_nt_acl(fsp->conn, fsp->fsp_name,
security_info, mem_ctx, ppdesc);
TALLOC_FREE(frame);
return status;
return status;
}
-NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
- uint32_t security_info,
- TALLOC_CTX *mem_ctx,
- struct security_descriptor **ppdesc)
+NTSTATUS posix_get_nt_acl(struct connection_struct *conn,
+ const struct smb_filename *smb_fname_in,
+ uint32_t security_info,
+ TALLOC_CTX *mem_ctx,
+ struct security_descriptor **ppdesc)
{
SMB_ACL_T posix_acl = NULL;
SMB_ACL_T def_acl = NULL;
struct pai_val *pal;
- struct smb_filename smb_fname;
+ struct smb_filename *smb_fname = NULL;
int ret;
TALLOC_CTX *frame = talloc_stackframe();
NTSTATUS status;
*ppdesc = NULL;
- DEBUG(10,("posix_get_nt_acl: called for file %s\n", name ));
+ DEBUG(10,("posix_get_nt_acl: called for file %s\n",
+ smb_fname_in->base_name ));
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = discard_const_p(char, name);
+ smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
+ if (smb_fname == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
/* Get the stat struct for the owner info. */
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LSTAT(conn, &smb_fname);
- } else {
- ret = SMB_VFS_STAT(conn, &smb_fname);
- }
+ /*
+ * We can directly use SMB_VFS_STAT here, as if this was a
+ * POSIX call on a symlink, we've already refused it.
+ * For a Windows acl mapped call on a symlink, we want to follow
+ * it.
+ */
+ ret = SMB_VFS_STAT(conn, smb_fname);
if (ret == -1) {
TALLOC_FREE(frame);
}
/* Get the ACL from the path. */
- posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name,
+ posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
SMB_ACL_TYPE_ACCESS, frame);
/* If it's a directory get the default POSIX ACL. */
- if(S_ISDIR(smb_fname.st.st_ex_mode)) {
- def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name,
+ if(S_ISDIR(smb_fname->st.st_ex_mode)) {
+ def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
SMB_ACL_TYPE_DEFAULT, frame);
def_acl = free_empty_sys_acl(conn, def_acl);
}
- pal = load_inherited_info(conn, name);
+ pal = load_inherited_info(conn, smb_fname);
- status = posix_get_nt_acl_common(conn, name, &smb_fname.st, pal,
- posix_acl, def_acl, security_info,
- mem_ctx,
- ppdesc);
+ status = posix_get_nt_acl_common(conn,
+ smb_fname->base_name,
+ &smb_fname->st,
+ pal,
+ posix_acl,
+ def_acl,
+ security_info,
+ mem_ctx,
+ ppdesc);
TALLOC_FREE(frame);
return status;
}
return status;
}
-#if 0
-/* Disable this - prevents ACL inheritance from the ACL editor. JRA. */
-
-/****************************************************************************
- Take care of parent ACL inheritance.
-****************************************************************************/
-
-NTSTATUS append_parent_acl(files_struct *fsp,
- const struct security_descriptor *pcsd,
- struct security_descriptor **pp_new_sd)
-{
- struct smb_filename *smb_dname = NULL;
- struct security_descriptor *parent_sd = NULL;
- files_struct *parent_fsp = NULL;
- TALLOC_CTX *mem_ctx = talloc_tos();
- char *parent_name = NULL;
- struct security_ace *new_ace = NULL;
- unsigned int num_aces = pcsd->dacl->num_aces;
- NTSTATUS status;
- int info;
- unsigned int i, j;
- struct security_descriptor *psd = dup_sec_desc(talloc_tos(), pcsd);
- bool is_dacl_protected = (pcsd->type & SEC_DESC_DACL_PROTECTED);
-
- if (psd == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (!parent_dirname(mem_ctx, fsp->fsp_name->base_name, &parent_name,
- NULL)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = create_synthetic_smb_fname(mem_ctx, parent_name, NULL, NULL,
- &smb_dname);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- status = SMB_VFS_CREATE_FILE(
- fsp->conn, /* conn */
- NULL, /* req */
- 0, /* root_dir_fid */
- smb_dname, /* fname */
- FILE_READ_ATTRIBUTES, /* access_mask */
- FILE_SHARE_NONE, /* share_access */
- FILE_OPEN, /* create_disposition*/
- FILE_DIRECTORY_FILE, /* create_options */
- 0, /* file_attributes */
- INTERNAL_OPEN_ONLY, /* oplock_request */
- 0, /* allocation_size */
- NULL, /* sd */
- NULL, /* ea_list */
- &parent_fsp, /* result */
- &info); /* pinfo */
-
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(smb_dname);
- return status;
- }
-
- status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, smb_dname->base_name,
- SECINFO_DACL, &parent_sd );
-
- close_file(NULL, parent_fsp, NORMAL_CLOSE);
- TALLOC_FREE(smb_dname);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /*
- * Make room for potentially all the ACLs from
- * the parent. We used to add the ugw triple here,
- * as we knew we were dealing with POSIX ACLs.
- * We no longer need to do so as we can guarentee
- * that a default ACL from the parent directory will
- * be well formed for POSIX ACLs if it came from a
- * POSIX ACL source, and if we're not writing to a
- * POSIX ACL sink then we don't care if it's not well
- * formed. JRA.
- */
-
- num_aces += parent_sd->dacl->num_aces;
-
- if((new_ace = talloc_zero_array(mem_ctx, struct security_ace,
- num_aces)) == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* Start by copying in all the given ACE entries. */
- for (i = 0; i < psd->dacl->num_aces; i++) {
- sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]);
- }
-
- /*
- * Note that we're ignoring "inherit permissions" here
- * as that really only applies to newly created files. JRA.
- */
-
- /* Finally append any inherited ACEs. */
- for (j = 0; j < parent_sd->dacl->num_aces; j++) {
- struct security_ace *se = &parent_sd->dacl->aces[j];
-
- if (fsp->is_directory) {
- if (!(se->flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
- /* Doesn't apply to a directory - ignore. */
- DEBUG(10,("append_parent_acl: directory %s "
- "ignoring non container "
- "inherit flags %u on ACE with sid %s "
- "from parent %s\n",
- fsp_str_dbg(fsp),
- (unsigned int)se->flags,
- sid_string_dbg(&se->trustee),
- parent_name));
- continue;
- }
- } else {
- if (!(se->flags & SEC_ACE_FLAG_OBJECT_INHERIT)) {
- /* Doesn't apply to a file - ignore. */
- DEBUG(10,("append_parent_acl: file %s "
- "ignoring non object "
- "inherit flags %u on ACE with sid %s "
- "from parent %s\n",
- fsp_str_dbg(fsp),
- (unsigned int)se->flags,
- sid_string_dbg(&se->trustee),
- parent_name));
- continue;
- }
- }
-
- if (is_dacl_protected) {
- /* If the DACL is protected it means we must
- * not overwrite an existing ACE entry with the
- * same SID. This is order N^2. Ouch :-(. JRA. */
- unsigned int k;
- for (k = 0; k < psd->dacl->num_aces; k++) {
- if (dom_sid_equal(&psd->dacl->aces[k].trustee,
- &se->trustee)) {
- break;
- }
- }
- if (k < psd->dacl->num_aces) {
- /* SID matched. Ignore. */
- DEBUG(10,("append_parent_acl: path %s "
- "ignoring ACE with protected sid %s "
- "from parent %s\n",
- fsp_str_dbg(fsp),
- sid_string_dbg(&se->trustee),
- parent_name));
- continue;
- }
- }
-
- sec_ace_copy(&new_ace[i], se);
- if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
- new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT);
- }
- new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE;
-
- if (fsp->is_directory) {
- /*
- * Strip off any inherit only. It's applied.
- */
- new_ace[i].flags &= ~(SEC_ACE_FLAG_INHERIT_ONLY);
- if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
- /* No further inheritance. */
- new_ace[i].flags &=
- ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
- SEC_ACE_FLAG_OBJECT_INHERIT);
- }
- } else {
- /*
- * Strip off any container or inherit
- * flags, they can't apply to objects.
- */
- new_ace[i].flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|
- SEC_ACE_FLAG_INHERIT_ONLY|
- SEC_ACE_FLAG_NO_PROPAGATE_INHERIT);
- }
- i++;
-
- DEBUG(10,("append_parent_acl: path %s "
- "inheriting ACE with sid %s "
- "from parent %s\n",
- fsp_str_dbg(fsp),
- sid_string_dbg(&se->trustee),
- parent_name));
- }
-
- psd->dacl->aces = new_ace;
- psd->dacl->num_aces = i;
- psd->type &= ~(SEC_DESC_DACL_AUTO_INHERITED|
- SEC_DESC_DACL_AUTO_INHERIT_REQ);
-
- *pp_new_sd = psd;
- return status;
-}
-#endif
-
/****************************************************************************
Reply to set a security descriptor on an fsp. security_info_sent is the
description of the following NT ACL.
it, even though it's a const pointer.
****************************************************************************/
-NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd_orig)
+NTSTATUS set_nt_acl(files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd_orig)
{
connection_struct *conn = fsp->conn;
uid_t user = (uid_t)-1;
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
- if (!psd_orig) {
+ if (psd_orig == NULL) {
return NT_STATUS_INVALID_PARAMETER;
}
- psd = dup_sec_desc(talloc_tos(), psd_orig);
- if (!psd) {
+ /*
+ * MS NFS mode, here's the deal: the client merely wants to
+ * modify the mode, but roundtripping get_acl/set/acl would
+ * add additional POSIX ACEs. So in case we get a request
+ * containing a MS NFS mode SID, we do nothing here.
+ */
+ if (security_descriptor_with_ms_nfs(psd_orig)) {
+ return NT_STATUS_OK;
+ }
+
+ psd = security_descriptor_copy(talloc_tos(), psd_orig);
+ if (psd == NULL) {
return NT_STATUS_NO_MEMORY;
}
security_info_sent &= ~SECINFO_GROUP;
}
+ /* If UNIX owner is inherited and Windows isn't, then
+ * setting the UNIX owner based on Windows owner conflicts
+ * with the inheritance rule
+ */
+ if (lp_inherit_owner(SNUM(conn)) == INHERIT_OWNER_UNIX_ONLY) {
+ security_info_sent &= ~SECINFO_OWNER;
+ }
+
status = unpack_nt_owners( conn, &user, &grp, security_info_sent, psd);
if (!NT_STATUS_IS_OK(status)) {
return status;
become_root();
}
sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn,
- fsp->fsp_name->base_name);
+ fsp->fsp_name);
if (set_acl_as_root) {
unbecome_root();
}
sret =
SMB_VFS_SYS_ACL_DELETE_DEF_FILE(
conn,
- fsp->fsp_name->base_name);
+ fsp->fsp_name);
unbecome_root();
}
if (set_acl_as_root) {
become_root();
}
- sret = SMB_VFS_CHMOD(conn, fsp->fsp_name->base_name,
+ sret = SMB_VFS_CHMOD(conn, fsp->fsp_name,
posix_perms);
if (set_acl_as_root) {
unbecome_root();
become_root();
sret = SMB_VFS_CHMOD(conn,
- fsp->fsp_name->base_name,
+ fsp->fsp_name,
posix_perms);
unbecome_root();
}
the mask bits, not the real group bits, for a file with an ACL.
****************************************************************************/
-int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode )
+int get_acl_group_bits( connection_struct *conn,
+ const struct smb_filename *smb_fname,
+ mode_t *mode )
{
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
SMB_ACL_T posix_acl;
int result = -1;
- posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+ posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
SMB_ACL_TYPE_ACCESS, talloc_tos());
if (posix_acl == (SMB_ACL_T)NULL)
return -1;
resulting ACL on TO. Note that name is in UNIX character set.
****************************************************************************/
-static int copy_access_posix_acl(connection_struct *conn, const char *from, const char *to, mode_t mode)
+static int copy_access_posix_acl(connection_struct *conn,
+ const struct smb_filename *smb_fname_from,
+ const struct smb_filename *smb_fname_to,
+ mode_t mode)
{
SMB_ACL_T posix_acl = NULL;
int ret = -1;
- if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from,
+ if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname_from,
SMB_ACL_TYPE_ACCESS,
talloc_tos())) == NULL)
return -1;
if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
goto done;
- ret = SMB_VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl);
+ ret = SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname_to,
+ SMB_ACL_TYPE_ACCESS, posix_acl);
done:
Note that name is in UNIX character set.
****************************************************************************/
-int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
+int chmod_acl(connection_struct *conn,
+ const struct smb_filename *smb_fname,
+ mode_t mode)
{
- return copy_access_posix_acl(conn, name, name, mode);
+ return copy_access_posix_acl(conn, smb_fname, smb_fname, mode);
}
/****************************************************************************
Check for an existing default POSIX ACL on a directory.
****************************************************************************/
-static bool directory_has_default_posix_acl(connection_struct *conn, const char *fname)
+static bool directory_has_default_posix_acl(connection_struct *conn,
+ const struct smb_filename *smb_fname)
{
- SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+ SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
SMB_ACL_TYPE_DEFAULT,
talloc_tos());
bool has_acl = False;
inherit this Access ACL to file name.
****************************************************************************/
-int inherit_access_posix_acl(connection_struct *conn, const char *inherit_from_dir,
- const char *name, mode_t mode)
+int inherit_access_posix_acl(connection_struct *conn,
+ const char *inherit_from_dir,
+ const struct smb_filename *smb_fname,
+ mode_t mode)
{
- if (directory_has_default_posix_acl(conn, inherit_from_dir))
+ struct smb_filename *inherit_from_fname =
+ synthetic_smb_fname(talloc_tos(),
+ smb_fname->base_name,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ if (inherit_from_fname == NULL) {
+ return-1;
+ }
+
+ if (directory_has_default_posix_acl(conn, inherit_from_fname))
return 0;
- return copy_access_posix_acl(conn, inherit_from_dir, name, mode);
+ return copy_access_posix_acl(conn, inherit_from_fname, smb_fname, mode);
}
/****************************************************************************
****************************************************************************/
static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn,
- uint16 num_acls,
+ uint16_t num_acls,
const char *pdata,
TALLOC_CTX *mem_ctx)
{
}
if (tag_type == SMB_ACL_USER) {
- uint32 uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
+ uint32_t uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
uid_t uid = (uid_t)uidval;
if (sys_acl_set_qualifier(the_entry,(void *)&uid) == -1) {
DEBUG(0,("create_posix_acl_from_wire: Failed to set uid %u on entry %u. (%s)\n",
}
if (tag_type == SMB_ACL_GROUP) {
- uint32 gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
+ uint32_t gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
gid_t gid = (uid_t)gidval;
if (sys_acl_set_qualifier(the_entry,(void *)&gid) == -1) {
DEBUG(0,("create_posix_acl_from_wire: Failed to set gid %u on entry %u. (%s)\n",
on the directory.
****************************************************************************/
-bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf,
- uint16 num_def_acls, const char *pdata)
+bool set_unix_posix_default_acl(connection_struct *conn,
+ const struct smb_filename *smb_fname,
+ uint16_t num_def_acls,
+ const char *pdata)
{
SMB_ACL_T def_acl = NULL;
- if (!S_ISDIR(psbuf->st_ex_mode)) {
+ if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
if (num_def_acls) {
- DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname ));
+ DEBUG(5,("set_unix_posix_default_acl: Can't "
+ "set default ACL on non-directory file %s\n",
+ smb_fname->base_name ));
errno = EISDIR;
return False;
} else {
if (!num_def_acls) {
/* Remove the default ACL. */
- if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) {
+ if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, smb_fname) == -1) {
DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n",
- fname, strerror(errno) ));
+ smb_fname->base_name, strerror(errno) ));
return False;
}
return True;
return False;
}
- if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) {
+ if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname,
+ SMB_ACL_TYPE_DEFAULT, def_acl) == -1) {
DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n",
- fname, strerror(errno) ));
+ smb_fname->base_name, strerror(errno) ));
TALLOC_FREE(def_acl);
return False;
}
- DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname ));
+ DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n",
+ smb_fname->base_name ));
TALLOC_FREE(def_acl);
return True;
}
FIXME ! How does the share mask/mode fit into this.... ?
****************************************************************************/
-static bool remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname)
+static bool remove_posix_acl(connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname)
{
SMB_ACL_T file_acl = NULL;
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
bool ret = False;
+ const char *fname = smb_fname->base_name;
/* Create a new ACL with only 3 entries, u/g/w. */
SMB_ACL_T new_file_acl = sys_acl_init(talloc_tos());
SMB_ACL_ENTRY_T user_ent = NULL;
if (fsp && fsp->fh->fd != -1) {
file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, talloc_tos());
} else {
- file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname,
+ file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, smb_fname,
SMB_ACL_TYPE_ACCESS,
talloc_tos());
}
goto done;
}
} else {
- if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, new_file_acl) == -1) {
+ if (SMB_VFS_SYS_ACL_SET_FILE(conn,
+ smb_fname,
+ SMB_ACL_TYPE_ACCESS,
+ new_file_acl) == -1) {
DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
fname, strerror(errno) ));
goto done;
except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER.
****************************************************************************/
-bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata)
+bool set_unix_posix_acl(connection_struct *conn, files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ uint16_t num_acls,
+ const char *pdata)
{
SMB_ACL_T file_acl = NULL;
+ const char *fname = smb_fname->base_name;
if (!num_acls) {
/* Remove the ACL from the file. */
- return remove_posix_acl(conn, fsp, fname);
+ return remove_posix_acl(conn, fsp, smb_fname);
}
if ((file_acl = create_posix_acl_from_wire(conn, num_acls,
return False;
}
} else {
- if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, file_acl) == -1) {
+ if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname,
+ SMB_ACL_TYPE_ACCESS, file_acl) == -1) {
DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
fname, strerror(errno) ));
TALLOC_FREE(file_acl);
check. Caller is responsible for freeing the returned security
descriptor via TALLOC_FREE(). This is designed for dealing with
user space access checks in smbd outside of the VFS. For example,
- checking access rights in OpenEventlog().
+ checking access rights in OpenEventlog() or from python.
- Assume we are dealing with files (for now)
********************************************************************/
-struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname, uint32 security_info_wanted)
+NTSTATUS get_nt_acl_no_snum(TALLOC_CTX *ctx, const char *fname,
+ uint32_t security_info_wanted,
+ struct security_descriptor **sd)
{
- struct security_descriptor *ret_sd;
- connection_struct *conn;
- files_struct finfo;
- struct fd_handle fh;
- NTSTATUS status;
TALLOC_CTX *frame = talloc_stackframe();
+ connection_struct *conn;
+ NTSTATUS status = NT_STATUS_OK;
+ struct smb_filename *smb_fname = synthetic_smb_fname(talloc_tos(),
+ fname,
+ NULL,
+ NULL,
+ 0);
+
+ if (smb_fname == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
- conn = talloc_zero(frame, connection_struct);
- if (conn == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return NULL;
+ if (!posix_locking_init(false)) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
}
- if (!(conn->params = talloc(conn, struct share_params))) {
- DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
+ status = create_conn_struct(ctx,
+ server_event_context(),
+ server_messaging_context(),
+ &conn,
+ -1,
+ "/",
+ NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("create_conn_struct returned %s.\n",
+ nt_errstr(status)));
TALLOC_FREE(frame);
- return NULL;
+ return status;
+ }
+
+ status = SMB_VFS_GET_NT_ACL(conn,
+ smb_fname,
+ security_info_wanted,
+ ctx,
+ sd);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("get_nt_acl_no_snum: SMB_VFS_GET_NT_ACL returned %s.\n",
+ nt_errstr(status)));
}
- conn->params->service = -1;
+ conn_free(conn);
+ TALLOC_FREE(frame);
- set_conn_connectpath(conn, "/");
+ return status;
+}
- if (!smbd_vfs_init(conn)) {
- DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
- conn_free(conn);
+int posix_sys_acl_blob_get_file(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname_in,
+ TALLOC_CTX *mem_ctx,
+ char **blob_description,
+ DATA_BLOB *blob)
+{
+ int ret;
+ TALLOC_CTX *frame = talloc_stackframe();
+ /* Initialise this to zero, in a portable way */
+ struct smb_acl_wrapper acl_wrapper = {
+ NULL
+ };
+ struct smb_filename *smb_fname = cp_smb_filename_nostream(frame,
+ smb_fname_in);
+ if (smb_fname == NULL) {
TALLOC_FREE(frame);
- return NULL;
- }
+ errno = ENOMEM;
+ return -1;
+ }
- ZERO_STRUCT( finfo );
- ZERO_STRUCT( fh );
+ acl_wrapper.access_acl
+ = smb_vfs_call_sys_acl_get_file(handle,
+ smb_fname,
+ SMB_ACL_TYPE_ACCESS,
+ frame);
- finfo.fnum = FNUM_FIELD_INVALID;
- finfo.conn = conn;
- finfo.fh = &fh;
- finfo.fh->fd = -1;
+ ret = smb_vfs_call_stat(handle, smb_fname);
+ if (ret == -1) {
+ TALLOC_FREE(frame);
+ return -1;
+ }
- status = create_synthetic_smb_fname(frame, fname, NULL, NULL,
- &finfo.fsp_name);
- if (!NT_STATUS_IS_OK(status)) {
- conn_free(conn);
+ if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ acl_wrapper.default_acl
+ = smb_vfs_call_sys_acl_get_file(handle,
+ smb_fname,
+ SMB_ACL_TYPE_DEFAULT,
+ frame);
+ }
+
+ acl_wrapper.owner = smb_fname->st.st_ex_uid;
+ acl_wrapper.group = smb_fname->st.st_ex_gid;
+ acl_wrapper.mode = smb_fname->st.st_ex_mode;
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(blob, mem_ctx,
+ &acl_wrapper,
+ (ndr_push_flags_fn_t)ndr_push_smb_acl_wrapper))) {
+ errno = EINVAL;
TALLOC_FREE(frame);
- return NULL;
+ return -1;
}
- if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo,
- security_info_wanted,
- ctx, &ret_sd))) {
- DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
- TALLOC_FREE(finfo.fsp_name);
- conn_free(conn);
+ *blob_description = talloc_strdup(mem_ctx, "posix_acl");
+ if (!*blob_description) {
+ errno = EINVAL;
TALLOC_FREE(frame);
- return NULL;
+ return -1;
}
- TALLOC_FREE(finfo.fsp_name);
- conn_free(conn);
TALLOC_FREE(frame);
-
- return ret_sd;
+ return 0;
}
-/* Stolen shamelessly from pvfs_default_acl() in source4 :-). */
-
-NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
- const char *name,
- SMB_STRUCT_STAT *psbuf,
- struct security_descriptor **ppdesc)
+int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle,
+ files_struct *fsp,
+ TALLOC_CTX *mem_ctx,
+ char **blob_description,
+ DATA_BLOB *blob)
{
- struct dom_sid owner_sid, group_sid;
- size_t size = 0;
- struct security_ace aces[4];
- uint32_t access_mask = 0;
- mode_t mode = psbuf->st_ex_mode;
- struct security_acl *new_dacl = NULL;
- int idx = 0;
+ SMB_STRUCT_STAT sbuf;
+ TALLOC_CTX *frame;
+ struct smb_acl_wrapper acl_wrapper;
+ int ret;
- DEBUG(10,("make_default_filesystem_acl: file %s mode = 0%o\n",
- name, (int)mode ));
+ /* This ensures that we also consider the default ACL */
+ if (fsp->is_directory || fsp->fh->fd == -1) {
+ return posix_sys_acl_blob_get_file(handle,
+ fsp->fsp_name,
+ mem_ctx,
+ blob_description,
+ blob);
+ }
+ frame = talloc_stackframe();
- uid_to_sid(&owner_sid, psbuf->st_ex_uid);
- gid_to_sid(&group_sid, psbuf->st_ex_gid);
+ acl_wrapper.default_acl = NULL;
- /*
- We provide up to 4 ACEs
- - Owner
- - Group
- - Everyone
- - NT System
- */
+ acl_wrapper.access_acl = smb_vfs_call_sys_acl_get_file(handle,
+ fsp->fsp_name,
+ SMB_ACL_TYPE_ACCESS,
+ frame);
- if (mode & S_IRUSR) {
- if (mode & S_IWUSR) {
- access_mask |= SEC_RIGHTS_FILE_ALL;
- } else {
- access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
- }
+ ret = smb_vfs_call_fstat(handle, fsp, &sbuf);
+ if (ret == -1) {
+ TALLOC_FREE(frame);
+ return -1;
}
- if (mode & S_IWUSR) {
- access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
- }
-
- init_sec_ace(&aces[idx],
- &owner_sid,
- SEC_ACE_TYPE_ACCESS_ALLOWED,
- access_mask,
- 0);
- idx++;
-
- access_mask = 0;
- if (mode & S_IRGRP) {
- access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
- }
- if (mode & S_IWGRP) {
- /* note that delete is not granted - this matches posix behaviour */
- access_mask |= SEC_RIGHTS_FILE_WRITE;
- }
- if (access_mask) {
- init_sec_ace(&aces[idx],
- &group_sid,
- SEC_ACE_TYPE_ACCESS_ALLOWED,
- access_mask,
- 0);
- idx++;
- }
-
- access_mask = 0;
- if (mode & S_IROTH) {
- access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
- }
- if (mode & S_IWOTH) {
- access_mask |= SEC_RIGHTS_FILE_WRITE;
- }
- if (access_mask) {
- init_sec_ace(&aces[idx],
- &global_sid_World,
- SEC_ACE_TYPE_ACCESS_ALLOWED,
- access_mask,
- 0);
- idx++;
- }
-
- init_sec_ace(&aces[idx],
- &global_sid_System,
- SEC_ACE_TYPE_ACCESS_ALLOWED,
- SEC_RIGHTS_FILE_ALL,
- 0);
- idx++;
-
- new_dacl = make_sec_acl(ctx,
- NT4_ACL_REVISION,
- idx,
- aces);
-
- if (!new_dacl) {
- return NT_STATUS_NO_MEMORY;
+
+ acl_wrapper.owner = sbuf.st_ex_uid;
+ acl_wrapper.group = sbuf.st_ex_gid;
+ acl_wrapper.mode = sbuf.st_ex_mode;
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(blob, mem_ctx,
+ &acl_wrapper,
+ (ndr_push_flags_fn_t)ndr_push_smb_acl_wrapper))) {
+ errno = EINVAL;
+ TALLOC_FREE(frame);
+ return -1;
}
- *ppdesc = make_sec_desc(ctx,
- SECURITY_DESCRIPTOR_REVISION_1,
- SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
- &owner_sid,
- &group_sid,
- NULL,
- new_dacl,
- &size);
- if (!*ppdesc) {
- return NT_STATUS_NO_MEMORY;
+ *blob_description = talloc_strdup(mem_ctx, "posix_acl");
+ if (!*blob_description) {
+ errno = EINVAL;
+ TALLOC_FREE(frame);
+ return -1;
}
- return NT_STATUS_OK;
+
+ TALLOC_FREE(frame);
+ return 0;
}