summaryrefslogtreecommitdiffstats
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.c260
1 files changed, 162 insertions, 98 deletions
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 0c7f4b7bb7f..76eee9b56aa 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -2560,36 +2560,23 @@ static bool current_user_in_group(gid_t gid)
****************************************************************************/
static bool acl_group_override(connection_struct *conn,
- const SMB_STRUCT_STAT *psbuf,
- const char *fname)
+ const struct smb_filename *smb_fname)
{
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
-
if ((errno != EPERM) && (errno != EACCES)) {
return false;
}
/* file primary group == user primary or supplementary group */
if (lp_acl_group_control(SNUM(conn)) &&
- current_user_in_group(psbuf->st_ex_gid)) {
+ current_user_in_group(smb_fname->st.st_ex_gid)) {
return true;
}
- status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
- &smb_fname);
-
- if (!NT_STATUS_IS_OK(status)) {
- return false;
- }
-
/* user has writeable permission */
if (lp_dos_filemode(SNUM(conn)) &&
can_write_to_file(conn, smb_fname)) {
- TALLOC_FREE(smb_fname);
return true;
}
- TALLOC_FREE(smb_fname);
return false;
}
@@ -2615,6 +2602,14 @@ static bool set_canon_ace_list(files_struct *fsp,
SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
bool needs_mask = False;
mode_t mask_perms = 0;
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+
+ status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
+ psbuf, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
#if defined(POSIX_ACL_NEEDS_MASK)
/* HP-UX always wants to have a mask (called "class" there). */
@@ -2632,7 +2627,7 @@ static bool set_canon_ace_list(files_struct *fsp,
default_ace ? "default" : "file", strerror(errno) ));
}
*pacl_set_support = False;
- return False;
+ goto fail;
}
if( DEBUGLVL( 10 )) {
@@ -2772,7 +2767,8 @@ static bool set_canon_ace_list(files_struct *fsp,
*/
if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
- if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) {
+ if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname->base_name,
+ the_acl_type, the_acl) == -1) {
/*
* Some systems allow all the above calls and only fail with no ACL support
* when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
@@ -2781,14 +2777,18 @@ static bool set_canon_ace_list(files_struct *fsp,
*pacl_set_support = False;
}
- if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
+ if (acl_group_override(conn, smb_fname)) {
int sret;
- DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
- fsp->fsp_name ));
+ DEBUG(5,("set_canon_ace_list: acl group "
+ "control on and current user in file "
+ "%s primary group.\n",
+ smb_fname_str_dbg(smb_fname)));
become_root();
- sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl);
+ sret = SMB_VFS_SYS_ACL_SET_FILE(conn,
+ smb_fname->base_name, the_acl_type,
+ the_acl);
unbecome_root();
if (sret == 0) {
ret = True;
@@ -2796,9 +2796,13 @@ static bool set_canon_ace_list(files_struct *fsp,
}
if (ret == False) {
- DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
- the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
- fsp->fsp_name, strerror(errno) ));
+ DEBUG(2,("set_canon_ace_list: "
+ "sys_acl_set_file type %s failed for "
+ "file %s (%s).\n",
+ the_acl_type == SMB_ACL_TYPE_DEFAULT ?
+ "directory default" : "file",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
goto fail;
}
}
@@ -2812,11 +2816,13 @@ static bool set_canon_ace_list(files_struct *fsp,
*pacl_set_support = False;
}
- if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
+ if (acl_group_override(conn, smb_fname)) {
int sret;
- DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
- fsp->fsp_name ));
+ DEBUG(5,("set_canon_ace_list: acl group "
+ "control on and current user in file "
+ "%s primary group.\n",
+ smb_fname_str_dbg(smb_fname)));
become_root();
sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl);
@@ -2827,8 +2833,11 @@ static bool set_canon_ace_list(files_struct *fsp,
}
if (ret == False) {
- DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
- fsp->fsp_name, strerror(errno) ));
+ DEBUG(2,("set_canon_ace_list: "
+ "sys_acl_set_file failed for file %s "
+ "(%s).\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno) ));
goto fail;
}
}
@@ -2841,6 +2850,7 @@ static bool set_canon_ace_list(files_struct *fsp,
if (the_acl != NULL) {
SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
}
+ TALLOC_FREE(smb_fname);
return ret;
}
@@ -3405,11 +3415,11 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
then allow chown to the currently authenticated user.
****************************************************************************/
-int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
+int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
+ uid_t uid, gid_t gid)
{
int ret;
files_struct *fsp;
- SMB_STRUCT_STAT st;
if(!CAN_WRITE(conn)) {
return -1;
@@ -3417,7 +3427,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
/* Case (1). */
/* try the direct way first */
- ret = SMB_VFS_CHOWN(conn, fname, uid, gid);
+ ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, gid);
if (ret == 0)
return 0;
@@ -3436,7 +3446,8 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
become_root();
/* Keep the current file gid the same - take ownership doesn't imply group change. */
- ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1);
+ ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid,
+ (gid_t)-1);
unbecome_root();
return ret;
}
@@ -3457,11 +3468,11 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
return -1;
}
- if (vfs_stat_smb_fname(conn,fname,&st)) {
+ if (SMB_VFS_STAT(conn, smb_fname)) {
return -1;
}
- if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, &st, &fsp))) {
+ if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname, &fsp))) {
return -1;
}
@@ -3507,8 +3518,8 @@ NTSTATUS append_parent_acl(files_struct *fsp,
return NT_STATUS_NO_MEMORY;
}
- status = create_synthetic_smb_fname_split(mem_ctx, parent_name, NULL,
- &smb_dname);
+ status = create_synthetic_smb_fname(mem_ctx, parent_name, NULL, NULL,
+ &smb_dname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
@@ -3530,16 +3541,16 @@ NTSTATUS append_parent_acl(files_struct *fsp,
&parent_fsp, /* result */
&info); /* pinfo */
- TALLOC_FREE(smb_fname);
-
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(smb_dname);
return status;
}
- status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, parent_fsp->fsp_name,
+ status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, smb_dname->base_name,
DACL_SECURITY_INFORMATION, &parent_sd );
close_file(NULL, parent_fsp, NORMAL_CLOSE);
+ TALLOC_FREE(smb_dname);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -3686,7 +3697,6 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
connection_struct *conn = fsp->conn;
uid_t user = (uid_t)-1;
gid_t grp = (gid_t)-1;
- SMB_STRUCT_STAT sbuf;
DOM_SID file_owner_sid;
DOM_SID file_grp_sid;
canon_ace *file_ace_list = NULL;
@@ -3697,12 +3707,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
bool set_acl_as_root = false;
bool acl_set_support = false;
bool ret = false;
+ struct smb_filename *smb_fname = NULL;
+
+ status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
+ NULL, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
- DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
+ DEBUG(10,("set_nt_acl: called for file %s\n",
+ smb_fname_str_dbg(smb_fname)));
if (!CAN_WRITE(conn)) {
DEBUG(10,("set acl rejected on read-only share\n"));
- return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ status = NT_STATUS_MEDIA_WRITE_PROTECTED;
+ goto out;
}
/*
@@ -3710,15 +3729,19 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
*/
if(fsp->is_directory || fsp->fh->fd == -1) {
- if(vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, &sbuf) != 0)
- return map_nt_error_from_unix(errno);
+ if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) {
+ status = map_nt_error_from_unix(errno);
+ goto out;
+ }
} else {
- if(SMB_VFS_FSTAT(fsp, &sbuf) != 0)
- return map_nt_error_from_unix(errno);
+ if(SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
+ status = map_nt_error_from_unix(errno);
+ goto out;
+ }
}
/* Save the original element we check against. */
- orig_mode = sbuf.st_ex_mode;
+ orig_mode = smb_fname->st.st_ex_mode;
/*
* Unpack the user/group/world id's.
@@ -3726,7 +3749,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
/*
@@ -3735,18 +3758,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
* Noticed by Simo.
*/
- if (((user != (uid_t)-1) && (sbuf.st_ex_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_ex_gid != grp))) {
+ if (((user != (uid_t)-1) && (smb_fname->st.st_ex_uid != user)) ||
+ (( grp != (gid_t)-1) && (smb_fname->st.st_ex_gid != grp))) {
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) ));
+ smb_fname_str_dbg(smb_fname), (unsigned int)user,
+ (unsigned int)grp ));
+
+ if(try_chown(fsp->conn, smb_fname, user, grp) == -1) {
+ DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error "
+ "= %s.\n", smb_fname_str_dbg(smb_fname),
+ (unsigned int)user, (unsigned int)grp,
+ strerror(errno)));
if (errno == EPERM) {
- return NT_STATUS_INVALID_OWNER;
+ status = NT_STATUS_INVALID_OWNER;
+ goto out;
}
- return map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
/*
@@ -3755,27 +3784,25 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
*/
if(fsp->is_directory) {
- if(vfs_stat_smb_fname(fsp->conn, fsp->fsp_name,
- &sbuf) != 0) {
- return map_nt_error_from_unix(errno);
+ if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) {
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
} else {
int sret;
if(fsp->fh->fd == -1)
- sret = vfs_stat_smb_fname(fsp->conn,
- fsp->fsp_name,
- &sbuf);
+ sret = SMB_VFS_STAT(fsp->conn, smb_fname);
else
- sret = SMB_VFS_FSTAT(fsp, &sbuf);
+ sret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
if(sret != 0)
return map_nt_error_from_unix(errno);
}
/* Save the original element we check against. */
- orig_mode = sbuf.st_ex_mode;
+ orig_mode = smb_fname->st.st_ex_mode;
/* If we successfully chowned, we know we must
* be able to set the acl, so do it as root.
@@ -3783,21 +3810,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
set_acl_as_root = true;
}
- create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
+ create_file_sids(&smb_fname->st, &file_owner_sid, &file_grp_sid);
- acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
- &file_ace_list, &dir_ace_list, security_info_sent, psd);
+ acl_perms = unpack_canon_ace(fsp, &smb_fname->st, &file_owner_sid,
+ &file_grp_sid, &file_ace_list,
+ &dir_ace_list, security_info_sent, psd);
/* Ignore W2K traverse DACL set. */
if (!file_ace_list && !dir_ace_list) {
- return NT_STATUS_OK;
+ status = NT_STATUS_OK;
+ goto out;
}
if (!acl_perms) {
DEBUG(3,("set_nt_acl: cannot set permissions\n"));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_ACCESS_DENIED;
+ goto out;
}
/*
@@ -3807,7 +3837,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) {
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return NT_STATUS_OK;
+ status = NT_STATUS_OK;
+ goto out;
}
/*
@@ -3819,15 +3850,19 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (set_acl_as_root) {
become_root();
}
- ret = set_canon_ace_list(fsp, file_ace_list, False, &sbuf, &acl_set_support);
+ ret = set_canon_ace_list(fsp, file_ace_list, false,
+ &smb_fname->st, &acl_set_support);
if (set_acl_as_root) {
unbecome_root();
}
if (acl_set_support && ret == false) {
- DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
+ DEBUG(3,("set_nt_acl: failed to set file acl on file "
+ "%s (%s).\n", smb_fname_str_dbg(smb_fname),
+ strerror(errno)));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
}
@@ -3836,15 +3871,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (set_acl_as_root) {
become_root();
}
- ret = set_canon_ace_list(fsp, dir_ace_list, True, &sbuf, &acl_set_support);
+ ret = set_canon_ace_list(fsp, dir_ace_list, true,
+ &smb_fname->st,
+ &acl_set_support);
if (set_acl_as_root) {
unbecome_root();
}
if (ret == false) {
- DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
+ DEBUG(3,("set_nt_acl: failed to set default "
+ "acl on directory %s (%s).\n",
+ smb_fname_str_dbg(smb_fname),
+ strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
} else {
int sret = -1;
@@ -3856,18 +3897,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (set_acl_as_root) {
become_root();
}
- sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
+ sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn,
+ smb_fname->base_name);
if (set_acl_as_root) {
unbecome_root();
}
if (sret == -1) {
- if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
- DEBUG(5,("set_nt_acl: acl group control on and "
- "current user in file %s primary group. Override delete_def_acl\n",
- fsp->fsp_name ));
+ if (acl_group_override(conn, smb_fname)) {
+ DEBUG(5,("set_nt_acl: acl group "
+ "control on and current user "
+ "in file %s primary group. "
+ "Override delete_def_acl\n",
+ smb_fname_str_dbg(smb_fname)));
become_root();
- sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
+ sret =
+ SMB_VFS_SYS_ACL_DELETE_DEF_FILE(
+ conn,
+ smb_fname->base_name);
unbecome_root();
}
@@ -3875,7 +3922,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
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 map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
}
}
@@ -3904,41 +3952,54 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
free_canon_ace_list(file_ace_list);
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 NT_STATUS_ACCESS_DENIED;
+ DEBUG(3,("set_nt_acl: failed to convert file acl to "
+ "posix permissions for file %s.\n",
+ smb_fname_str_dbg(smb_fname)));
+ status = NT_STATUS_ACCESS_DENIED;
+ goto out;
}
if (orig_mode != posix_perms) {
int sret = -1;
DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
- fsp->fsp_name, (unsigned int)posix_perms ));
+ smb_fname_str_dbg(smb_fname),
+ (unsigned int)posix_perms));
if (set_acl_as_root) {
become_root();
}
- sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
+ sret = SMB_VFS_CHMOD(conn, smb_fname->base_name,
+ posix_perms);
if (set_acl_as_root) {
unbecome_root();
}
if(sret == -1) {
- if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
- DEBUG(5,("set_nt_acl: acl group control on and "
- "current user in file %s primary group. Override chmod\n",
- fsp->fsp_name ));
+ if (acl_group_override(conn, smb_fname)) {
+ DEBUG(5,("set_nt_acl: acl group "
+ "control on and current user "
+ "in file %s primary group. "
+ "Override chmod\n",
+ smb_fname_str_dbg(smb_fname)));
become_root();
- sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
+ sret =
+ SMB_VFS_CHMOD(conn,
+ smb_fname->base_name,
+ posix_perms);
unbecome_root();
}
if (sret == -1) {
- DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
- fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
+ DEBUG(3,("set_nt_acl: chmod %s, 0%o "
+ "failed. Error = %s.\n",
+ smb_fname_str_dbg(smb_fname),
+ (unsigned int)posix_perms,
+ strerror(errno)));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ goto out;
}
}
}
@@ -3947,7 +4008,10 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return NT_STATUS_OK;
+ status = NT_STATUS_OK;
+ out:
+ TALLOC_FREE(smb_fname);
+ return status;
}
/****************************************************************************