X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source%2Fsmbd%2Fposix_acls.c;h=aa1629e598bd6ca6e6cc4a7c043cb9faa47ba06f;hb=785c4d7d821d5302ed72c10b85366cb34915bcb9;hp=7eda998547e650afad450ab250828a256fe81ac1;hpb=10649540ac11e679997f414d4a6b12d057bd7913;p=obnox%2Fsamba%2Fsamba-obnox.git
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 7eda998547e..aa1629e598b 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -6,7 +6,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -15,14 +15,13 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see .
*/
#include "includes.h"
extern struct current_user current_user;
-extern struct generic_mapping file_generic_mapping;
+extern const struct generic_mapping file_generic_mapping;
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_ACLS
@@ -47,8 +46,8 @@ typedef struct canon_ace {
DOM_SID trustee;
enum ace_owner owner_type;
enum ace_attribute attr;
- posix_id unix_ug;
- BOOL inherited;
+ posix_id unix_ug;
+ bool inherited;
} canon_ace;
#define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)
@@ -80,11 +79,11 @@ typedef struct canon_ace {
struct pai_entry {
struct pai_entry *next, *prev;
enum ace_owner owner_type;
- posix_id unix_ug;
+ posix_id unix_ug;
};
-
+
struct pai_val {
- BOOL pai_protected;
+ bool pai_protected;
unsigned int num_entries;
struct pai_entry *entry_list;
unsigned int num_def_entries;
@@ -149,7 +148,7 @@ static unsigned int num_inherited_entries(canon_ace *ace_list)
Create the on-disk format. Caller must free.
************************************************************************/
-static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL pai_protected, size_t *store_size)
+static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, bool pai_protected, size_t *store_size)
{
char *pai_buf = NULL;
canon_ace *ace_list = NULL;
@@ -213,7 +212,7 @@ static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, B
************************************************************************/
static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list,
- canon_ace *dir_ace_list, BOOL pai_protected)
+ canon_ace *dir_ace_list, bool pai_protected)
{
int ret;
size_t store_size;
@@ -276,7 +275,7 @@ static void free_inherited_info(struct pai_val *pal)
Was this ACL protected ?
************************************************************************/
-static BOOL get_protected_flag(struct pai_val *pal)
+static bool get_protected_flag(struct pai_val *pal)
{
if (!pal)
return False;
@@ -287,7 +286,7 @@ static BOOL get_protected_flag(struct pai_val *pal)
Was this ACE inherited ?
************************************************************************/
-static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL default_ace)
+static bool get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, bool default_ace)
{
struct pai_entry *paie;
@@ -307,7 +306,7 @@ static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL d
Ensure an attribute just read is valid.
************************************************************************/
-static BOOL check_pai_ok(char *pai_buf, size_t pai_buf_data_size)
+static bool check_pai_ok(char *pai_buf, size_t pai_buf_data_size)
{
uint16 num_entries;
uint16 num_def_entries;
@@ -673,7 +672,7 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI
Is the identity in two ACEs equal ? Check both SID and uid/gid.
****************************************************************************/
-static BOOL identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
+static bool identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
{
if (sid_equal(&ace1->trustee, &ace2->trustee)) {
return True;
@@ -808,7 +807,7 @@ static void merge_aces( canon_ace **pp_list_head )
Check if we need to return NT4.x compatible ACL entries.
****************************************************************************/
-static BOOL nt4_compatible_acls(void)
+static bool nt4_compatible_acls(void)
{
int compat = lp_acl_compatibility();
@@ -828,20 +827,23 @@ static BOOL nt4_compatible_acls(void)
not get. Deny entries are implicit on get with ace->perms = 0.
****************************************************************************/
-static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_sid, canon_ace *ace, BOOL directory_ace)
+static SEC_ACCESS map_canon_ace_perms(int snum,
+ int *pacl_type,
+ mode_t perms,
+ bool directory_ace)
{
SEC_ACCESS sa;
uint32 nt_mask = 0;
*pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
- if (lp_acl_map_full_control(snum) && ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {
+ if (lp_acl_map_full_control(snum) && ((perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {
if (directory_ace) {
nt_mask = UNIX_DIRECTORY_ACCESS_RWX;
} else {
nt_mask = UNIX_ACCESS_RWX;
}
- } else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) {
+ } else if ((perms & ALL_ACE_PERMS) == (mode_t)0) {
/*
* Windows NT refuses to display ACEs with no permissions in them (but
* they are perfectly legal with Windows 2000). If the ACE has empty
@@ -857,18 +859,18 @@ static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_
nt_mask = 0;
} else {
if (directory_ace) {
- nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
- nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );
- nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );
+ nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
+ nt_mask |= ((perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );
+ nt_mask |= ((perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );
} else {
- nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
- nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
- nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
+ nt_mask |= ((perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
+ nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
+ nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
}
}
DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",
- (unsigned int)ace->perms, (unsigned int)nt_mask ));
+ (unsigned int)perms, (unsigned int)nt_mask ));
init_sec_access(&sa,nt_mask);
return sa;
@@ -923,7 +925,7 @@ static mode_t map_nt_perms( uint32 *mask, int type)
Unpack a SEC_DESC into a UNIX owner and group.
****************************************************************************/
-BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
+NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
{
DOM_SID owner_sid;
DOM_SID grp_sid;
@@ -933,7 +935,7 @@ BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_
if(security_info_sent == 0) {
DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
- return True;
+ return NT_STATUS_OK;
}
/*
@@ -961,9 +963,11 @@ BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_
DEBUG(3,("unpack_nt_owners: unable to validate"
" owner sid for %s\n",
sid_string_static(&owner_sid)));
- return False;
+ return NT_STATUS_INVALID_OWNER;
}
}
+ DEBUG(3,("unpack_nt_owners: owner sid mapped to uid %u\n",
+ (unsigned int)*puser ));
}
/*
@@ -981,21 +985,23 @@ BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_
} else {
DEBUG(3,("unpack_nt_owners: unable to validate"
" group sid.\n"));
- return False;
+ return NT_STATUS_INVALID_OWNER;
}
}
- }
+ DEBUG(3,("unpack_nt_owners: group sid mapped to gid %u\n",
+ (unsigned int)*pgrp));
+ }
DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));
- return True;
+ return NT_STATUS_OK;
}
/****************************************************************************
Ensure the enforced permissions for this share apply.
****************************************************************************/
-static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
+static void apply_default_perms(const files_struct *fsp, canon_ace *pace, mode_t type)
{
int snum = SNUM(fsp->conn);
mode_t and_bits = (mode_t)0;
@@ -1039,9 +1045,9 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
expensive and will need optimisation. A *lot* of optimisation :-). JRA.
****************************************************************************/
-static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
+static bool uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
{
- fstring u_name;
+ const char *u_name = NULL;
/* "Everyone" always matches every uid. */
@@ -1053,7 +1059,11 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
if (uid_ace->unix_ug.uid == current_user.ut.uid && group_ace->unix_ug.gid == current_user.ut.gid)
return True;
- fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
+ /* u_name talloc'ed off tos. */
+ u_name = uidtoname(uid_ace->unix_ug.uid);
+ if (!u_name) {
+ return False;
+ }
return user_in_group_sid(u_name, &group_ace->trustee);
}
@@ -1067,17 +1077,17 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
type.
****************************************************************************/
-static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
- files_struct *fsp,
+static bool ensure_canon_entry_valid(canon_ace **pp_ace,
+ const files_struct *fsp,
const DOM_SID *pfile_owner_sid,
const DOM_SID *pfile_grp_sid,
SMB_STRUCT_STAT *pst,
- BOOL setting_acl)
+ bool setting_acl)
{
canon_ace *pace;
- BOOL got_user = False;
- BOOL got_grp = False;
- BOOL got_other = False;
+ bool got_user = False;
+ bool got_grp = False;
+ bool got_other = False;
canon_ace *pace_other = NULL;
for (pace = *pp_ace; pace; pace = pace->next) {
@@ -1127,7 +1137,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
/* See if the owning user is in any of the other groups in
the ACE. If so, OR in the permissions from that group. */
- BOOL group_matched = False;
+ bool group_matched = False;
canon_ace *pace_iter;
for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
@@ -1213,7 +1223,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid)
{
- BOOL got_user_obj, got_group_obj;
+ bool got_user_obj, got_group_obj;
canon_ace *current_ace;
int i, entries;
@@ -1254,18 +1264,18 @@ static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID
Unpack a SEC_DESC into two canonical ace lists.
****************************************************************************/
-static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
+static bool create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
DOM_SID *pfile_owner_sid,
DOM_SID *pfile_grp_sid,
canon_ace **ppfile_ace, canon_ace **ppdir_ace,
SEC_ACL *dacl)
{
- BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False);
+ bool all_aces_are_inherit_only = (fsp->is_directory ? True : False);
canon_ace *file_ace = NULL;
canon_ace *dir_ace = NULL;
canon_ace *current_ace = NULL;
- BOOL got_dir_allow = False;
- BOOL got_file_allow = False;
+ bool got_dir_allow = False;
+ bool got_file_allow = False;
int i, j;
*ppfile_ace = NULL;
@@ -1895,7 +1905,7 @@ static void process_deny_list( canon_ace **pp_ace_list )
no user/group/world entries.
****************************************************************************/
-static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode)
+static mode_t create_default_mode(files_struct *fsp, bool interitable_mode)
{
int snum = SNUM(fsp->conn);
mode_t and_bits = (mode_t)0;
@@ -1929,7 +1939,7 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode)
succeeding.
****************************************************************************/
-static BOOL unpack_canon_ace(files_struct *fsp,
+static bool unpack_canon_ace(files_struct *fsp,
SMB_STRUCT_STAT *pst,
DOM_SID *pfile_owner_sid,
DOM_SID *pfile_grp_sid,
@@ -2100,7 +2110,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head)
Create a linked list of canonical ACE entries.
****************************************************************************/
-static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf,
+static canon_ace *canonicalise_acl( const files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf,
const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
{
connection_struct *conn = fsp->conn;
@@ -2260,7 +2270,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_
Check if the current user group list contains a given group.
****************************************************************************/
-static BOOL current_user_in_group(gid_t gid)
+static bool current_user_in_group(gid_t gid)
{
int i;
@@ -2278,7 +2288,7 @@ static BOOL current_user_in_group(gid_t gid)
and 'dos filemode'
****************************************************************************/
-static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid)
+static bool acl_group_override(connection_struct *conn, gid_t prim_gid)
{
if ( (errno == EACCES || errno == EPERM)
&& (lp_acl_group_control(SNUM(conn)) || lp_dos_filemode(SNUM(conn)))
@@ -2294,18 +2304,18 @@ static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid)
Attempt to apply an ACL to a file or directory.
****************************************************************************/
-static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, gid_t prim_gid, BOOL *pacl_set_support)
+static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool default_ace, gid_t prim_gid, bool *pacl_set_support)
{
connection_struct *conn = fsp->conn;
- BOOL ret = False;
+ bool ret = False;
SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1);
canon_ace *p_ace;
int i;
SMB_ACL_ENTRY_T mask_entry;
- BOOL got_mask_entry = False;
+ bool got_mask_entry = False;
SMB_ACL_PERMSET_T mask_permset;
SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
- BOOL needs_mask = False;
+ bool needs_mask = False;
mode_t mask_perms = 0;
#if defined(POSIX_ACL_NEEDS_MASK)
@@ -2576,7 +2586,7 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
#define MAP_PERM(p,mask,result) (((p) & (mask)) ? (result) : 0 )
-static BOOL convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms)
+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);
@@ -2660,8 +2670,8 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces)
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);
- 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;
+ 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;
/* We know the lower number ACE's are file entries. */
if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
@@ -2889,26 +2899,37 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
}
memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(SEC_ACE) );
-
+
/*
* Create the NT ACE list from the canonical ace lists.
*/
-
+
ace = file_ace;
for (i = 0; i < num_acls; i++, ace = ace->next) {
SEC_ACCESS acc;
- acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory);
- init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0);
+ acc = map_canon_ace_perms(SNUM(conn),
+ &nt_acl_type,
+ ace->perms,
+ fsp->is_directory);
+ init_sec_ace(&nt_ace_list[num_aces++],
+ &ace->trustee,
+ nt_acl_type,
+ acc,
+ ace->inherited ?
+ SEC_ACE_FLAG_INHERITED_ACE : 0);
}
- /* The User must have access to a profile share - even if we can't map the SID. */
+ /* The User must have access to a profile share - even
+ * if we can't map the SID. */
if (lp_profile_acls(SNUM(conn))) {
SEC_ACCESS acc;
init_sec_access(&acc,FILE_GENERIC_ALL);
- init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED,
+ init_sec_ace(&nt_ace_list[num_aces++],
+ &global_sid_Builtin_Users,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
acc, 0);
}
@@ -2916,18 +2937,27 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
for (i = 0; i < num_def_acls; i++, ace = ace->next) {
SEC_ACCESS acc;
-
- acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory);
- init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc,
- SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
- SEC_ACE_FLAG_INHERIT_ONLY|
- (ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0));
+
+ acc = map_canon_ace_perms(SNUM(conn),
+ &nt_acl_type,
+ ace->perms,
+ fsp->is_directory);
+ init_sec_ace(&nt_ace_list[num_aces++],
+ &ace->trustee,
+ nt_acl_type,
+ acc,
+ SEC_ACE_FLAG_OBJECT_INHERIT|
+ SEC_ACE_FLAG_CONTAINER_INHERIT|
+ SEC_ACE_FLAG_INHERIT_ONLY|
+ (ace->inherited ?
+ SEC_ACE_FLAG_INHERITED_ACE : 0));
}
- /* The User must have access to a profile share - even if we can't map the SID. */
+ /* The User must have access to a profile share - even
+ * if we can't map the SID. */
if (lp_profile_acls(SNUM(conn))) {
SEC_ACCESS acc;
-
+
init_sec_access(&acc,FILE_GENERIC_ALL);
init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc,
SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
@@ -2945,14 +2975,14 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
}
if (num_aces) {
- if((psa = make_sec_acl( main_loop_talloc_get(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) {
+ if((psa = make_sec_acl( talloc_tos(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) {
DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n"));
goto done;
}
}
} /* security_info & DACL_SECURITY_INFORMATION */
- psd = make_standard_sec_desc( main_loop_talloc_get(),
+ psd = make_standard_sec_desc( talloc_tos(),
(security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL,
(security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL,
psa,
@@ -3029,9 +3059,9 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
/* Case (2) / (3) */
if (lp_enable_privileges()) {
- BOOL has_take_ownership_priv = user_has_privileges(current_user.nt_user_token,
+ bool has_take_ownership_priv = user_has_privileges(current_user.nt_user_token,
&se_take_ownership);
- BOOL has_restore_priv = user_has_privileges(current_user.nt_user_token,
+ bool has_restore_priv = user_has_privileges(current_user.nt_user_token,
&se_restore);
/* Case (2) */
@@ -3049,6 +3079,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
/* Case (4). */
if (!lp_dos_filemode(SNUM(conn))) {
+ errno = EPERM;
return -1;
}
@@ -3076,33 +3107,224 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
return ret;
}
+static NTSTATUS append_ugw_ace(files_struct *fsp,
+ SMB_STRUCT_STAT *psbuf,
+ mode_t unx_mode,
+ int ugw,
+ SEC_ACE *se)
+{
+ mode_t perms;
+ SEC_ACCESS acc;
+ int nt_acl_type;
+ DOM_SID trustee;
+
+ switch (ugw) {
+ case S_IRUSR:
+ perms = unix_perms_to_acl_perms(unx_mode,
+ S_IRUSR,
+ S_IWUSR,
+ S_IXUSR);
+ uid_to_sid(&trustee, psbuf->st_uid );
+ break;
+ case S_IRGRP:
+ perms = unix_perms_to_acl_perms(unx_mode,
+ S_IRGRP,
+ S_IWGRP,
+ S_IXGRP);
+ gid_to_sid(&trustee, psbuf->st_gid );
+ break;
+ case S_IROTH:
+ perms = unix_perms_to_acl_perms(unx_mode,
+ S_IROTH,
+ S_IWOTH,
+ S_IXOTH);
+ sid_copy(&trustee, &global_sid_World);
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ acc = map_canon_ace_perms(SNUM(fsp->conn),
+ &nt_acl_type,
+ perms,
+ fsp->is_directory);
+
+ init_sec_ace(se,
+ &trustee,
+ nt_acl_type,
+ acc,
+ 0);
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ If this is an
+****************************************************************************/
+
+static NTSTATUS append_parent_acl(files_struct *fsp,
+ SMB_STRUCT_STAT *psbuf,
+ SEC_DESC *psd,
+ SEC_DESC **pp_new_sd)
+{
+ SEC_DESC *parent_sd = NULL;
+ files_struct *parent_fsp = NULL;
+ TALLOC_CTX *mem_ctx = talloc_parent(psd);
+ char *parent_name = NULL;
+ SEC_ACE *new_ace = NULL;
+ unsigned int num_aces = psd->dacl->num_aces;
+ SMB_STRUCT_STAT sbuf;
+ NTSTATUS status;
+ int info;
+ size_t sd_size;
+ unsigned int i, j;
+ mode_t unx_mode;
+
+ ZERO_STRUCT(sbuf);
+
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!parent_dirname_talloc(mem_ctx,
+ fsp->fsp_name,
+ &parent_name,
+ NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Create a default mode for u/g/w. */
+ unx_mode = unix_mode(fsp->conn,
+ aARCH | (fsp->is_directory ? aDIR : 0),
+ fsp->fsp_name,
+ parent_name);
+
+ status = open_directory(fsp->conn,
+ NULL,
+ parent_name,
+ &sbuf,
+ FILE_READ_ATTRIBUTES, /* Just a stat open */
+ FILE_SHARE_NONE, /* Ignored for stat opens */
+ FILE_OPEN,
+ 0,
+ INTERNAL_OPEN_ONLY,
+ &info,
+ &parent_fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ sd_size = SMB_VFS_GET_NT_ACL(parent_fsp, parent_fsp->fsp_name,
+ DACL_SECURITY_INFORMATION, &parent_sd );
+
+ close_file(parent_fsp, NORMAL_CLOSE);
+
+ if (!sd_size) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ /*
+ * Make room for potentially all the ACLs from
+ * the parent, plus the user/group/other triple.
+ */
+
+ num_aces += parent_sd->dacl->num_aces + 3;
+
+ if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, SEC_ACE,
+ num_aces)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ DEBUG(10,("append_parent_acl: parent ACL has %u entries. New "
+ "ACL has %u entries\n",
+ parent_sd->dacl->num_aces, num_aces ));
+
+ /* 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.
+ */
+
+ /*
+ * Append u/g/w.
+ */
+
+ status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRUSR, &new_ace[i++]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRGRP, &new_ace[i++]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = append_ugw_ace(fsp, psbuf, unx_mode, S_IROTH, &new_ace[i++]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Finally append any inherited ACEs. */
+ for (j = 0; j < parent_sd->dacl->num_aces; j++) {
+ SEC_ACE *se = &parent_sd->dacl->aces[j];
+ uint32 i_flags = se->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
+ SEC_ACE_FLAG_CONTAINER_INHERIT|
+ SEC_ACE_FLAG_INHERIT_ONLY);
+
+ if (fsp->is_directory) {
+ if (i_flags == SEC_ACE_FLAG_OBJECT_INHERIT) {
+ /* Should only apply to a file - ignore. */
+ continue;
+ }
+ } else {
+ if ((i_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
+ SEC_ACE_FLAG_INHERIT_ONLY)) !=
+ SEC_ACE_FLAG_OBJECT_INHERIT) {
+ /* Should not apply to a file - ignore. */
+ 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;
+ i++;
+ }
+
+ parent_sd->dacl->aces = new_ace;
+ parent_sd->dacl->num_aces = i;
+
+ *pp_new_sd = parent_sd;
+ return status;
+}
+
/****************************************************************************
Reply to set a security descriptor on an fsp. security_info_sent is the
description of the following NT ACL.
This should be the only external function needed for the UNIX style set ACL.
****************************************************************************/
-BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
+NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
{
connection_struct *conn = fsp->conn;
uid_t user = (uid_t)-1;
gid_t grp = (gid_t)-1;
- SMB_STRUCT_STAT sbuf;
+ SMB_STRUCT_STAT sbuf;
DOM_SID file_owner_sid;
DOM_SID file_grp_sid;
canon_ace *file_ace_list = NULL;
canon_ace *dir_ace_list = NULL;
- BOOL acl_perms = False;
+ bool acl_perms = False;
mode_t orig_mode = (mode_t)0;
- uid_t orig_uid;
- gid_t orig_gid;
- BOOL need_chown = False;
+ NTSTATUS status;
DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
if (!CAN_WRITE(conn)) {
DEBUG(10,("set acl rejected on read-only share\n"));
- return False;
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
/*
@@ -3111,40 +3333,29 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
if(fsp->is_directory || fsp->fh->fd == -1) {
if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
- return False;
+ return map_nt_error_from_unix(errno);
} else {
if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0)
- return False;
+ return map_nt_error_from_unix(errno);
}
/* Save the original elements we check against. */
orig_mode = sbuf.st_mode;
- orig_uid = sbuf.st_uid;
- orig_gid = sbuf.st_gid;
/*
* Unpack the user/group/world id's.
*/
- if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) {
- return False;
+ status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/*
* Do we need to chown ?
*/
- if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) {
- need_chown = True;
- }
-
- /*
- * Chown before setting ACL only if we don't change the user, or
- * if we change to the current user, but not if we want to give away
- * the file.
- */
-
- if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) {
+ if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
@@ -3152,7 +3363,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
if(try_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;
+ if (errno == EPERM) {
+ return NT_STATUS_INVALID_OWNER;
+ }
+ return map_nt_error_from_unix(errno);
}
/*
@@ -3162,32 +3376,39 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
if(fsp->is_directory) {
if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
- return False;
+ return map_nt_error_from_unix(errno);
}
} else {
int ret;
-
+
if(fsp->fh->fd == -1)
ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
else
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf);
-
+
if(ret != 0)
- return False;
+ return map_nt_error_from_unix(errno);
}
/* Save the original elements we check against. */
orig_mode = sbuf.st_mode;
- orig_uid = sbuf.st_uid;
- orig_gid = sbuf.st_gid;
-
- /* We did it, don't try again */
- need_chown = False;
}
create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
+ if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
+ psd->dacl != NULL &&
+ (psd->type & (SE_DESC_DACL_AUTO_INHERITED|
+ SE_DESC_DACL_AUTO_INHERIT_REQ))==
+ (SE_DESC_DACL_AUTO_INHERITED|
+ SE_DESC_DACL_AUTO_INHERIT_REQ) ) {
+ status = append_parent_acl(fsp, &sbuf, psd, &psd);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
&file_ace_list, &dir_ace_list, security_info_sent, psd);
@@ -3198,7 +3419,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: cannot set permissions\n"));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
/*
@@ -3207,8 +3428,8 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) {
- BOOL acl_set_support = False;
- BOOL ret = False;
+ bool acl_set_support = False;
+ bool ret = False;
/*
* Try using the POSIX ACL set first. Fall back to chmod if
@@ -3221,7 +3442,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return False;
+ return map_nt_error_from_unix(errno);
}
}
@@ -3231,7 +3452,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return False;
+ return map_nt_error_from_unix(errno);
}
} else {
@@ -3256,7 +3477,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return False;
+ return map_nt_error_from_unix(errno);
}
}
}
@@ -3279,7 +3500,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
free_canon_ace_list(dir_ace_list);
DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
fsp->fsp_name ));
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
if (orig_mode != posix_perms) {
@@ -3304,7 +3525,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return False;
+ return map_nt_error_from_unix(errno);
}
}
}
@@ -3315,20 +3536,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
free_canon_ace_list(dir_ace_list);
}
- /* Any chown pending? */
- if (need_chown) {
-
- 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) {
- 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;
- }
- }
-
- return True;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -3524,10 +3732,10 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode)
Check for an existing default POSIX ACL on a directory.
****************************************************************************/
-BOOL directory_has_default_acl(connection_struct *conn, const char *fname)
+bool directory_has_default_acl(connection_struct *conn, const char *fname)
{
SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT);
- BOOL has_acl = False;
+ bool has_acl = False;
SMB_ACL_ENTRY_T entry;
if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
@@ -3544,7 +3752,7 @@ BOOL directory_has_default_acl(connection_struct *conn, const char *fname)
Map from wire type to permset.
****************************************************************************/
-static BOOL unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset)
+static bool unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset)
{
if (wire_perm & ~(SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE)) {
return False;
@@ -3576,7 +3784,7 @@ static BOOL unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_
Map from wire type to tagtype.
****************************************************************************/
-static BOOL unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
+static bool unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
{
switch (wire_tt) {
case SMB_POSIX_ACL_USER_OBJ:
@@ -3699,7 +3907,7 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
on the directory.
****************************************************************************/
-BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf,
+bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf,
uint16 num_def_acls, const char *pdata)
{
SMB_ACL_T def_acl = NULL;
@@ -3744,12 +3952,12 @@ BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_
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 char *fname)
{
SMB_ACL_T file_acl = NULL;
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
- BOOL ret = False;
+ bool ret = False;
/* Create a new ACL with only 3 entries, u/g/w. */
SMB_ACL_T new_file_acl = SMB_VFS_SYS_ACL_INIT(conn, 3);
SMB_ACL_ENTRY_T user_ent = NULL;
@@ -3882,7 +4090,7 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
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 char *fname, uint16 num_acls, const char *pdata)
{
SMB_ACL_T file_acl = NULL;
@@ -3917,463 +4125,25 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
return True;
}
-/****************************************************************************
- Check for POSIX group ACLs. If none use stat entry.
- Return -1 if no match, 0 if match and denied, 1 if match and allowed.
-****************************************************************************/
-
-static int check_posix_acl_group_access(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
-{
- SMB_ACL_T posix_acl = NULL;
- int entry_id = SMB_ACL_FIRST_ENTRY;
- SMB_ACL_ENTRY_T entry;
- int i;
- BOOL seen_mask = False;
- BOOL seen_owning_group = False;
- int ret = -1;
- gid_t cu_gid;
-
- DEBUG(10,("check_posix_acl_group_access: requesting 0x%x on file %s\n",
- (unsigned int)access_mask, fname ));
-
- if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS)) == NULL) {
- goto check_stat;
- }
-
- /* First ensure the group mask allows group access. */
- /* Also check any user entries (these take preference over group). */
-
- while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
- SMB_ACL_TAG_T tagtype;
- SMB_ACL_PERMSET_T permset;
- int have_write = -1;
- int have_read = -1;
-
- /* get_next... */
- if (entry_id == SMB_ACL_FIRST_ENTRY)
- entry_id = SMB_ACL_NEXT_ENTRY;
-
- if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
- goto check_stat;
- }
-
- if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
- goto check_stat;
- }
-
- have_read = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ);
- if (have_read == -1) {
- goto check_stat;
- }
-
- have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE);
- if (have_write == -1) {
- goto check_stat;
- }
-
- /*
- * Solaris returns 2 for this if write is available.
- * canonicalize to 0 or 1.
- */
- have_write = (have_write ? 1 : 0);
- have_read = (have_read ? 1 : 0);
-
- switch(tagtype) {
- case SMB_ACL_MASK:
- seen_mask = True;
- switch (access_mask) {
- case FILE_READ_DATA:
- if (!have_read) {
- ret = -1;
- DEBUG(10,("check_posix_acl_group_access: file %s "
- "refusing read due to mask.\n", fname));
- goto done;
- }
- break;
- case FILE_WRITE_DATA:
- if (!have_write) {
- ret = -1;
- DEBUG(10,("check_posix_acl_group_access: file %s "
- "refusing write due to mask.\n", fname));
- goto done;
- }
- break;
- default: /* FILE_READ_DATA|FILE_WRITE_DATA */
- if (!have_write || !have_read) {
- ret = -1;
- DEBUG(10,("check_posix_acl_group_access: file %s "
- "refusing read/write due to mask.\n", fname));
- goto done;
- }
- break;
- }
- break;
- case SMB_ACL_USER:
- {
- /* Check against current_user.ut.uid. */
- uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
- if (puid == NULL) {
- goto check_stat;
- }
- if (current_user.ut.uid == *puid) {
- /* We have a uid match but we must ensure we have seen the acl mask. */
- switch (access_mask) {
- case FILE_READ_DATA:
- ret = have_read;
- break;
- case FILE_WRITE_DATA:
- ret = have_write;
- break;
- default: /* FILE_READ_DATA|FILE_WRITE_DATA */
- ret = (have_write & have_read);
- break;
- }
- DEBUG(10,("check_posix_acl_group_access: file %s "
- "match on user %u -> %s.\n",
- fname, (unsigned int)*puid,
- ret ? "can access" : "cannot access"));
- if (seen_mask) {
- goto done;
- }
- }
- break;
- }
- default:
- continue;
- }
- }
-
- /* If ret is anything other than -1 we matched on a user entry. */
- if (ret != -1) {
- goto done;
- }
-
- /* Next check all group entries. */
- entry_id = SMB_ACL_FIRST_ENTRY;
- while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
- SMB_ACL_TAG_T tagtype;
- SMB_ACL_PERMSET_T permset;
- int have_write = -1;
- int have_read = -1;
-
- /* get_next... */
- if (entry_id == SMB_ACL_FIRST_ENTRY)
- entry_id = SMB_ACL_NEXT_ENTRY;
-
- if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
- goto check_stat;
- }
-
- if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
- goto check_stat;
- }
-
- have_read = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ);
- if (have_read == -1) {
- goto check_stat;
- }
-
- have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE);
- if (have_write == -1) {
- goto check_stat;
- }
-
- /*
- * Solaris returns 2 for this if write is available.
- * canonicalize to 0 or 1.
- */
- have_write = (have_write ? 1 : 0);
- have_read = (have_read ? 1 : 0);
-
- switch(tagtype) {
- case SMB_ACL_GROUP:
- case SMB_ACL_GROUP_OBJ:
- {
- gid_t *pgid = NULL;
-
- if (tagtype == SMB_ACL_GROUP) {
- pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
- } else {
- seen_owning_group = True;
- pgid = &psbuf->st_gid;
- }
- if (pgid == NULL) {
- goto check_stat;
- }
-
- /*
- * Does it match the current effective group
- * or supplementary groups ?
- */
- for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1;
- cu_gid = get_current_user_gid_next(&i)) {
- if (cu_gid == *pgid) {
- switch (access_mask) {
- case FILE_READ_DATA:
- ret = have_read;
- break;
- case FILE_WRITE_DATA:
- ret = have_write;
- break;
- default: /* FILE_READ_DATA|FILE_WRITE_DATA */
- ret = (have_write & have_read);
- break;
- }
-
- DEBUG(10,("check_posix_acl_group_access: file %s "
- "match on group %u -> can access.\n",
- fname, (unsigned int)cu_gid ));
-
- /* If we don't have access permission this entry doesn't
- terminate the enumeration of the entries. */
- if (ret) {
- goto done;
- }
- /* But does terminate the group iteration. */
- break;
- }
- }
- break;
- }
- default:
- continue;
- }
- }
-
- /* If ret is -1 here we didn't match on the user entry or
- supplemental group entries. */
-
- DEBUG(10,("check_posix_acl_group_access: ret = %d before check_stat:\n", ret));
-
- check_stat:
-
- /*
- * We only check the S_I[RW]GRP permissions if we haven't already
- * seen an owning group SMB_ACL_GROUP_OBJ ace entry. If there is an
- * SMB_ACL_GROUP_OBJ ace entry then the group bits in st_gid are
- * the same as the SMB_ACL_MASK bits, not the SMB_ACL_GROUP_OBJ
- * bits. Thanks to Marc Cousin for pointing
- * this out. JRA.
- */
-
- if (!seen_owning_group) {
- /* Do we match on the owning group entry ? */
- /*
- * Does it match the current effective group
- * or supplementary groups ?
- */
- for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1;
- cu_gid = get_current_user_gid_next(&i)) {
- if (cu_gid == psbuf->st_gid) {
- switch (access_mask) {
- case FILE_READ_DATA:
- ret = (psbuf->st_mode & S_IRGRP) ? 1 : 0;
- break;
- case FILE_WRITE_DATA:
- ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0;
- break;
- default: /* FILE_READ_DATA|FILE_WRITE_DATA */
- if ((psbuf->st_mode & (S_IWGRP|S_IRGRP)) == (S_IWGRP|S_IRGRP)) {
- ret = 1;
- } else {
- ret = 0;
- }
- break;
- }
- DEBUG(10,("check_posix_acl_group_access: file %s "
- "match on owning group %u -> %s.\n",
- fname, (unsigned int)psbuf->st_gid,
- ret ? "can access" : "cannot access"));
- break;
- }
- }
-
- if (cu_gid == (gid_t)-1) {
- DEBUG(10,("check_posix_acl_group_access: file %s "
- "failed to match on user or group in token (ret = %d).\n",
- fname, ret ));
- }
- }
-
- done:
-
- if (posix_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
- }
-
- DEBUG(10,("check_posix_acl_group_access: file %s returning (ret = %d).\n", fname, ret ));
- return ret;
-}
-
-/****************************************************************************
- Actually emulate the in-kernel access checking for delete access. We need
- this to successfully return ACCESS_DENIED on a file open for delete access.
-****************************************************************************/
-
-BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
-{
- SMB_STRUCT_STAT sbuf;
- pstring dname;
- int ret;
-
- if (!CAN_WRITE(conn)) {
- return False;
- }
-
- /* Get the parent directory permission mask and owners. */
- pstrcpy(dname, parent_dirname(fname));
- if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
- return False;
- }
- if (!S_ISDIR(sbuf.st_mode)) {
- return False;
- }
- if (current_user.ut.uid == 0 || conn->admin_user) {
- /* I'm sorry sir, I didn't know you were root... */
- return True;
- }
-
- /* Check primary owner write access. */
- if (current_user.ut.uid == sbuf.st_uid) {
- return (sbuf.st_mode & S_IWUSR) ? True : False;
- }
-
-#ifdef S_ISVTX
- /* sticky bit means delete only by owner or root. */
- if (sbuf.st_mode & S_ISVTX) {
- SMB_STRUCT_STAT sbuf_file;
- if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
- if (errno == ENOENT) {
- /* If the file doesn't already exist then
- * yes we'll be able to delete it. */
- return True;
- }
- return False;
- }
- /*
- * Patch from SATOH Fumiyasu
- * for bug #3348. Don't assume owning sticky bit
- * directory means write access allowed.
- */
- if (current_user.ut.uid != sbuf_file.st_uid) {
- return False;
- }
- }
-#endif
-
- /* Check group or explicit user acl entry write access. */
- ret = check_posix_acl_group_access(conn, dname, &sbuf, FILE_WRITE_DATA);
- if (ret == 0 || ret == 1) {
- return ret ? True : False;
- }
-
- /* Finally check other write access. */
- return (sbuf.st_mode & S_IWOTH) ? True : False;
-}
-
-/****************************************************************************
- Actually emulate the in-kernel access checking for read/write access. We need
- this to successfully check for ability to write for dos filetimes.
- Note this doesn't take into account share write permissions.
-****************************************************************************/
-
-BOOL can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
-{
- int ret;
-
- if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
- return False;
- }
- access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA);
-
- DEBUG(10,("can_access_file: requesting 0x%x on file %s\n",
- (unsigned int)access_mask, fname ));
-
- if (current_user.ut.uid == 0 || conn->admin_user) {
- /* I'm sorry sir, I didn't know you were root... */
- return True;
- }
-
- if (!VALID_STAT(*psbuf)) {
- /* Get the file permission mask and owners. */
- if(SMB_VFS_STAT(conn, fname, psbuf) != 0) {
- return False;
- }
- }
-
- /* Check primary owner access. */
- if (current_user.ut.uid == psbuf->st_uid) {
- switch (access_mask) {
- case FILE_READ_DATA:
- return (psbuf->st_mode & S_IRUSR) ? True : False;
-
- case FILE_WRITE_DATA:
- return (psbuf->st_mode & S_IWUSR) ? True : False;
-
- default: /* FILE_READ_DATA|FILE_WRITE_DATA */
-
- if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) {
- return True;
- } else {
- return False;
- }
- }
- }
-
- /* Check group or explicit user acl entry access. */
- ret = check_posix_acl_group_access(conn, fname, psbuf, access_mask);
- if (ret == 0 || ret == 1) {
- return ret ? True : False;
- }
-
- /* Finally check other access. */
- switch (access_mask) {
- case FILE_READ_DATA:
- return (psbuf->st_mode & S_IROTH) ? True : False;
-
- case FILE_WRITE_DATA:
- return (psbuf->st_mode & S_IWOTH) ? True : False;
-
- default: /* FILE_READ_DATA|FILE_WRITE_DATA */
-
- if ((psbuf->st_mode & (S_IWOTH|S_IROTH)) == (S_IWOTH|S_IROTH)) {
- return True;
- }
- }
- return False;
-}
-
-/****************************************************************************
- Userspace check for write access.
- Note this doesn't take into account share write permissions.
-****************************************************************************/
-
-BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
-{
- return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA);
-}
-
/********************************************************************
Pull the NT ACL from a file on disk or the OpenEventlog() access
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().
-
+
Assume we are dealing with files (for now)
********************************************************************/
-SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
+SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
{
SEC_DESC *psd, *ret_sd;
connection_struct conn;
files_struct finfo;
struct fd_handle fh;
- pstring path;
- pstring filename;
-
+
ZERO_STRUCT( conn );
-
+
if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
return NULL;
@@ -4386,35 +4156,33 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
}
conn.params->service = -1;
-
- pstrcpy( path, "/" );
- set_conn_connectpath(&conn, path);
-
+
+ set_conn_connectpath(&conn, "/");
+
if (!smbd_vfs_init(&conn)) {
DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
conn_free_internal( &conn );
return NULL;
}
-
+
ZERO_STRUCT( finfo );
ZERO_STRUCT( fh );
-
+
finfo.fnum = -1;
finfo.conn = &conn;
finfo.fh = &fh;
finfo.fh->fd = -1;
- pstrcpy( filename, fname );
- finfo.fsp_name = filename;
-
+ finfo.fsp_name = CONST_DISCARD(char *,fname);
+
if (get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ) == 0) {
DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
conn_free_internal( &conn );
return NULL;
}
-
+
ret_sd = dup_sec_desc( ctx, psd );
-
+
conn_free_internal( &conn );
-
+
return ret_sd;
}