Commit 841b8862 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Define a server-side structure for ACE.

parent c36f81fa
......@@ -309,25 +309,21 @@ static struct fd *file_get_fd( struct object *obj )
struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group )
{
struct security_descriptor *sd;
unsigned char flags;
size_t dacl_size;
ACE_HEADER *current_ace;
ACCESS_ALLOWED_ACE *aaa;
struct ace *ace;
struct acl *dacl;
SID *sid;
char *ptr;
const SID *world_sid = security_world_sid;
const SID *local_system_sid = security_local_system_sid;
dacl_size = sizeof(*dacl) + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
security_sid_len( local_system_sid );
if (mode & S_IRWXU)
dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( user );
dacl_size = sizeof(*dacl) + sizeof(*ace) + security_sid_len( local_system_sid );
if (mode & S_IRWXU) dacl_size += sizeof(*ace) + security_sid_len( user );
if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
(!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
(!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + security_sid_len( user );
if (mode & S_IRWXO)
dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( world_sid );
dacl_size += sizeof(*ace) + security_sid_len( user );
if (mode & S_IRWXO) dacl_size += sizeof(*ace) + security_sid_len( world_sid );
sd = mem_alloc( sizeof(struct security_descriptor) +
security_sid_len( user ) + security_sid_len( group ) +
......@@ -359,66 +355,37 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
dacl->count++;
if (mode & S_IRWXO) dacl->count++;
flags = (mode & S_IFDIR) ? OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE : 0;
/* always give FILE_ALL_ACCESS for Local System */
aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1);
current_ace = &aaa->Header;
aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
aaa->Header.AceFlags = (mode & S_IFDIR) ? OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE : 0;
aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( local_system_sid );
aaa->Mask = FILE_ALL_ACCESS;
sid = (SID *)&aaa->SidStart;
memcpy( sid, local_system_sid, security_sid_len( local_system_sid ));
ace = set_ace( (struct ace *)(dacl + 1), local_system_sid,
ACCESS_ALLOWED_ACE_TYPE, flags, FILE_ALL_ACCESS );
if (mode & S_IRWXU)
{
/* appropriate access rights for the user */
aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
current_ace = &aaa->Header;
aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
aaa->Header.AceFlags = (mode & S_IFDIR) ? OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE : 0;
aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( user );
aaa->Mask = WRITE_DAC | WRITE_OWNER;
if (mode & S_IRUSR)
aaa->Mask |= FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
if (mode & S_IWUSR)
aaa->Mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
sid = (SID *)&aaa->SidStart;
memcpy( sid, user, security_sid_len( user ));
ace = set_ace( ace_next( ace ), user, ACCESS_ALLOWED_ACE_TYPE, flags, WRITE_DAC | WRITE_OWNER );
if (mode & S_IRUSR) ace->mask |= FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
if (mode & S_IWUSR) ace->mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
}
if ((!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) ||
(!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) ||
(!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))))
{
/* deny just in case the user is a member of the group */
ACCESS_DENIED_ACE *ada = (ACCESS_DENIED_ACE *)ace_next( current_ace );
current_ace = &ada->Header;
ada->Header.AceType = ACCESS_DENIED_ACE_TYPE;
ada->Header.AceFlags = (mode & S_IFDIR) ? OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE : 0;
ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + security_sid_len( user );
ada->Mask = 0;
ace = set_ace( ace_next( ace ), user, ACCESS_DENIED_ACE_TYPE, flags, 0 );
if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
ada->Mask |= FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
ace->mask |= FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IROTH)))
ada->Mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
ada->Mask &= ~STANDARD_RIGHTS_ALL; /* never deny standard rights */
sid = (SID *)&ada->SidStart;
memcpy( sid, user, security_sid_len( user ));
ace->mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
ace->mask &= ~STANDARD_RIGHTS_ALL; /* never deny standard rights */
}
if (mode & S_IRWXO)
{
/* appropriate access rights for Everyone */
aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
current_ace = &aaa->Header;
aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
aaa->Header.AceFlags = (mode & S_IFDIR) ? OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE : 0;
aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + security_sid_len( world_sid );
aaa->Mask = 0;
if (mode & S_IROTH)
aaa->Mask |= FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
if (mode & S_IWOTH)
aaa->Mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
sid = (SID *)&aaa->SidStart;
memcpy( sid, world_sid, security_sid_len( world_sid ));
ace = set_ace( ace_next( ace ), world_sid, ACCESS_ALLOWED_ACE_TYPE, flags, 0 );
if (mode & S_IROTH) ace->mask |= FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
if (mode & S_IWOTH) ace->mask |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD;
}
return sd;
......@@ -473,24 +440,22 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
mode_t mode;
int present;
const struct acl *dacl = sd_get_dacl( sd, &present );
if (present && dacl)
{
const ACE_HEADER *ace = (const ACE_HEADER *)(dacl + 1);
ULONG i;
const struct ace *ace = (const struct ace *)(dacl + 1);
unsigned int i;
for (i = 0; i < dacl->count; i++, ace = ace_next( ace ))
{
const ACCESS_ALLOWED_ACE *aa_ace;
const ACCESS_DENIED_ACE *ad_ace;
const SID *sid;
const SID *sid = (const SID *)(ace + 1);
if (ace->AceFlags & INHERIT_ONLY_ACE) continue;
if (ace->flags & INHERIT_ONLY_ACE) continue;
switch (ace->AceType)
mode = file_access_to_mode( ace->mask );
switch (ace->type)
{
case ACCESS_DENIED_ACE_TYPE:
ad_ace = (const ACCESS_DENIED_ACE *)ace;
sid = (const SID *)&ad_ace->SidStart;
mode = file_access_to_mode( ad_ace->Mask );
if (security_equal_sid( sid, security_world_sid ))
{
bits_to_set &= ~((mode << 6) | (mode << 3) | mode); /* all */
......@@ -506,9 +471,6 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
}
break;
case ACCESS_ALLOWED_ACE_TYPE:
aa_ace = (const ACCESS_ALLOWED_ACE *)ace;
sid = (const SID *)&aa_ace->SidStart;
mode = file_access_to_mode( aa_ace->Mask );
if (security_equal_sid( sid, security_world_sid ))
{
mode = (mode << 6) | (mode << 3) | mode; /* all */
......
......@@ -823,12 +823,11 @@ static struct security_descriptor *process_get_sd( struct object *obj )
if (!process_default_sd)
{
struct ace *ace;
struct acl *dacl;
size_t users_sid_len = security_sid_len( security_domain_users_sid );
size_t admins_sid_len = security_sid_len( security_builtin_admins_sid );
size_t dacl_len = sizeof(struct acl) + 2 * offsetof( ACCESS_ALLOWED_ACE, SidStart )
+ users_sid_len + admins_sid_len;
ACCESS_ALLOWED_ACE *aaa;
struct acl *dacl;
size_t dacl_len = sizeof(*dacl) + 2 * sizeof(*ace) + users_sid_len + admins_sid_len;
process_default_sd = mem_alloc( sizeof(*process_default_sd) + admins_sid_len + users_sid_len
+ dacl_len );
......@@ -846,18 +845,9 @@ static struct security_descriptor *process_get_sd( struct object *obj )
dacl->size = dacl_len;
dacl->count = 2;
dacl->pad2 = 0;
aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1);
aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
aaa->Header.AceFlags = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE;
aaa->Header.AceSize = offsetof( ACCESS_ALLOWED_ACE, SidStart ) + users_sid_len;
aaa->Mask = GENERIC_READ;
memcpy( &aaa->SidStart, security_domain_users_sid, users_sid_len );
aaa = (ACCESS_ALLOWED_ACE *)((char *)aaa + aaa->Header.AceSize);
aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
aaa->Header.AceFlags = 0;
aaa->Header.AceSize = offsetof( ACCESS_ALLOWED_ACE, SidStart ) + admins_sid_len;
aaa->Mask = PROCESS_ALL_ACCESS;
memcpy( &aaa->SidStart, security_builtin_admins_sid, admins_sid_len );
ace = set_ace( ace_first( dacl ), security_domain_users_sid, ACCESS_ALLOWED_ACE_TYPE,
INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, GENERIC_READ );
set_ace( ace_next( ace ), security_builtin_admins_sid, ACCESS_ALLOWED_ACE_TYPE, 0, PROCESS_ALL_ACCESS );
}
return process_default_sd;
}
......
......@@ -370,11 +370,10 @@ static struct security_descriptor *key_get_sd( struct object *obj )
if (!key_default_sd)
{
struct acl *dacl;
struct ace *ace;
size_t users_sid_len = security_sid_len( security_builtin_users_sid );
size_t admins_sid_len = security_sid_len( security_builtin_admins_sid );
size_t dacl_len = sizeof(*dacl) + 2 * offsetof( ACCESS_ALLOWED_ACE, SidStart )
+ users_sid_len + admins_sid_len;
ACCESS_ALLOWED_ACE *aaa;
size_t dacl_len = sizeof(*dacl) + 2 * sizeof(*ace) + users_sid_len + admins_sid_len;
key_default_sd = mem_alloc( sizeof(*key_default_sd) + 2 * admins_sid_len + dacl_len );
key_default_sd->control = SE_DACL_PRESENT;
......@@ -391,18 +390,9 @@ static struct security_descriptor *key_get_sd( struct object *obj )
dacl->size = dacl_len;
dacl->count = 2;
dacl->pad2 = 0;
aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1);
aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
aaa->Header.AceFlags = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE;
aaa->Header.AceSize = offsetof( ACCESS_ALLOWED_ACE, SidStart ) + users_sid_len;
aaa->Mask = GENERIC_READ;
memcpy( &aaa->SidStart, security_builtin_users_sid, users_sid_len );
aaa = (ACCESS_ALLOWED_ACE *)((char *)aaa + aaa->Header.AceSize);
aaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
aaa->Header.AceFlags = 0;
aaa->Header.AceSize = offsetof( ACCESS_ALLOWED_ACE, SidStart ) + admins_sid_len;
aaa->Mask = KEY_ALL_ACCESS;
memcpy( &aaa->SidStart, security_builtin_admins_sid, admins_sid_len );
ace = set_ace( ace_first( dacl ), security_builtin_users_sid, ACCESS_ALLOWED_ACE_TYPE,
INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, GENERIC_READ );
set_ace( ace_next( ace ), security_builtin_admins_sid, ACCESS_ALLOWED_ACE_TYPE, 0, KEY_ALL_ACCESS );
}
return key_default_sd;
}
......
......@@ -52,6 +52,13 @@ extern const PSID security_builtin_admins_sid;
extern const PSID security_domain_users_sid;
extern const PSID security_high_label_sid;
struct ace
{
unsigned char type;
unsigned char flags;
unsigned short size;
unsigned int mask;
};
/* token functions */
......@@ -71,9 +78,14 @@ extern const SID *token_get_primary_group( struct token *token );
extern unsigned int token_get_session_id( struct token *token );
extern int token_sid_present( struct token *token, const SID *sid, int deny);
static inline const ACE_HEADER *ace_next( const ACE_HEADER *ace )
static inline struct ace *ace_first( const struct acl *acl )
{
return (const ACE_HEADER *)((const char *)ace + ace->AceSize);
return (struct ace *)(acl + 1);
}
static inline struct ace *ace_next( const struct ace *ace )
{
return (struct ace *)((char *)ace + ace->size);
}
static inline size_t security_sid_len( const SID *sid )
......@@ -87,6 +99,22 @@ static inline int security_equal_sid( const SID *sid1, const SID *sid2 )
!memcmp( sid1, sid2, security_sid_len( sid1 )));
}
static inline int sid_valid_size( const SID *sid, data_size_t size )
{
return (size >= offsetof( SID, SubAuthority[0] ) && size >= security_sid_len( sid ));
}
static inline struct ace *set_ace( struct ace *ace, const SID *sid, unsigned char type,
unsigned char flags, unsigned int mask )
{
ace->type = type;
ace->flags = flags;
ace->size = sizeof(*ace) + security_sid_len( sid );
ace->mask = mask;
memcpy( ace + 1, sid, security_sid_len( sid ));
return ace;
}
extern void security_set_thread_token( struct thread *thread, obj_handle_t handle );
extern const SID *security_unix_uid_to_sid( uid_t uid );
extern int check_object_access( struct token *token, struct object *obj, unsigned int *access );
......
......@@ -44,6 +44,7 @@
#include "winsock2.h"
#include "file.h"
#include "request.h"
#include "security.h"
#include "unicode.h"
static const void *cur_data;
......@@ -1047,7 +1048,7 @@ static void dump_varargs_SID( const char *prefix, data_size_t size )
static void dump_inline_acl( const char *prefix, const struct acl *acl, data_size_t size )
{
const ACE_HEADER *ace;
const struct ace *ace;
ULONG i;
fprintf( stderr,"%s{", prefix );
......@@ -1059,56 +1060,30 @@ static void dump_inline_acl( const char *prefix, const struct acl *acl, data_siz
return;
}
size -= sizeof(*acl);
ace = (const ACE_HEADER *)(acl + 1);
for (i = 0; i < acl->count; i++)
for (i = 0, ace = ace_first( acl ); i < acl->count; i++, ace = ace_next( ace ))
{
const SID *sid = NULL;
data_size_t sid_size = 0;
const SID *sid = (const SID *)(ace + 1);
data_size_t sid_size;
if (size < sizeof(ACE_HEADER) || size < ace->AceSize) break;
size -= ace->AceSize;
if (size < sizeof(*ace) || size < ace->size) break;
size -= ace->size;
sid_size = ace->size - sizeof(*ace);
if (i != 0) fputc( ',', stderr );
fprintf( stderr, "{AceType=" );
switch (ace->AceType)
fprintf( stderr, "{type=" );
switch (ace->type)
{
case ACCESS_DENIED_ACE_TYPE:
sid = (const SID *)&((const ACCESS_DENIED_ACE *)ace)->SidStart;
sid_size = ace->AceSize - FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart);
fprintf( stderr, "ACCESS_DENIED_ACE_TYPE,Mask=%x",
((const ACCESS_DENIED_ACE *)ace)->Mask );
break;
case ACCESS_ALLOWED_ACE_TYPE:
sid = (const SID *)&((const ACCESS_ALLOWED_ACE *)ace)->SidStart;
sid_size = ace->AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
fprintf( stderr, "ACCESS_ALLOWED_ACE_TYPE,Mask=%x",
((const ACCESS_ALLOWED_ACE *)ace)->Mask );
break;
case SYSTEM_AUDIT_ACE_TYPE:
sid = (const SID *)&((const SYSTEM_AUDIT_ACE *)ace)->SidStart;
sid_size = ace->AceSize - FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart);
fprintf( stderr, "SYSTEM_AUDIT_ACE_TYPE,Mask=%x",
((const SYSTEM_AUDIT_ACE *)ace)->Mask );
break;
case SYSTEM_ALARM_ACE_TYPE:
sid = (const SID *)&((const SYSTEM_ALARM_ACE *)ace)->SidStart;
sid_size = ace->AceSize - FIELD_OFFSET(SYSTEM_ALARM_ACE, SidStart);
fprintf( stderr, "SYSTEM_ALARM_ACE_TYPE,Mask=%x",
((const SYSTEM_ALARM_ACE *)ace)->Mask );
break;
case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
sid = (const SID *)&((const SYSTEM_MANDATORY_LABEL_ACE *)ace)->SidStart;
sid_size = ace->AceSize - FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart);
fprintf( stderr, "SYSTEM_MANDATORY_LABEL_ACE_TYPE,Mask=%x",
((const SYSTEM_MANDATORY_LABEL_ACE *)ace)->Mask );
break;
case ACCESS_DENIED_ACE_TYPE: fprintf( stderr, "ACCESS_DENIED" ); break;
case ACCESS_ALLOWED_ACE_TYPE: fprintf( stderr, "ACCESS_ALLOWED" ); break;
case SYSTEM_AUDIT_ACE_TYPE: fprintf( stderr, "SYSTEM_AUDIT" ); break;
case SYSTEM_ALARM_ACE_TYPE: fprintf( stderr, "SYSTEM_ALARM" ); break;
case SYSTEM_MANDATORY_LABEL_ACE_TYPE: fprintf( stderr, "SYSTEM_MANDATORY_LABEL" ); break;
default:
fprintf( stderr, "unknown<%d>", ace->AceType );
fprintf( stderr, "%02x", ace->type );
sid = NULL;
break;
}
fprintf( stderr, ",AceFlags=%x", ace->AceFlags );
if (sid)
dump_inline_sid( ",Sid=", sid, sid_size );
ace = (const ACE_HEADER *)((const char *)ace + ace->AceSize);
fprintf( stderr, ",flags=%x,mask=%x", ace->flags, ace->mask );
if (sid) dump_inline_sid( ",sid=", sid, sid_size );
fputc( '}', stderr );
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment