1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00

r5355: Fill in the access check code for POSIX ACLs to *really* fix bug #2227.

Jeremy.
This commit is contained in:
Jeremy Allison 2005-02-12 01:05:49 +00:00 committed by Gerald (Jerry) Carter
parent fdf9bdbbac
commit ecc134a2e3

View File

@ -3754,6 +3754,128 @@ 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.
****************************************************************************/
static int check_posix_acl_group_write(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *psbuf)
{
extern struct current_user current_user;
SMB_ACL_T posix_acl = NULL;
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
int i;
int ret = -1;
if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, dname, SMB_ACL_TYPE_ACCESS)) == NULL) {
goto check_stat;
}
/* First ensure the group mask allows group read. */
while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
SMB_ACL_TAG_T tagtype;
SMB_ACL_PERMSET_T permset;
/* 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;
}
switch(tagtype) {
case SMB_ACL_MASK:
if (!SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE)) {
/* We don't have group write permission. */
ret = -1; /* Allow caller to check "other" permissions. */
goto done;
}
break;
default:
continue;
}
}
/* Now 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;
/* 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_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE);
if (have_write == -1) {
goto check_stat;
}
switch(tagtype) {
case SMB_ACL_USER:
{
/* Check against current_user.uid. */
uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
if (puid == NULL) {
goto check_stat;
}
if (current_user.uid == *puid) {
/* We're done now we have a uid match. */
ret = have_write;
goto done;
}
}
break;
case SMB_ACL_MASK:
{
gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
if (pgid == NULL) {
goto check_stat;
}
for (i = 0; i < current_user.ngroups; i++) {
if (current_user.groups[i] == *pgid) {
/* We're done now we have a gid match. */
ret = have_write;
goto done;
}
}
}
break;
default:
continue;
}
}
check_stat:
for (i = 0; i < current_user.ngroups; i++) {
if (current_user.groups[i] == psbuf->st_gid) {
ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0;
break;
}
}
done:
SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
return ret;
}
/****************************************************************************
Actually emulate the in-kernel access checking for write access. We need
this to successfully return ACCESS_DENIED on a file open for delete access.
@ -3761,6 +3883,30 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
{
/* Add acl check here... JRA */
return True;
extern struct current_user current_user;
SMB_STRUCT_STAT sbuf;
pstring dname;
int ret;
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.uid == 0) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
if (current_user.uid == sbuf.st_uid) {
return (sbuf.st_mode & S_IWUSR) ? True : False;
}
/* Check group ownership. */
ret = check_posix_acl_group_write(conn, dname, &sbuf);
if (ret == 0 || ret == 1) {
return ret ? True : False;
}
return (sbuf.st_mode & S_IWOTH) ? True : False;
}