Exemplo n.º 1
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 );
        }
    }
}
Exemplo n.º 2
0
Arquivo: file.c Projeto: 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;
}
Exemplo n.º 3
0
Arquivo: file.c Projeto: ccpgames/wine
struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group )
{
    struct security_descriptor *sd;
    size_t dacl_size;
    ACE_HEADER *current_ace;
    ACCESS_ALLOWED_ACE *aaa;
    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(ACL) + 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 );
    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 );

    sd = mem_alloc( sizeof(struct security_descriptor) +
                    security_sid_len( user ) + security_sid_len( group ) +
                    dacl_size );
    if (!sd) return sd;

    sd->control = SE_DACL_PRESENT;
    sd->owner_len = security_sid_len( user );
    sd->group_len = security_sid_len( group );
    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 = 1 + (mode & S_IRWXU ? 1 : 0) + (mode & S_IRWXO ? 1 : 0);
    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->AceCount++;
    dacl->Sbz2 = 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 ));

    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 ));
    }
    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;
        if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
            ada->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 ));
    }
    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 ));
    }

    return sd;
}
Exemplo n.º 4
0
struct security_descriptor *get_xattr_acls( int fd, const SID *user, const SID *group )
{
    int dacl_size = sizeof(ACL), n;
    int offset, type, flags, mask, rev, ia, sa;
    char buffer[XATTR_SIZE_MAX + 1], *p, *ptr;
    struct security_descriptor *sd;
    ACL *dacl;

    n = xattr_fget( fd, XATTR_USER_PREFIX "wine.acl", buffer, sizeof(buffer) - 1 );
    if (n == -1) return NULL;
    buffer[n] = 0; /* ensure NULL terminated buffer for string functions */

    p = buffer;
    do
    {
        int sub_authority_count = 0;

        if (sscanf(p, "%x,%x,%x,S-%u-%d%n", &type, &flags, &mask, &rev, &ia, &offset) != 5)
            return NULL;
        p += offset;

        while (sscanf(p, "-%u%n", &sa, &offset) == 1)
        {
            p += offset;
            sub_authority_count++;
        }

        if (*p == ';') p++;
        else if (*p) return NULL;

        /* verify that the SubAuthorityCount does not exceed the maximum permitted value */
        if (sub_authority_count > SID_MAX_SUB_AUTHORITIES)
            continue;

        switch (type)
        {
            case ACCESS_DENIED_ACE_TYPE:
                dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
                             FIELD_OFFSET(SID, SubAuthority[sub_authority_count]);
                break;
            case ACCESS_ALLOWED_ACE_TYPE:
                dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
                             FIELD_OFFSET(SID, SubAuthority[sub_authority_count]);
                break;
            default:
                continue;
        }
    }
    while (*p);

    n = sizeof(struct security_descriptor) +
        FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) +
        FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) +
        dacl_size;

    sd = mem_alloc( n );
    if (!sd) return NULL;

    sd->control = SE_DACL_PRESENT;
    sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
    sd->group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
    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 = 0;
    dacl->Sbz2 = 0;

    ptr = (char *)(dacl + 1);
    p = buffer;
    do
    {
        char sid_buffer[sizeof(SID) + sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES];
        SID *sid = (SID *)sid_buffer;
        int sub_authority_count = 0;

        if (sscanf(p, "%x,%x,%x,S-%u-%d%n", &type, &flags, &mask, &rev, &ia, &offset) != 5)
            goto err;
        p += offset;

        while (sscanf(p, "-%u%n", &sa, &offset) == 1)
        {
            p += offset;
            if (sub_authority_count < SID_MAX_SUB_AUTHORITIES)
                sid->SubAuthority[sub_authority_count] = sa;
            sub_authority_count++;
        }

        if (*p == ';') p++;
        else if (*p) goto err;

        if (sub_authority_count > SID_MAX_SUB_AUTHORITIES)
            continue;

        sid->Revision = rev;
        sid->IdentifierAuthority.Value[0] = 0;
        sid->IdentifierAuthority.Value[1] = 0;
        sid->IdentifierAuthority.Value[2] = HIBYTE(HIWORD(ia));
        sid->IdentifierAuthority.Value[3] = LOBYTE(HIWORD(ia));
        sid->IdentifierAuthority.Value[4] = HIBYTE(LOWORD(ia));
        sid->IdentifierAuthority.Value[5] = LOBYTE(LOWORD(ia));
        sid->SubAuthorityCount = sub_authority_count;

        /* Handle the specific ACE */
        switch (type)
        {
            case ACCESS_DENIED_ACE_TYPE:
                {
                    ACCESS_DENIED_ACE *ada = (ACCESS_DENIED_ACE *)ptr;
                    ada->Header.AceType  = type;
                    ada->Header.AceFlags = flags;
                    ada->Header.AceSize  = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
                                           FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]);
                    ada->Mask            = mask;
                    memcpy( &ada->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) );
                }
                break;
            case ACCESS_ALLOWED_ACE_TYPE:
                {
                    ACCESS_ALLOWED_ACE *aaa = (ACCESS_ALLOWED_ACE *)ptr;
                    aaa->Header.AceType  = type;
                    aaa->Header.AceFlags = flags;
                    aaa->Header.AceSize  = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
                                           FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]);
                    aaa->Mask            = mask;
                    memcpy( &aaa->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) );
                }
                break;
            default:
                continue;
        }

        ptr = (char *)ace_next( (ACE_HEADER *)ptr );
        dacl->AceCount++;
    }
    while (*p);

    if (sd_is_valid( sd, n ))
        return sd;

err:
    free( sd );
    return NULL;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}