summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/passdb/passdb.c14
-rw-r--r--source3/smbd/posix_acls.c133
2 files changed, 120 insertions, 27 deletions
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index 42c0176fc5..0e4948a322 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -575,6 +575,8 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
DOM_SID dom_sid;
uint32 rid;
+ fstring str;
+ struct passwd *pass;
*name_type = SID_NAME_UNKNOWN;
@@ -593,9 +595,12 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
/*
* Ensure this uid really does exist.
*/
- if(!sys_getpwuid(*puid))
+ if(!(pass = sys_getpwuid(*puid)))
return False;
+ DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid),
+ (unsigned int)*puid, pass->pw_name ));
+
return True;
}
@@ -620,6 +625,8 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
extern DOM_SID global_sam_sid;
DOM_SID dom_sid;
uint32 rid;
+ fstring str;
+ struct group *grp;
*name_type = SID_NAME_UNKNOWN;
@@ -640,9 +647,12 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
* Ensure this gid really does exist.
*/
- if(!getgrgid(*pgid))
+ if(!(grp = getgrgid(*pgid)))
return False;
+ DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u) (%s).\n", sid_to_string( str, psid),
+ (unsigned int)*pgid, grp->gr_name ));
+
return True;
}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 4791375851..0071f8786d 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -41,32 +41,55 @@ typedef struct canon_ace {
static void free_canon_ace_list( canon_ace *list_head );
-#if 0
/****************************************************************************
- Function to duplicate a canon_ace struct.
+ Function to create owner and group SIDs from a SMB_STRUCT_STAT.
****************************************************************************/
-static canon_ace *dup_canon_ace( canon_ace *c_ace)
+static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid)
{
- canon_ace *new_ace = (canon_ace *)malloc(sizeof(canon_ace));
-
- if (new_ace == NULL)
- return NULL;
-
- *new_ace = *c_ace;
-
- return new_ace;
+ uid_to_sid( powner_sid, psbuf->st_uid );
+ gid_to_sid( pgroup_sid, psbuf->st_gid );
}
-#endif
/****************************************************************************
- Function to create owner and group SIDs from a SMB_STRUCT_STAT.
+ Print out a canon ace.
****************************************************************************/
-static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid)
+static void print_canon_ace(canon_ace *ace, int num)
{
- uid_to_sid( powner_sid, psbuf->st_uid );
- gid_to_sid( pgroup_sid, psbuf->st_gid );
+ fstring str;
+
+ dbgtext( "canon_ace index %d.", num );
+ dbgtext( "SID = %s ", sid_to_string( str, &ace->sid));
+ if (ace->owner_type == UID_ACE) {
+ struct passwd *pass = sys_getpwuid(ace->unix_ug.uid);
+ dbgtext( "uid %u (%s) ", (unsigned int)ace->unix_ug.uid, pass ? pass->pw_name : "UNKNOWN");
+ } else if (ace->owner_type == GID_ACE) {
+ struct group *grp = getgrgid(ace->unix_ug.gid);
+ dbgtext( "gid %u (%s) ", (unsigned int)ace->unix_ug.gid, grp ? grp->gr_name : "UNKNOWN");
+ } else
+ dbgtext( "other ");
+ switch (ace->type) {
+ case SMB_ACL_USER:
+ dbgtext( "SMB_ACL_USER ");
+ break;
+ case SMB_ACL_USER_OBJ:
+ dbgtext( "SMB_ACL_USER_OBJ ");
+ break;
+ case SMB_ACL_GROUP:
+ dbgtext( "SMB_ACL_GROUP ");
+ break;
+ case SMB_ACL_GROUP_OBJ:
+ dbgtext( "SMB_ACL_GROUP_OBJ ");
+ break;
+ case SMB_ACL_OTHER:
+ dbgtext( "SMB_ACL_OTHER ");
+ break;
+ }
+ dbgtext( "perms ");
+ dbgtext( "%c", ace->perms & S_IRUSR ? 'r' : '-');
+ dbgtext( "%c", ace->perms & S_IWUSR ? 'w' : '-');
+ dbgtext( "%c\n", ace->perms & S_IXUSR ? 'x' : '-');
}
/****************************************************************************
@@ -80,9 +103,9 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon
*pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
- if((ace->perms & (S_IRWXU|S_IWUSR|S_IXUSR)) == (S_IRWXU|S_IWUSR|S_IXUSR)) {
+ if((ace->perms & (S_IRUSR|S_IWUSR|S_IXUSR)) == (S_IRUSR|S_IWUSR|S_IXUSR)) {
nt_mask = UNIX_ACCESS_RWX;
- } else if((ace->perms & (S_IRWXU|S_IWUSR|S_IXUSR)) == 0) {
+ } else if((ace->perms & (S_IRUSR|S_IWUSR|S_IXUSR)) == 0) {
/*
* Here we differentiate between the owner and any other user.
*/
@@ -93,7 +116,7 @@ static SEC_ACCESS map_canon_ace_perms(int *pacl_type, DOM_SID *powner_sid, canon
nt_mask = 0;
}
} else {
- nt_mask |= ((ace->perms & S_IRWXU) ? UNIX_ACCESS_R : 0 );
+ 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 );
}
@@ -203,6 +226,34 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
}
/****************************************************************************
+ Merge aces with a common user.
+****************************************************************************/
+
+static BOOL merge_aces( canon_ace *list_head, canon_ace *p_ace)
+{
+ canon_ace *curr_ace;
+
+ for (curr_ace = list_head; curr_ace; curr_ace = curr_ace->next) {
+ if (curr_ace == p_ace)
+ continue;
+
+ if (curr_ace->type == p_ace->type && sid_equal(&curr_ace->sid, &p_ace->sid)) {
+ if( DEBUGLVL( 10 )) {
+ dbgtext("Merging ACE's\n");
+ print_canon_ace( p_ace, 0);
+ print_canon_ace( curr_ace, 0);
+ }
+ p_ace->perms |= curr_ace->perms;
+ DLIST_REMOVE(list_head, curr_ace);
+ free(curr_ace);
+ return True;
+ }
+ }
+
+ return False;
+}
+
+/****************************************************************************
Unpack a SEC_DESC into two canonical ace lists. We don't depend on this
succeeding.
****************************************************************************/
@@ -218,6 +269,7 @@ static BOOL unpack_canon_ace(files_struct *fsp,
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;
enum SID_NAME_USE sid_type;
int i;
@@ -242,7 +294,6 @@ static BOOL unpack_canon_ace(files_struct *fsp,
for(i = 0; i < dacl->num_aces; i++) {
SEC_ACE *psa = &dacl->ace[i];
- canon_ace *current_ace = NULL;
if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
DEBUG(3,("unpack_canon_ace: unable to set anything but an ALLOW or DENY ACE.\n"));
@@ -308,7 +359,7 @@ static BOOL unpack_canon_ace(files_struct *fsp,
if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED)
current_ace->perms |= map_nt_perms( psa->info, S_IRUSR);
else
- current_ace->perms &= ~(map_nt_perms( psa->info, S_IRUSR));
+ current_ace->perms = 0;
/*
* Now note what kind of a POSIX ACL this should map to.
@@ -357,10 +408,29 @@ static BOOL unpack_canon_ace(files_struct *fsp,
* there was no DACL sent. JRA.
*/
- DEBUG(10,("unpack_posix_permissions: Win2k inherit acl traverse. Ignoring DACL.\n"));
+ DEBUG(10,("unpack_canon_ace: Win2k inherit acl traverse. Ignoring DACL.\n"));
free_sec_acl(&psd->dacl);
}
+ /*
+ * Now go through the canon_ace lists and merge entries
+ * belonging to identical users.
+ */
+
+ again_file:
+
+ for (current_ace = file_ace; current_ace; current_ace = current_ace->next ) {
+ if (merge_aces( file_ace, current_ace))
+ goto again_file;
+ }
+
+ again_dir:
+
+ for (current_ace = dir_ace; current_ace; current_ace = current_ace->next ) {
+ if (merge_aces( dir_ace, current_ace))
+ goto again_dir;
+ }
+
*ppfile_ace = file_ace;
*ppdir_ace = dir_ace;
return True;
@@ -371,7 +441,7 @@ static BOOL unpack_canon_ace(files_struct *fsp,
****************************************************************************/
static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf, mode_t *pmode,
- uint32 security_info_sent, SEC_DESC *psd)
+ uint32 security_info_sent, SEC_DESC *psd, BOOL posix_acls)
{
extern DOM_SID global_sid_World;
connection_struct *conn = fsp->conn;
@@ -478,6 +548,7 @@ static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf,
else
*pmode &= ~(map_nt_perms( psa->info, S_IRUSR));
+
} else if( sid_equal(&ace_sid, &file_grp_sid)) {
/*
* Map the desired permissions into group perms.
@@ -499,7 +570,12 @@ static BOOL unpack_posix_permissions(files_struct *fsp, SMB_STRUCT_STAT *psbuf,
*pmode &= ~(map_nt_perms( psa->info, S_IROTH));
} else {
- DEBUG(0,("unpack_posix_permissions: unknown SID used in ACL.\n"));
+ /*
+ * Only bother printing the level zero error if we didn't get any
+ * POSIX ACLS.
+ */
+ if (!posix_acls)
+ DEBUG(0,("unpack_posix_permissions: unknown SID used in ACL.\n"));
return False;
}
}
@@ -926,6 +1002,9 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau
i, strerror(errno) ));
goto done;
}
+
+ if( DEBUGLVL( 10 ))
+ print_canon_ace( p_ace, i);
}
/*
@@ -1019,6 +1098,8 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
*ppdesc = NULL;
+ DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name ));
+
if(fsp->is_directory || fsp->fd == -1) {
/* Get the stat struct for the owner info. */
@@ -1160,6 +1241,8 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
BOOL posix_perms;
BOOL acl_perms;
+ DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
+
/*
* Get the current state of the file.
*/
@@ -1219,9 +1302,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
- posix_perms = unpack_posix_permissions( fsp, &sbuf, &perms, security_info_sent, psd);
acl_perms = unpack_canon_ace( fsp, &file_owner_sid, &file_grp_sid,
&file_ace_list, &dir_ace_list, security_info_sent, psd);
+ posix_perms = unpack_posix_permissions( fsp, &sbuf, &perms, security_info_sent, psd, acl_perms);
if (!posix_perms && !acl_perms) {
/*