summaryrefslogtreecommitdiff
path: root/source3/smbd/posix_acls.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/posix_acls.c')
-rw-r--r--source3/smbd/posix_acls.c180
1 files changed, 50 insertions, 130 deletions
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 85818d524a..9c8835214f 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -104,7 +104,7 @@ static void print_canon_ace(canon_ace *pace, int num)
dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee));
if (pace->owner_type == UID_ACE) {
- const char *u_name = uidtoname(pace->unix_ug.uid);
+ char *u_name = uidtoname(pace->unix_ug.uid);
dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name);
} else if (pace->owner_type == GID_ACE) {
char *g_name = gidtoname(pace->unix_ug.gid);
@@ -439,15 +439,9 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
if (security_info_sent & OWNER_SECURITY_INFORMATION) {
sid_copy(&owner_sid, psd->owner_sid);
if (!sid_to_uid( &owner_sid, puser, &sid_type)) {
-#if ACL_FORCE_UNMAPPABLE
- /* this allows take ownership to work reasonably */
- extern struct current_user current_user;
- *puser = current_user.uid;
-#else
DEBUG(3,("unpack_nt_owners: unable to validate owner sid for %s\n",
sid_string_static(&owner_sid)));
return False;
-#endif
}
}
@@ -459,14 +453,8 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
if (security_info_sent & GROUP_SECURITY_INFORMATION) {
sid_copy(&grp_sid, psd->grp_sid);
if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) {
-#if ACL_FORCE_UNMAPPABLE
- /* this allows take group ownership to work reasonably */
- extern struct current_user current_user;
- *pgrp = current_user.gid;
-#else
DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n"));
return False;
-#endif
}
}
@@ -479,7 +467,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
Ensure the enforced permissions for this share apply.
****************************************************************************/
-static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
+static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type)
{
int snum = SNUM(fsp->conn);
mode_t and_bits = (mode_t)0;
@@ -498,10 +486,6 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
/* Now bounce them into the S_USR space. */
switch(type) {
case S_IRUSR:
- /* Ensure owner has read access. */
- pace->perms |= S_IRUSR;
- if (fsp->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;
@@ -515,34 +499,7 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
break;
}
- pace->perms = ((pace->perms & and_bits)|or_bits);
-}
-
-/****************************************************************************
- Check if a given uid/SID is in a group gid/SID. This is probably very
- expensive and will need optimisation. A *lot* of optimisation :-). JRA.
-****************************************************************************/
-
-static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
-{
- extern DOM_SID global_sid_World;
- fstring u_name;
- fstring g_name;
-
- /* "Everyone" always matches every uid. */
-
- if (sid_equal(&group_ace->trustee, &global_sid_World))
- return True;
-
- fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
- fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));
-
- /*
- * Due to the winbind interfaces we need to do this via names,
- * not uids/gids.
- */
-
- return user_in_group_list(u_name, g_name );
+ return ((perms & and_bits)|or_bits);
}
/****************************************************************************
@@ -567,16 +524,24 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
BOOL got_user = False;
BOOL got_grp = False;
BOOL got_other = False;
- canon_ace *pace_other = NULL;
- canon_ace *pace_group = NULL;
for (pace = *pp_ace; pace; pace = pace->next) {
if (pace->type == SMB_ACL_USER_OBJ) {
- if (setting_acl)
- apply_default_perms(fsp, pace, S_IRUSR);
- got_user = True;
+ if (setting_acl) {
+ /* Ensure owner has read access. */
+ pace->perms |= S_IRUSR;
+ if (fsp->is_directory)
+ pace->perms |= (S_IWUSR|S_IXUSR);
+ /*
+ * Ensure create mask/force create mode is respected on set.
+ */
+
+ pace->perms = apply_default_perms(fsp, pace->perms, S_IRUSR);
+ }
+
+ got_user = True;
} else if (pace->type == SMB_ACL_GROUP_OBJ) {
/*
@@ -584,10 +549,8 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
*/
if (setting_acl)
- apply_default_perms(fsp, pace, S_IRGRP);
+ pace->perms = apply_default_perms(fsp, pace->perms, S_IRGRP);
got_grp = True;
- pace_group = pace;
-
} else if (pace->type == SMB_ACL_OTHER) {
/*
@@ -595,9 +558,8 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
*/
if (setting_acl)
- apply_default_perms(fsp, pace, S_IROTH);
+ pace->perms = apply_default_perms(fsp, pace->perms, S_IROTH);
got_other = True;
- pace_other = pace;
}
}
@@ -612,21 +574,9 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
pace->owner_type = UID_ACE;
pace->unix_ug.uid = pst->st_uid;
pace->trustee = *pfile_owner_sid;
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
pace->attr = ALLOW_ACE;
- if (setting_acl) {
- /* If we only got an "everyone" perm, just use that. */
- if (!got_grp && got_other)
- pace->perms = pace_other->perms;
- else if (got_grp && uid_entry_in_group(pace, pace_group))
- pace->perms = pace_group->perms;
- else
- pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
- apply_default_perms(fsp, pace, S_IRUSR);
- } else {
- pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
- }
-
DLIST_ADD(*pp_ace, pace);
}
@@ -641,17 +591,8 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
pace->owner_type = GID_ACE;
pace->unix_ug.uid = pst->st_gid;
pace->trustee = *pfile_grp_sid;
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
pace->attr = ALLOW_ACE;
- if (setting_acl) {
- /* If we only got an "everyone" perm, just use that. */
- if (got_other)
- pace->perms = pace_other->perms;
- else
- pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
- apply_default_perms(fsp, pace, S_IRGRP);
- } else {
- pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
- }
DLIST_ADD(*pp_ace, pace);
}
@@ -667,9 +608,8 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
pace->owner_type = WORLD_ACE;
pace->unix_ug.world = -1;
pace->trustee = global_sid_World;
- pace->attr = ALLOW_ACE;
pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
- apply_default_perms(fsp, pace, S_IROTH);
+ pace->attr = ALLOW_ACE;
DLIST_ADD(*pp_ace, pace);
}
@@ -979,6 +919,33 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
}
/****************************************************************************
+ Check if a given uid/SID is in a group gid/SID. This is probably very
+ expensive and will need optimisation. A *lot* of optimisation :-). JRA.
+****************************************************************************/
+
+static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
+{
+ extern DOM_SID global_sid_World;
+ fstring u_name;
+ fstring g_name;
+
+ /* "Everyone" always matches every uid. */
+
+ if (sid_equal(&group_ace->trustee, &global_sid_World))
+ return True;
+
+ fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
+ fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));
+
+ /*
+ * Due to the winbind interfaces we need to do this via names,
+ * not uids/gids.
+ */
+
+ return user_in_group_list(u_name, g_name );
+}
+
+/****************************************************************************
ASCII art time again... JRA :-).
We have 3 cases to process when moving from an NT ACL to a POSIX ACL. Firstly,
@@ -2029,52 +1996,6 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
return sd_size;
}
-/*
- try to chown a file. We will be able to chown it under the following conditions
-
- 1) if we have root privileges, then it will just work
- 2) if we have write permission to the file and dos_filemodes is set
- then allow chown to the currently authenticated user.
-
- */
-static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
-{
- int ret;
- extern struct current_user current_user;
- files_struct *fsp;
- SMB_STRUCT_STAT st;
-
- /* try the direct way first */
- ret = vfs_chown(conn, fname, uid, gid);
- if (ret == 0)
- return 0;
-
- if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
- return -1;
-
- if (vfs_stat(conn,fname,&st))
- return -1;
-
- fsp = open_file_fchmod(conn,fname,&st);
- if (!fsp)
- return -1;
-
- /* only allow chown to the current user. This is more secure,
- and also copes with the case where the SID in a take ownership ACL is
- a local SID on the users workstation
- */
- uid = current_user.uid;
-
- become_root();
- /* Keep the current file gid the same. */
- ret = vfswrap_fchown(fsp, fsp->fd, uid, (gid_t)-1);
- unbecome_root();
-
- close_file_fchmod(fsp);
-
- return ret;
-}
-
/****************************************************************************
Reply to set a security descriptor on an fsp. security_info_sent is the
description of the following NT ACL.
@@ -2131,7 +2052,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
- if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
+ if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
return False;
@@ -2387,7 +2308,6 @@ BOOL directory_has_default_acl(connection_struct *conn, const char *fname)
if (dir_acl != NULL && (conn->vfs_ops.sys_acl_get_entry(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1))
has_acl = True;
- if (dir_acl)
- conn->vfs_ops.sys_acl_free_acl(conn, dir_acl);
+ conn->vfs_ops.sys_acl_free_acl(conn, dir_acl);
return has_acl;
}