*/
#include "includes.h"
+#include "smbd/smbd.h"
+#include "system/filesys.h"
+#include "../libcli/security/security.h"
+#include "trans2.h"
+#include "passdb/lookup_sid.h"
extern const struct generic_mapping file_generic_mapping;
struct canon_ace *next, *prev;
SMB_ACL_TAG_T type;
mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */
- DOM_SID trustee;
+ struct dom_sid trustee;
enum ace_owner owner_type;
enum ace_attribute attr;
posix_id unix_ug;
paie->ace_flags = SEC_ACE_FLAG_INHERITED_ACE;
if (!get_pai_owner_type(paie, entry_offset)) {
+ SAFE_FREE(paie);
return NULL;
}
memset(paiv, '\0', sizeof(struct pai_val));
paiv->sd_type = (CVAL(buf,PAI_V1_FLAG_OFFSET) == PAI_V1_ACL_FLAG_PROTECTED) ?
- SE_DESC_DACL_PROTECTED : 0;
+ SEC_DESC_DACL_PROTECTED : 0;
paiv->num_entries = SVAL(buf,PAI_V1_NUM_ENTRIES_OFFSET);
paiv->num_def_entries = SVAL(buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
paie->ace_flags = CVAL(entry_offset,0);
if (!get_pai_owner_type(paie, entry_offset+1)) {
+ SAFE_FREE(paie);
return NULL;
}
if (!def_entry) {
Function to create owner and group SIDs from a SMB_STRUCT_STAT.
****************************************************************************/
-void create_file_sids(const SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid)
+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 );
* ensure the POSIX ACL types are the same. */
if (!dir_acl) {
- can_merge = (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+ can_merge = (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
(curr_ace->attr == curr_ace_outer->attr));
} else {
- can_merge = (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+ can_merge = (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
(curr_ace->type == curr_ace_outer->type) &&
(curr_ace->attr == curr_ace_outer->attr));
}
* we've put on the ACL, we know the deny must be the first one.
*/
- if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+ if (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
(curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
if( DEBUGLVL( 10 )) {
}
/****************************************************************************
- Unpack a SEC_DESC into a UNIX owner and group.
+ Unpack a struct security_descriptor into a UNIX owner and group.
****************************************************************************/
NTSTATUS unpack_nt_owners(struct connection_struct *conn,
uid_t *puser, gid_t *pgrp,
- uint32 security_info_sent, const SEC_DESC *psd)
+ uint32 security_info_sent, const struct
+ security_descriptor *psd)
{
- DOM_SID owner_sid;
- DOM_SID grp_sid;
+ struct dom_sid owner_sid;
+ struct dom_sid grp_sid;
*puser = (uid_t)-1;
*pgrp = (gid_t)-1;
* This may be a group chown only set.
*/
- if (security_info_sent & OWNER_SECURITY_INFORMATION) {
+ if (security_info_sent & SECINFO_OWNER) {
sid_copy(&owner_sid, psd->owner_sid);
if (!sid_to_uid(&owner_sid, puser)) {
if (lp_force_unknown_acl_user(SNUM(conn))) {
* This may be an owner chown only set.
*/
- if (security_info_sent & GROUP_SECURITY_INFORMATION) {
+ if (security_info_sent & SECINFO_GROUP) {
sid_copy(&grp_sid, psd->group_sid);
if (!sid_to_gid( &grp_sid, pgrp)) {
if (lp_force_unknown_acl_user(SNUM(conn))) {
/* "Everyone" always matches every uid. */
- if (sid_equal(&group_ace->trustee, &global_sid_World))
+ if (dom_sid_equal(&group_ace->trustee, &global_sid_World))
return True;
/*
* and don't need to do the complex user_in_group_sid() call
*/
if (uid_ace->unix_ug.uid == get_current_uid(conn)) {
- const UNIX_USER_TOKEN *curr_utok = NULL;
+ const struct security_unix_token *curr_utok = NULL;
size_t i;
if (group_ace->unix_ug.gid == get_current_gid(conn)) {
static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace,
const struct share_params *params,
const bool is_directory,
- const DOM_SID *pfile_owner_sid,
- const DOM_SID *pfile_grp_sid,
+ const struct dom_sid *pfile_owner_sid,
+ const struct dom_sid *pfile_grp_sid,
const SMB_STRUCT_STAT *pst,
bool setting_acl)
{
file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ.
****************************************************************************/
-static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid)
+static void check_owning_objs(canon_ace *ace, struct dom_sid *pfile_owner_sid, struct dom_sid *pfile_grp_sid)
{
bool got_user_obj, got_group_obj;
canon_ace *current_ace;
for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
if (!got_user_obj && current_ace->owner_type == UID_ACE &&
- sid_equal(¤t_ace->trustee, pfile_owner_sid)) {
+ dom_sid_equal(¤t_ace->trustee, pfile_owner_sid)) {
current_ace->type = SMB_ACL_USER_OBJ;
got_user_obj = True;
}
if (!got_group_obj && current_ace->owner_type == GID_ACE &&
- sid_equal(¤t_ace->trustee, pfile_grp_sid)) {
+ dom_sid_equal(¤t_ace->trustee, pfile_grp_sid)) {
current_ace->type = SMB_ACL_GROUP_OBJ;
got_group_obj = True;
}
*/
if (ace->type == SMB_ACL_USER_OBJ &&
- !(sid_equal(&ace->trustee, &global_sid_Creator_Owner))) {
+ !(dom_sid_equal(&ace->trustee, &global_sid_Creator_Owner))) {
canon_ace *dup_ace = dup_canon_ace(ace);
if (dup_ace == NULL) {
}
if (ace->type == SMB_ACL_GROUP_OBJ &&
- !(sid_equal(&ace->trustee, &global_sid_Creator_Group))) {
+ !(dom_sid_equal(&ace->trustee, &global_sid_Creator_Group))) {
canon_ace *dup_ace = dup_canon_ace(ace);
if (dup_ace == NULL) {
}
/****************************************************************************
- Unpack a SEC_DESC into two canonical ace lists.
+ Unpack a struct security_descriptor into two canonical ace lists.
****************************************************************************/
static bool create_canon_ace_lists(files_struct *fsp,
const SMB_STRUCT_STAT *pst,
- DOM_SID *pfile_owner_sid,
- DOM_SID *pfile_grp_sid,
+ struct dom_sid *pfile_owner_sid,
+ struct dom_sid *pfile_grp_sid,
canon_ace **ppfile_ace,
canon_ace **ppdir_ace,
const struct security_acl *dacl)
if (psa1->access_mask != psa2->access_mask)
continue;
- if (!sid_equal(&psa1->trustee, &psa2->trustee))
+ if (!dom_sid_equal(&psa1->trustee, &psa2->trustee))
continue;
/*
struct security_ace *psa = &dacl->aces[i];
/*
- * Create a cannon_ace entry representing this NT DACL ACE.
+ * Create a canon_ace entry representing this NT DACL ACE.
*/
if ((current_ace = SMB_MALLOC_P(canon_ace)) == NULL) {
* Note what kind of a POSIX ACL this should map to.
*/
- if( sid_equal(¤t_ace->trustee, &global_sid_World)) {
+ if( dom_sid_equal(¤t_ace->trustee, &global_sid_World)) {
current_ace->owner_type = WORLD_ACE;
current_ace->unix_ug.world = -1;
current_ace->type = SMB_ACL_OTHER;
- } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) {
+ } else if (dom_sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) {
current_ace->owner_type = UID_ACE;
current_ace->unix_ug.uid = pst->st_ex_uid;
current_ace->type = SMB_ACL_USER_OBJ;
psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
- } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) {
+ } else if (dom_sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) {
current_ace->owner_type = GID_ACE;
current_ace->unix_ug.gid = pst->st_ex_gid;
current_ace->type = SMB_ACL_GROUP_OBJ;
continue;
}
+ if (lp_force_unknown_acl_user(SNUM(fsp->conn))) {
+ DEBUG(10, ("create_canon_ace_lists: ignoring "
+ "unknown or foreign SID %s\n",
+ sid_string_dbg(&psa->trustee)));
+ SAFE_FREE(current_ace);
+ continue;
+ }
+
free_canon_ace_list(file_ace);
free_canon_ace_list(dir_ace);
DEBUG(0, ("create_canon_ace_lists: unable to map SID "
continue;
}
- if (!sid_equal(&curr_ace->trustee, &global_sid_World))
+ if (!dom_sid_equal(&curr_ace->trustee, &global_sid_World))
continue;
/* JRATEST - assert. */
}
/****************************************************************************
- Unpack a SEC_DESC into two canonical ace lists. We don't depend on this
+ Unpack a struct security_descriptor into two canonical ace lists. We don't depend on this
succeeding.
****************************************************************************/
static bool unpack_canon_ace(files_struct *fsp,
const SMB_STRUCT_STAT *pst,
- DOM_SID *pfile_owner_sid,
- DOM_SID *pfile_grp_sid,
+ struct dom_sid *pfile_owner_sid,
+ struct dom_sid *pfile_grp_sid,
canon_ace **ppfile_ace,
canon_ace **ppdir_ace,
uint32 security_info_sent,
- const SEC_DESC *psd)
+ const struct security_descriptor *psd)
{
SMB_STRUCT_STAT st;
canon_ace *file_ace = NULL;
* If no DACL then this is a chown only security descriptor.
*/
- if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !psd->dacl)
+ if(!(security_info_sent & SECINFO_DACL) || !psd->dacl)
return True;
/*
static canon_ace *canonicalise_acl(struct connection_struct *conn,
const char *fname, SMB_ACL_T posix_acl,
const SMB_STRUCT_STAT *psbuf,
- const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
+ const struct dom_sid *powner, const struct dom_sid *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
{
mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
canon_ace *l_head = NULL;
while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
SMB_ACL_TAG_T tagtype;
SMB_ACL_PERMSET_T permset;
- DOM_SID sid;
+ struct dom_sid sid;
posix_id unix_ug;
enum ace_owner owner_type;
static bool current_user_in_group(connection_struct *conn, gid_t gid)
{
int i;
- const UNIX_USER_TOKEN *utok = get_current_utok(conn);
+ const struct security_unix_token *utok = get_current_utok(conn);
for (i = 0; i < utok->ngroups; i++) {
if (utok->groups[i] == gid) {
if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
(nt_ace_list[i].size == nt_ace_list[j].size) &&
(nt_ace_list[i].access_mask == nt_ace_list[j].access_mask) &&
- sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
+ dom_sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
(i_inh == j_inh) &&
(i_flags_ni == 0) &&
(j_flags_ni == (SEC_ACE_FLAG_OBJECT_INHERIT|
*/
static void add_or_replace_ace(struct security_ace *nt_ace_list, size_t *num_aces,
- const DOM_SID *sid, enum security_ace_type type,
+ const struct dom_sid *sid, enum security_ace_type type,
uint32_t mask, uint8_t flags)
{
int i;
/* first search for a duplicate */
for (i = 0; i < *num_aces; i++) {
- if (sid_equal(&nt_ace_list[i].trustee, sid) &&
+ if (dom_sid_equal(&nt_ace_list[i].trustee, sid) &&
(nt_ace_list[i].flags == flags)) break;
}
SMB_ACL_T posix_acl,
SMB_ACL_T def_acl,
uint32_t security_info,
- SEC_DESC **ppdesc)
+ struct security_descriptor **ppdesc)
{
- DOM_SID owner_sid;
- DOM_SID group_sid;
+ struct dom_sid owner_sid;
+ struct dom_sid group_sid;
size_t sd_size = 0;
struct security_acl *psa = NULL;
size_t num_acls = 0;
canon_ace *dir_ace = NULL;
struct security_ace *nt_ace_list = NULL;
size_t num_profile_acls = 0;
- DOM_SID orig_owner_sid;
- SEC_DESC *psd = NULL;
+ struct dom_sid orig_owner_sid;
+ struct security_descriptor *psd = NULL;
int i;
/*
num_profile_acls = 3;
}
- if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) {
+ if ((security_info & SECINFO_DACL) && !(security_info & SECINFO_PROTECTED_DACL)) {
/*
* In the optimum case Creator Owner and Creator Group would be used for
if (lp_profile_acls(SNUM(conn))) {
for (i = 0; i < num_aces; i++) {
- if (sid_equal(&nt_ace_list[i].trustee, &owner_sid)) {
+ if (dom_sid_equal(&nt_ace_list[i].trustee, &owner_sid)) {
add_or_replace_ace(nt_ace_list, &num_aces,
&orig_owner_sid,
nt_ace_list[i].type,
goto done;
}
}
- } /* security_info & DACL_SECURITY_INFORMATION */
+ } /* security_info & SECINFO_DACL */
psd = make_standard_sec_desc( talloc_tos(),
- (security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL,
- (security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL,
+ (security_info & SECINFO_OWNER) ? &owner_sid : NULL,
+ (security_info & SECINFO_GROUP) ? &group_sid : NULL,
psa,
&sd_size);
}
NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
- SEC_DESC **ppdesc)
+ struct security_descriptor **ppdesc)
{
SMB_STRUCT_STAT sbuf;
SMB_ACL_T posix_acl = NULL;
}
NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
- uint32_t security_info, SEC_DESC **ppdesc)
+ uint32_t security_info, struct security_descriptor **ppdesc)
{
SMB_ACL_T posix_acl = NULL;
SMB_ACL_T def_acl = NULL;
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 SeTakeOwnershipPrivilege we can change the user to the current user.
- 3) If we have SeRestorePrivilege we can change the user to any other user.
+ 2) If we have SeRestorePrivilege we can change the user + group to any other user.
+ 3) If we have SeTakeOwnershipPrivilege we can change the user to the current user.
4) If we have write permission to the file and dos_filemodes is set
then allow chown to the currently authenticated user.
****************************************************************************/
-int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
- uid_t uid, gid_t gid)
+NTSTATUS try_chown(files_struct *fsp, uid_t uid, gid_t gid)
{
- int ret;
- files_struct *fsp;
+ NTSTATUS status;
- if(!CAN_WRITE(conn)) {
- return -1;
+ if(!CAN_WRITE(fsp->conn)) {
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
/* Case (1). */
- /* try the direct way first */
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid, gid);
- } else {
- ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, gid);
+ status = vfs_chown_fsp(fsp, uid, gid);
+ if (NT_STATUS_IS_OK(status)) {
+ return status;
}
- if (ret == 0)
- return 0;
-
/* Case (2) / (3) */
if (lp_enable_privileges()) {
-
- bool has_take_ownership_priv = user_has_privileges(get_current_nttok(conn),
- &se_take_ownership);
- bool has_restore_priv = user_has_privileges(get_current_nttok(conn),
- &se_restore);
-
- /* Case (2) */
- if ( ( has_take_ownership_priv && ( uid == get_current_uid(conn) ) ) ||
- /* Case (3) */
- ( has_restore_priv ) ) {
-
- become_root();
- /* Keep the current file gid the same - take ownership doesn't imply group change. */
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
+ bool has_take_ownership_priv = security_token_has_privilege(
+ get_current_nttok(fsp->conn),
+ SEC_PRIV_TAKE_OWNERSHIP);
+ bool has_restore_priv = security_token_has_privilege(
+ get_current_nttok(fsp->conn),
+ SEC_PRIV_RESTORE);
+
+ if (has_restore_priv) {
+ ; /* Case (2) */
+ } else if (has_take_ownership_priv) {
+ /* Case (3) */
+ if (uid == get_current_uid(fsp->conn)) {
+ gid = (gid_t)-1;
} else {
- ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
+ has_take_ownership_priv = false;
}
+ }
+
+ if (has_take_ownership_priv || has_restore_priv) {
+ become_root();
+ status = vfs_chown_fsp(fsp, uid, gid);
unbecome_root();
- return ret;
+ return status;
}
}
/* Case (4). */
- if (!lp_dos_filemode(SNUM(conn))) {
- errno = EPERM;
- return -1;
+ if (!lp_dos_filemode(SNUM(fsp->conn))) {
+ return NT_STATUS_ACCESS_DENIED;
}
/* 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
*/
- if (uid != get_current_uid(conn)) {
- errno = EPERM;
- return -1;
- }
-
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
- } else {
- ret = SMB_VFS_STAT(conn, smb_fname);
- }
-
- if (ret == -1) {
- return -1;
- }
-
- if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname, &fsp))) {
- return -1;
+ if (uid != get_current_uid(fsp->conn)) {
+ return NT_STATUS_ACCESS_DENIED;
}
become_root();
/* Keep the current file gid the same. */
- if (fsp->fh->fd == -1) {
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
- } else {
- ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
- }
- } else {
- ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1);
- }
+ status = vfs_chown_fsp(fsp, uid, (gid_t)-1);
unbecome_root();
- close_file_fchmod(NULL, fsp);
-
- return ret;
+ return status;
}
#if 0
****************************************************************************/
NTSTATUS append_parent_acl(files_struct *fsp,
- const SEC_DESC *pcsd,
- SEC_DESC **pp_new_sd)
+ const struct security_descriptor *pcsd,
+ struct security_descriptor **pp_new_sd)
{
struct smb_filename *smb_dname = NULL;
- SEC_DESC *parent_sd = NULL;
+ struct security_descriptor *parent_sd = NULL;
files_struct *parent_fsp = NULL;
TALLOC_CTX *mem_ctx = talloc_tos();
char *parent_name = NULL;
NTSTATUS status;
int info;
unsigned int i, j;
- SEC_DESC *psd = dup_sec_desc(talloc_tos(), pcsd);
+ struct security_descriptor *psd = dup_sec_desc(talloc_tos(), pcsd);
bool is_dacl_protected = (pcsd->type & SEC_DESC_DACL_PROTECTED);
if (psd == NULL) {
}
status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, smb_dname->base_name,
- DACL_SECURITY_INFORMATION, &parent_sd );
+ SECINFO_DACL, &parent_sd );
close_file(NULL, parent_fsp, NORMAL_CLOSE);
TALLOC_FREE(smb_dname);
* same SID. This is order N^2. Ouch :-(. JRA. */
unsigned int k;
for (k = 0; k < psd->dacl->num_aces; k++) {
- if (sid_equal(&psd->dacl->aces[k].trustee,
+ if (dom_sid_equal(&psd->dacl->aces[k].trustee,
&se->trustee)) {
break;
}
psd->dacl->aces = new_ace;
psd->dacl->num_aces = i;
- psd->type &= ~(SE_DESC_DACL_AUTO_INHERITED|
- SE_DESC_DACL_AUTO_INHERIT_REQ);
+ psd->type &= ~(SEC_DESC_DACL_AUTO_INHERITED|
+ SEC_DESC_DACL_AUTO_INHERIT_REQ);
*pp_new_sd = psd;
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.
+ We make a copy of psd_orig as internal functions modify the elements inside
+ it, even though it's a const pointer.
****************************************************************************/
-NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
+NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd_orig)
{
connection_struct *conn = fsp->conn;
uid_t user = (uid_t)-1;
gid_t grp = (gid_t)-1;
- DOM_SID file_owner_sid;
- DOM_SID file_grp_sid;
+ struct dom_sid file_owner_sid;
+ struct dom_sid file_grp_sid;
canon_ace *file_ace_list = NULL;
canon_ace *dir_ace_list = NULL;
bool acl_perms = False;
bool set_acl_as_root = false;
bool acl_set_support = false;
bool ret = false;
+ struct security_descriptor *psd = NULL;
DEBUG(10,("set_nt_acl: called for file %s\n",
fsp_str_dbg(fsp)));
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
+ if (!psd_orig) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ psd = dup_sec_desc(talloc_tos(), psd_orig);
+ if (!psd) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
/*
* Get the current state of the file.
*/
* Unpack the user/group/world id's.
*/
+ /* POSIX can't cope with missing owner/group. */
+ if ((security_info_sent & SECINFO_OWNER) && (psd->owner_sid == NULL)) {
+ security_info_sent &= ~SECINFO_OWNER;
+ }
+ if ((security_info_sent & SECINFO_GROUP) && (psd->group_sid == NULL)) {
+ security_info_sent &= ~SECINFO_GROUP;
+ }
+
status = unpack_nt_owners( conn, &user, &grp, security_info_sent, psd);
if (!NT_STATUS_IS_OK(status)) {
return status;
fsp_str_dbg(fsp), (unsigned int)user,
(unsigned int)grp));
- if(try_chown(fsp->conn, fsp->fsp_name, user, grp) == -1) {
+ status = try_chown(fsp, user, grp);
+ if(!NT_STATUS_IS_OK(status)) {
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error "
- "= %s.\n", fsp_str_dbg(fsp),
- (unsigned int)user, (unsigned int)grp,
- strerror(errno)));
- if (errno == EPERM) {
- return NT_STATUS_INVALID_OWNER;
- }
- return map_nt_error_from_unix(errno);
+ "= %s.\n", fsp_str_dbg(fsp),
+ (unsigned int)user,
+ (unsigned int)grp,
+ nt_errstr(status)));
+ return status;
}
/*
create_file_sids(&fsp->fsp_name->st, &file_owner_sid, &file_grp_sid);
+ if((security_info_sent & SECINFO_DACL) &&
+ (psd->type & SEC_DESC_DACL_PRESENT) &&
+ (psd->dacl == NULL)) {
+ struct security_ace ace[3];
+
+ /* We can't have NULL DACL in POSIX.
+ Use owner/group/Everyone -> full access. */
+
+ init_sec_ace(&ace[0],
+ &file_owner_sid,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ GENERIC_ALL_ACCESS,
+ 0);
+ init_sec_ace(&ace[1],
+ &file_grp_sid,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ GENERIC_ALL_ACCESS,
+ 0);
+ init_sec_ace(&ace[2],
+ &global_sid_World,
+ SEC_ACE_TYPE_ACCESS_ALLOWED,
+ GENERIC_ALL_ACCESS,
+ 0);
+ psd->dacl = make_sec_acl(talloc_tos(),
+ NT4_ACL_REVISION,
+ 3,
+ ace);
+ if (psd->dacl == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ security_acl_map_generic(psd->dacl, &file_generic_mapping);
+ }
+
acl_perms = unpack_canon_ace(fsp, &fsp->fsp_name->st, &file_owner_sid,
&file_grp_sid, &file_ace_list,
&dir_ace_list, security_info_sent, psd);
* Only change security if we got a DACL.
*/
- if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) {
+ if(!(security_info_sent & SECINFO_DACL) || (psd->dacl == NULL)) {
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
return NT_STATUS_OK;
Assume we are dealing with files (for now)
********************************************************************/
-SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
+struct security_descriptor *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
{
- SEC_DESC *psd, *ret_sd;
+ struct security_descriptor *psd, *ret_sd;
connection_struct *conn;
files_struct finfo;
struct fd_handle fh;
return NULL;
}
- if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) {
+ if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, SECINFO_DACL, &psd))) {
DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
TALLOC_FREE(finfo.fsp_name);
conn_free(conn);
return ret_sd;
}
+
+/* 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)
+{
+ 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;
+
+ DEBUG(10,("make_default_filesystem_acl: file %s mode = 0%o\n",
+ name, (int)mode ));
+
+ uid_to_sid(&owner_sid, psbuf->st_ex_uid);
+ gid_to_sid(&group_sid, psbuf->st_ex_gid);
+
+ /*
+ We provide up to 4 ACEs
+ - Owner
+ - Group
+ - Everyone
+ - NT System
+ */
+
+ if (mode & S_IRUSR) {
+ if (mode & S_IWUSR) {
+ access_mask |= SEC_RIGHTS_FILE_ALL;
+ } else {
+ access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+ }
+ }
+ 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;
+ }
+
+ *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;
+ }
+ return NT_STATUS_OK;
+}