server: Refactor server side implementation of GetFileSecurity().
This commit is contained in:
parent
2703721860
commit
d87af3dfb2
102
server/file.c
102
server/file.c
|
@ -75,7 +75,6 @@ static void file_destroy( struct object *obj );
|
||||||
static int file_get_poll_events( struct fd *fd );
|
static int file_get_poll_events( struct fd *fd );
|
||||||
static void file_flush( struct fd *fd, struct event **event );
|
static void file_flush( struct fd *fd, struct event **event );
|
||||||
static enum server_fd_type file_get_fd_type( struct fd *fd );
|
static enum server_fd_type file_get_fd_type( struct fd *fd );
|
||||||
static mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner );
|
|
||||||
|
|
||||||
static const struct object_ops file_ops =
|
static const struct object_ops file_ops =
|
||||||
{
|
{
|
||||||
|
@ -291,14 +290,9 @@ static unsigned int generic_file_map_access( unsigned int access )
|
||||||
return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
|
return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct security_descriptor *file_get_sd( struct object *obj )
|
struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group )
|
||||||
{
|
{
|
||||||
struct file *file = (struct file *)obj;
|
|
||||||
struct stat st;
|
|
||||||
int unix_fd;
|
|
||||||
struct security_descriptor *sd;
|
struct security_descriptor *sd;
|
||||||
const SID *user;
|
|
||||||
const SID *group;
|
|
||||||
size_t dacl_size;
|
size_t dacl_size;
|
||||||
ACE_HEADER *current_ace;
|
ACE_HEADER *current_ace;
|
||||||
ACCESS_ALLOWED_ACE *aaa;
|
ACCESS_ALLOWED_ACE *aaa;
|
||||||
|
@ -308,34 +302,17 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
const SID *world_sid = security_world_sid;
|
const SID *world_sid = security_world_sid;
|
||||||
const SID *local_system_sid = security_local_system_sid;
|
const SID *local_system_sid = security_local_system_sid;
|
||||||
|
|
||||||
assert( obj->ops == &file_ops );
|
|
||||||
|
|
||||||
unix_fd = get_file_unix_fd( file );
|
|
||||||
|
|
||||||
if (unix_fd == -1) return obj->sd;
|
|
||||||
|
|
||||||
if (fstat( unix_fd, &st ) == -1)
|
|
||||||
return obj->sd;
|
|
||||||
|
|
||||||
/* mode and uid the same? if so, no need to re-generate security descriptor */
|
|
||||||
if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (file->mode & (S_IRWXU|S_IRWXO)) &&
|
|
||||||
(st.st_uid == file->uid))
|
|
||||||
return obj->sd;
|
|
||||||
|
|
||||||
user = security_unix_uid_to_sid( st.st_uid );
|
|
||||||
group = token_get_primary_group( current->process->token );
|
|
||||||
|
|
||||||
dacl_size = sizeof(ACL) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
dacl_size = sizeof(ACL) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]);
|
FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]);
|
||||||
if (st.st_mode & S_IRWXU)
|
if (mode & S_IRWXU)
|
||||||
dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
||||||
if ((!(st.st_mode & S_IRUSR) && (st.st_mode & (S_IRGRP|S_IROTH))) ||
|
if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
|
||||||
(!(st.st_mode & S_IWUSR) && (st.st_mode & (S_IWGRP|S_IWOTH))) ||
|
(!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
|
||||||
(!(st.st_mode & S_IXUSR) && (st.st_mode & (S_IXGRP|S_IXOTH))))
|
(!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
|
||||||
dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
|
dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
||||||
if (st.st_mode & S_IRWXO)
|
if (mode & S_IRWXO)
|
||||||
dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[world_sid->SubAuthorityCount]);
|
FIELD_OFFSET(SID, SubAuthority[world_sid->SubAuthorityCount]);
|
||||||
|
|
||||||
|
@ -343,7 +320,7 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) +
|
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) +
|
FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) +
|
||||||
dacl_size );
|
dacl_size );
|
||||||
if (!sd) return obj->sd;
|
if (!sd) return sd;
|
||||||
|
|
||||||
sd->control = SE_DACL_PRESENT;
|
sd->control = SE_DACL_PRESENT;
|
||||||
sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
||||||
|
@ -361,10 +338,10 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
dacl->AclRevision = ACL_REVISION;
|
dacl->AclRevision = ACL_REVISION;
|
||||||
dacl->Sbz1 = 0;
|
dacl->Sbz1 = 0;
|
||||||
dacl->AclSize = dacl_size;
|
dacl->AclSize = dacl_size;
|
||||||
dacl->AceCount = 1 + (st.st_mode & S_IRWXU ? 1 : 0) + (st.st_mode & S_IRWXO ? 1 : 0);
|
dacl->AceCount = 1 + (mode & S_IRWXU ? 1 : 0) + (mode & S_IRWXO ? 1 : 0);
|
||||||
if ((!(st.st_mode & S_IRUSR) && (st.st_mode & (S_IRGRP|S_IROTH))) ||
|
if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
|
||||||
(!(st.st_mode & S_IWUSR) && (st.st_mode & (S_IWGRP|S_IWOTH))) ||
|
(!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
|
||||||
(!(st.st_mode & S_IXUSR) && (st.st_mode & (S_IXGRP|S_IXOTH))))
|
(!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
|
||||||
dacl->AceCount++;
|
dacl->AceCount++;
|
||||||
dacl->Sbz2 = 0;
|
dacl->Sbz2 = 0;
|
||||||
|
|
||||||
|
@ -379,7 +356,7 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
sid = (SID *)&aaa->SidStart;
|
sid = (SID *)&aaa->SidStart;
|
||||||
memcpy( sid, local_system_sid, FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]) );
|
memcpy( sid, local_system_sid, FIELD_OFFSET(SID, SubAuthority[local_system_sid->SubAuthorityCount]) );
|
||||||
|
|
||||||
if (st.st_mode & S_IRWXU)
|
if (mode & S_IRWXU)
|
||||||
{
|
{
|
||||||
/* appropriate access rights for the user */
|
/* appropriate access rights for the user */
|
||||||
aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
|
aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
|
||||||
|
@ -389,18 +366,18 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
||||||
aaa->Mask = WRITE_DAC | WRITE_OWNER;
|
aaa->Mask = WRITE_DAC | WRITE_OWNER;
|
||||||
if (st.st_mode & S_IRUSR)
|
if (mode & S_IRUSR)
|
||||||
aaa->Mask |= FILE_GENERIC_READ;
|
aaa->Mask |= FILE_GENERIC_READ;
|
||||||
if (st.st_mode & S_IWUSR)
|
if (mode & S_IWUSR)
|
||||||
aaa->Mask |= FILE_GENERIC_WRITE | DELETE;
|
aaa->Mask |= FILE_GENERIC_WRITE | DELETE;
|
||||||
if (st.st_mode & S_IXUSR)
|
if (mode & S_IXUSR)
|
||||||
aaa->Mask |= FILE_GENERIC_EXECUTE;
|
aaa->Mask |= FILE_GENERIC_EXECUTE;
|
||||||
sid = (SID *)&aaa->SidStart;
|
sid = (SID *)&aaa->SidStart;
|
||||||
memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
|
memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
|
||||||
}
|
}
|
||||||
if ((!(st.st_mode & S_IRUSR) && (st.st_mode & (S_IRGRP|S_IROTH))) ||
|
if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
|
||||||
(!(st.st_mode & S_IWUSR) && (st.st_mode & (S_IWGRP|S_IWOTH))) ||
|
(!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
|
||||||
(!(st.st_mode & S_IXUSR) && (st.st_mode & (S_IXGRP|S_IXOTH))))
|
(!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
|
||||||
{
|
{
|
||||||
/* deny just in case the user is a member of the group */
|
/* deny just in case the user is a member of the group */
|
||||||
ACCESS_DENIED_ACE *ada = (ACCESS_DENIED_ACE *)ace_next( current_ace );
|
ACCESS_DENIED_ACE *ada = (ACCESS_DENIED_ACE *)ace_next( current_ace );
|
||||||
|
@ -410,17 +387,17 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
|
ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
||||||
ada->Mask = 0;
|
ada->Mask = 0;
|
||||||
if (!(st.st_mode & S_IRUSR) && (st.st_mode & (S_IRGRP|S_IROTH)))
|
if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
|
||||||
ada->Mask |= FILE_GENERIC_READ;
|
ada->Mask |= FILE_GENERIC_READ;
|
||||||
if (!(st.st_mode & S_IWUSR) && (st.st_mode & (S_IWGRP|S_IROTH)))
|
if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IROTH)))
|
||||||
ada->Mask |= FILE_GENERIC_WRITE | DELETE;
|
ada->Mask |= FILE_GENERIC_WRITE | DELETE;
|
||||||
if (!(st.st_mode & S_IXUSR) && (st.st_mode & (S_IXGRP|S_IXOTH)))
|
if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))
|
||||||
ada->Mask |= FILE_GENERIC_EXECUTE;
|
ada->Mask |= FILE_GENERIC_EXECUTE;
|
||||||
ada->Mask &= ~STANDARD_RIGHTS_ALL; /* never deny standard rights */
|
ada->Mask &= ~STANDARD_RIGHTS_ALL; /* never deny standard rights */
|
||||||
sid = (SID *)&ada->SidStart;
|
sid = (SID *)&ada->SidStart;
|
||||||
memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
|
memcpy( sid, user, FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) );
|
||||||
}
|
}
|
||||||
if (st.st_mode & S_IRWXO)
|
if (mode & S_IRWXO)
|
||||||
{
|
{
|
||||||
/* appropriate access rights for Everyone */
|
/* appropriate access rights for Everyone */
|
||||||
aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
|
aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
|
||||||
|
@ -430,16 +407,43 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
||||||
FIELD_OFFSET(SID, SubAuthority[world_sid->SubAuthorityCount]);
|
FIELD_OFFSET(SID, SubAuthority[world_sid->SubAuthorityCount]);
|
||||||
aaa->Mask = 0;
|
aaa->Mask = 0;
|
||||||
if (st.st_mode & S_IROTH)
|
if (mode & S_IROTH)
|
||||||
aaa->Mask |= FILE_GENERIC_READ;
|
aaa->Mask |= FILE_GENERIC_READ;
|
||||||
if (st.st_mode & S_IWOTH)
|
if (mode & S_IWOTH)
|
||||||
aaa->Mask |= FILE_GENERIC_WRITE | DELETE;
|
aaa->Mask |= FILE_GENERIC_WRITE | DELETE;
|
||||||
if (st.st_mode & S_IXOTH)
|
if (mode & S_IXOTH)
|
||||||
aaa->Mask |= FILE_GENERIC_EXECUTE;
|
aaa->Mask |= FILE_GENERIC_EXECUTE;
|
||||||
sid = (SID *)&aaa->SidStart;
|
sid = (SID *)&aaa->SidStart;
|
||||||
memcpy( sid, world_sid, FIELD_OFFSET(SID, SubAuthority[world_sid->SubAuthorityCount]) );
|
memcpy( sid, world_sid, FIELD_OFFSET(SID, SubAuthority[world_sid->SubAuthorityCount]) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
|
{
|
||||||
|
struct file *file = (struct file *)obj;
|
||||||
|
struct stat st;
|
||||||
|
int unix_fd;
|
||||||
|
struct security_descriptor *sd;
|
||||||
|
|
||||||
|
assert( obj->ops == &file_ops );
|
||||||
|
|
||||||
|
unix_fd = get_file_unix_fd( file );
|
||||||
|
|
||||||
|
if (unix_fd == -1 || fstat( unix_fd, &st ) == -1)
|
||||||
|
return obj->sd;
|
||||||
|
|
||||||
|
/* mode and uid the same? if so, no need to re-generate security descriptor */
|
||||||
|
if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (file->mode & (S_IRWXU|S_IRWXO)) &&
|
||||||
|
(st.st_uid == file->uid))
|
||||||
|
return obj->sd;
|
||||||
|
|
||||||
|
sd = mode_to_sd( st.st_mode,
|
||||||
|
security_unix_uid_to_sid( st.st_uid ),
|
||||||
|
token_get_primary_group( current->process->token ));
|
||||||
|
if (!sd) return obj->sd;
|
||||||
|
|
||||||
file->mode = st.st_mode;
|
file->mode = st.st_mode;
|
||||||
file->uid = st.st_uid;
|
file->uid = st.st_uid;
|
||||||
free( obj->sd );
|
free( obj->sd );
|
||||||
|
@ -447,7 +451,7 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||||
return sd;
|
return sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
|
mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
|
||||||
{
|
{
|
||||||
mode_t new_mode = 0;
|
mode_t new_mode = 0;
|
||||||
mode_t denied_mode = 0;
|
mode_t denied_mode = 0;
|
||||||
|
|
|
@ -112,6 +112,8 @@ extern struct file *grab_file_unless_removable( struct file *file );
|
||||||
extern int grow_file( struct file *file, file_pos_t size );
|
extern int grow_file( struct file *file, file_pos_t size );
|
||||||
extern struct file *create_temp_file( int access );
|
extern struct file *create_temp_file( int access );
|
||||||
extern void file_set_error(void);
|
extern void file_set_error(void);
|
||||||
|
extern struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group );
|
||||||
|
extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner );
|
||||||
|
|
||||||
/* change notification functions */
|
/* change notification functions */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue