예제 #1
0
void set_xattr_sd( int fd, const struct security_descriptor *sd, const SID *user, const SID *group )
{
    char buffer[XATTR_SIZE_MAX], *dst_ptr = &buffer[2], *src_ptr = (char *)sd;
    int present, len, owner_len, group_len;
    struct security_descriptor *dst_sd;
    const ACL *dacl;

    /* there's no point in storing the security descriptor if there's no DACL */
    if (!sd) return;
    dacl = sd_get_dacl( sd, &present );
    if (!present || !dacl) return;

    /* make sure that we always store the ownership information */
    if (!sd->owner_len)
        owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
    else
        owner_len = sd->owner_len;
    if (!sd->group_len)
        group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
    else
        group_len = sd->group_len;
    len = 2 + sizeof(struct security_descriptor) + owner_len + group_len + sd->sacl_len
          + sd->dacl_len;
    if (len > XATTR_SIZE_MAX) return;

    /* include the descriptor revision and resource manager control bits */
    buffer[0] = SECURITY_DESCRIPTOR_REVISION;
    buffer[1] = 0;
    memcpy( dst_ptr, sd, sizeof(struct security_descriptor) );
    dst_sd = (struct security_descriptor *)dst_ptr;
    dst_sd->owner_len = owner_len;
    dst_sd->group_len = group_len;
    src_ptr += sizeof(struct security_descriptor);
    dst_ptr += sizeof(struct security_descriptor);
    /* copy the appropriate ownership information (explicit or inferred) */
    if (sd->owner_len)
    {
        memcpy( dst_ptr, src_ptr, sd->owner_len );
        src_ptr += sd->owner_len;
    }
    else
        memcpy( dst_ptr, user, owner_len );
    dst_ptr += owner_len;
    if (sd->group_len)
    {
        memcpy( dst_ptr, src_ptr, sd->group_len );
        src_ptr += sd->group_len;
    }
    else
        memcpy( dst_ptr, group, group_len );
    dst_ptr += group_len;
    /* copy the ACL information (explicit only) */
    memcpy( dst_ptr, src_ptr, sd->sacl_len );
    src_ptr += sd->sacl_len;
    dst_ptr += sd->sacl_len;
    memcpy( dst_ptr, src_ptr, sd->dacl_len );
    src_ptr += sd->dacl_len;
    dst_ptr += sd->dacl_len;
    xattr_fset( fd, WINE_XATTR_SD, buffer, len );
}
예제 #2
0
/* Convert generic rights into standard access rights */
void convert_generic_sd( struct security_descriptor *sd )
{
    const ACL *dacl;
    int present;

    dacl = sd_get_dacl( sd, &present );
    if (present && dacl)
    {
        const ACE_HEADER *ace = (const ACE_HEADER *)(dacl + 1);
        ULONG i;

        for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace ))
        {
            DWORD *mask = (DWORD *)(ace + 1);

            *mask = generic_file_map_access( *mask );
        }
    }
}
예제 #3
0
파일: file.c 프로젝트: ccpgames/wine
mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
{
    mode_t new_mode = 0;
    mode_t bits_to_set = ~0;
    mode_t mode;
    int present;
    const ACL *dacl = sd_get_dacl( sd, &present );
    const SID *user = token_get_user( current->process->token );
    if (present && dacl)
    {
        const ACE_HEADER *ace = (const ACE_HEADER *)(dacl + 1);
        ULONG i;
        for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace ))
        {
            const ACCESS_ALLOWED_ACE *aa_ace;
            const ACCESS_DENIED_ACE *ad_ace;
            const SID *sid;

            if (ace->AceFlags & INHERIT_ONLY_ACE) continue;

            switch (ace->AceType)
            {
                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 */
                    }
                    else if ((security_equal_sid( user, owner ) &&
                              token_sid_present( current->process->token, sid, TRUE )))
                    {
                        bits_to_set &= ~((mode << 6) | (mode << 3));  /* user + group */
                    }
                    else if (security_equal_sid( sid, owner ))
                    {
                        bits_to_set &= ~(mode << 6);  /* user only */
                    }
                    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 */
                        new_mode |= mode & bits_to_set;
                        bits_to_set &= ~mode;
                    }
                    else if ((security_equal_sid( user, owner ) &&
                              token_sid_present( current->process->token, sid, FALSE )))
                    {
                        mode = (mode << 6) | (mode << 3);  /* user + group */
                        new_mode |= mode & bits_to_set;
                        bits_to_set &= ~mode;
                    }
                    else if (security_equal_sid( sid, owner ))
                    {
                        mode = (mode << 6);  /* user only */
                        new_mode |= mode & bits_to_set;
                        bits_to_set &= ~mode;
                    }
                    break;
            }
        }
    }
    else
        /* no ACL means full access rights to anyone */
        new_mode = S_IRWXU | S_IRWXG | S_IRWXO;

    return new_mode;
}
예제 #4
0
struct security_descriptor *file_combine_sds( const struct security_descriptor *parent_sd,
                                              const struct security_descriptor *child_sd )
{
    size_t dacl_size = sizeof(ACL), ace_count = 0;
    const struct security_descriptor *old_sd;
    struct security_descriptor *sd = NULL;
    const ACL *child_dacl, *parent_dacl;
    int child_present, parent_present;
    const SID *user, *group;
    const ACE_HEADER *old_ace;
    ACE_HEADER *ace;
    ACL *dacl;
    char *ptr;
    ULONG i;

    child_dacl = sd_get_dacl( child_sd, &child_present );
    if (child_present && child_dacl)
    {
        old_ace = (const ACE_HEADER *)(child_dacl + 1);
        for (i = 0; i < child_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
        {
            ace_count++;
            dacl_size += sizeof(ACE_HEADER) + old_ace->AceSize;
        }
    }

    parent_dacl = sd_get_dacl( parent_sd, &parent_present );
    if (parent_present && parent_dacl)
    {
        old_ace = (const ACE_HEADER *)(parent_dacl + 1);
        for (i = 0; i < parent_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
        {
            ace_count++;
            dacl_size += sizeof(ACE_HEADER) + old_ace->AceSize;
        }
    }

    if(!ace_count) return sd; /* No inheritance */

    /* FIXME: should use set_info flags? */
    if (child_present && child_dacl)
        old_sd = child_sd;
    else
        old_sd = parent_sd;

    /* Fill in the security descriptor so that it is compatible with our DACL */
    user = (const SID *)(old_sd + 1);
    group = (const SID *)((char *)(old_sd + 1) + old_sd->owner_len);
    sd = mem_alloc( sizeof(struct security_descriptor) + old_sd->owner_len
                    + old_sd->group_len + dacl_size );
    if (!sd) return sd;
    sd->control = SE_DACL_PRESENT;
    sd->owner_len = old_sd->owner_len;
    sd->group_len = old_sd->group_len;
    sd->sacl_len = 0;
    sd->dacl_len = dacl_size;
    ptr = (char *)(sd + 1);
    memcpy( ptr, user, sd->owner_len );
    ptr += sd->owner_len;
    memcpy( ptr, group, sd->group_len );
    ptr += sd->group_len;
    dacl = (ACL *)ptr;
    dacl->AclRevision = ACL_REVISION;
    dacl->Sbz1 = 0;
    dacl->AclSize = dacl_size;
    dacl->AceCount = ace_count;
    dacl->Sbz2 = 0;
    ace = (ACE_HEADER *)(dacl + 1);

    if (parent_present && parent_dacl)
    {
        /* Build the new DACL, inheriting from the parent's information */
        old_ace = (const ACE_HEADER *)(parent_dacl + 1);
        for (i = 0; i < parent_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
        {
            ace->AceType = old_ace->AceType;
            ace->AceFlags = old_ace->AceFlags;
            ace->AceSize = old_ace->AceSize;
            memcpy( ace + 1, old_ace + 1, old_ace->AceSize - sizeof(ACE_HEADER));
            ace = (ACE_HEADER *)ace_next( ace );
        }
    }

    if (child_present && child_dacl)
    {
        /* Build the new DACL, inheriting from the child's information */
        old_ace = (const ACE_HEADER *)(child_dacl + 1);
        for (i = 0; i < child_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
        {
            ace->AceType = old_ace->AceType;
            ace->AceFlags = old_ace->AceFlags;
            ace->AceSize = old_ace->AceSize;
            memcpy( ace + 1, old_ace + 1, old_ace->AceSize - sizeof(ACE_HEADER));
            ace = (ACE_HEADER *)ace_next( ace );
        }
    }

    return sd;
}
예제 #5
0
struct security_descriptor *inherit_sd( const struct security_descriptor *parent_sd, int is_dir )
{
    const DWORD inheritance_mask = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
    struct security_descriptor *sd = NULL;
    const ACL *parent_dacl;
    int present;
    ACL *dacl;

    parent_dacl = sd_get_dacl( parent_sd, &present );
    if (present && parent_dacl)
    {
        size_t dacl_size = sizeof(ACL), ace_count = 0;
        const ACE_HEADER *parent_ace;
        const SID *user, *group;
        ACE_HEADER *ace;
        char *ptr;
        ULONG i;

        /* Calculate the size of the DACL */
        parent_ace = (const ACE_HEADER *)(parent_dacl + 1);
        for (i = 0; i < parent_dacl->AceCount; i++, parent_ace = ace_next( parent_ace ))
        {
            if (!(parent_ace->AceFlags & inheritance_mask)) continue;

            ace_count++;
            dacl_size += parent_ace->AceSize;
        }
        if (!ace_count) return sd; /* No inheritance */

        /* Fill in the security descriptor so that it is compatible with our DACL */
        user = (const SID *)(parent_sd + 1);
        group = (const SID *)((char *)(parent_sd + 1) + parent_sd->owner_len);
        sd = mem_alloc( sizeof(struct security_descriptor) + parent_sd->owner_len
                        + parent_sd->group_len + dacl_size );
        if (!sd) return sd;
        sd->control = SE_DACL_PRESENT;
        sd->owner_len = parent_sd->owner_len;
        sd->group_len = parent_sd->group_len;
        sd->sacl_len = 0;
        sd->dacl_len = dacl_size;
        ptr = (char *)(sd + 1);
        memcpy( ptr, user, sd->owner_len );
        ptr += sd->owner_len;
        memcpy( ptr, group, sd->group_len );
        ptr += sd->group_len;
        dacl = (ACL *)ptr;
        dacl->AclRevision = ACL_REVISION;
        dacl->Sbz1 = 0;
        dacl->AclSize = dacl_size;
        dacl->AceCount = ace_count;
        dacl->Sbz2 = 0;
        ace = (ACE_HEADER *)(dacl + 1);

        /* Build the new DACL, inheriting from the parent's information */
        parent_ace = (const ACE_HEADER *)(parent_dacl + 1);
        for (i = 0; i < parent_dacl->AceCount; i++, parent_ace = ace_next( parent_ace ))
        {
            DWORD flags = parent_ace->AceFlags;

            if (!(flags & inheritance_mask)) continue;

            ace->AceType = parent_ace->AceType;
            if (is_dir && (flags & CONTAINER_INHERIT_ACE))
                flags &= ~INHERIT_ONLY_ACE;
            else if (!is_dir && (flags & OBJECT_INHERIT_ACE))
                flags &= ~INHERIT_ONLY_ACE;
            else if (is_dir && (flags & OBJECT_INHERIT_ACE))
                flags |= INHERIT_ONLY_ACE;
            if (is_dir)
                ace->AceFlags = flags | INHERITED_ACE;
            else
                ace->AceFlags = (parent_ace->AceFlags & ~inheritance_mask) | INHERITED_ACE;
            ace->AceSize = parent_ace->AceSize;
            memcpy( ace + 1, parent_ace + 1, parent_ace->AceSize - sizeof(ACE_HEADER));
            ace = (ACE_HEADER *)ace_next( ace );
        }
    }
    return sd;
}