Unpack a SEC_DESC into a UNIX owner and group.
****************************************************************************/
-NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
+BOOL 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;
if(security_info_sent == 0) {
DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
- return NT_STATUS_OK;
+ return True;
}
/*
DEBUG(3,("unpack_nt_owners: unable to validate"
" owner sid for %s\n",
sid_string_static(&owner_sid)));
- return NT_STATUS_INVALID_OWNER;
+ return False;
}
}
- DEBUG(3,("unpack_nt_owners: owner sid mapped to uid %u\n",
- (unsigned int)*puser ));
}
/*
} else {
DEBUG(3,("unpack_nt_owners: unable to validate"
" group sid.\n"));
- return NT_STATUS_INVALID_OWNER;
+ return False;
}
}
- 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 NT_STATUS_OK;
+ return True;
}
/****************************************************************************
/* Case (4). */
if (!lp_dos_filemode(SNUM(conn))) {
- errno = EPERM;
return -1;
}
{
mode_t perms;
SEC_ACCESS acc;
- int acl_type;
+ int nt_acl_type; /* Tru64 has "acl_type" as a macro.. */
DOM_SID trustee;
switch (ugw) {
return NT_STATUS_INVALID_PARAMETER;
}
acc = map_canon_ace_perms(SNUM(fsp->conn),
- &acl_type,
+ &nt_acl_type,
perms,
fsp->is_directory);
init_sec_ace(se,
&trustee,
- acl_type,
+ nt_acl_type,
acc,
0);
return NT_STATUS_OK;
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,
+ 0,
&info,
&parent_fsp);
This should be the only external function needed for the UNIX style set ACL.
****************************************************************************/
-NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
+BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
{
connection_struct *conn = fsp->conn;
uid_t user = (uid_t)-1;
canon_ace *dir_ace_list = NULL;
BOOL acl_perms = False;
mode_t orig_mode = (mode_t)0;
- NTSTATUS status;
+ uid_t orig_uid;
+ gid_t orig_gid;
+ BOOL need_chown = False;
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 NT_STATUS_MEDIA_WRITE_PROTECTED;
+ return False;
}
/*
if(fsp->is_directory || fsp->fh->fd == -1) {
if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
- return map_nt_error_from_unix(errno);
+ return False;
} else {
if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0)
- return map_nt_error_from_unix(errno);
+ return False;
}
/* 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.
*/
- status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) {
+ return False;
}
/*
* Do we need to chown ?
*/
- if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
+ 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)) {
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) ));
- if (errno == EPERM) {
- return NT_STATUS_INVALID_OWNER;
- }
- return map_nt_error_from_unix(errno);
+ return False;
}
/*
if(fsp->is_directory) {
if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
- return map_nt_error_from_unix(errno);
+ return False;
}
} else {
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf);
if(ret != 0)
- return map_nt_error_from_unix(errno);
+ return False;
}
/* 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);
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);
+ NTSTATUS status = append_parent_acl(fsp, &sbuf, psd, &psd);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ return False;
}
}
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;
+ return False;
}
/*
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 map_nt_error_from_unix(errno);
+ return False;
}
}
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 map_nt_error_from_unix(errno);
+ return False;
}
} else {
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);
+ return False;
}
}
}
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;
+ return False;
}
if (orig_mode != posix_perms) {
fsp->fsp_name, (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);
+ return False;
}
}
}
free_canon_ace_list(dir_ace_list);
}
- return NT_STATUS_OK;
+ /* 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;
}
/****************************************************************************