Ejemplo n.º 1
0
NTSTATUS
LwRtlAnsiStringAllocateFromCString(
    OUT PANSI_STRING pNewString,
    IN PCSTR pszString
    )
{
    NTSTATUS status = 0;
    PSTR pszNewString = NULL;
    ANSI_STRING newString = { 0 };

    status = RtlCStringDuplicate(&pszNewString, pszString);
    GOTO_CLEANUP_ON_STATUS(status);

    status = LwRtlAnsiStringInitEx(&newString, pszNewString);
    GOTO_CLEANUP_ON_STATUS(status);

    pszNewString = 0;

cleanup:
    if (status)
    {
        RtlCStringFree(&pszNewString);
        RtlAnsiStringFree(&newString);
    }

    *pNewString = newString;

    return status;
}
Ejemplo n.º 2
0
LW_NTSTATUS
LwRtlAnsiStringAllocatePrintfV(
    LW_OUT LW_PANSI_STRING pNewString,
    LW_IN LW_PCSTR Format,
    LW_IN va_list Args
    )
{
    NTSTATUS status = 0;
    PSTR pOutputString = NULL;
    ANSI_STRING newString = { 0 };

    status = LwRtlCStringAllocatePrintfV(
                    &pOutputString,
                    Format,
                    Args);
    GOTO_CLEANUP_ON_STATUS(status);

    status = LwRtlAnsiStringInitEx(&newString, pOutputString);
    GOTO_CLEANUP_ON_STATUS(status);

    pOutputString = NULL;

cleanup:
    if (status)
    {
        RTL_ANSI_STRING_FREE(&newString);
    }

    RTL_FREE(&pOutputString);

    *pNewString = newString;

    return status;
}
Ejemplo n.º 3
0
NTSTATUS
RtlGetRidSid(
    OUT PULONG Rid,
    IN PSID Sid
    )
{
    NTSTATUS status = STATUS_SUCCESS;

    if (!Rid || !Sid)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP_ON_STATUS(status);
    }
    
    if (Sid->SubAuthorityCount == 0)
    {
        status = STATUS_INVALID_SUB_AUTHORITY;
        GOTO_CLEANUP_ON_STATUS(status);
    }
    
    *Rid = Sid->SubAuthority[Sid->SubAuthorityCount-1];

cleanup:

    return status;
}
Ejemplo n.º 4
0
LW_NTSTATUS
LwRtlWC16StringAllocateFromUnicodeString(
    LW_OUT LW_PWSTR* ppszNewString,
    LW_IN LW_PUNICODE_STRING pOriginalString
    )
{
    NTSTATUS status = 0;
    UNICODE_STRING terminatedOriginalString = { 0 };
    PWSTR pszNewString = NULL;

    // Since duplicate always does NULL-termination, we can
    // safely use the Buffer field as a WC16String.

    status = LwRtlUnicodeStringDuplicate(&terminatedOriginalString, pOriginalString);
    GOTO_CLEANUP_ON_STATUS(status);

    pszNewString = terminatedOriginalString.Buffer;
    terminatedOriginalString.Buffer = NULL;
    terminatedOriginalString.Length = 0;
    terminatedOriginalString.MaximumLength = 0;

cleanup:
    if (!NT_SUCCESS(status))
    {
        RTL_FREE(&pszNewString);
    }
    LwRtlUnicodeStringFree(&terminatedOriginalString);

    *ppszNewString = pszNewString;

    return status;
}
Ejemplo n.º 5
0
NTSTATUS
LwRtlAnsiStringAllocateFromUnicodeString(
    OUT PANSI_STRING pNewString,
    IN PUNICODE_STRING pString
    )
{
    NTSTATUS status = 0;
    PSTR pszNewString = NULL;
    ANSI_STRING newString = { 0 };

    status = RtlCStringDuplicate(&pszNewString, pszString);
    GOTO_CLEANUP_ON_STATUS(status);

    newString.Buffer = pszNewString;
    pszNewString = 0;
    newString.Length = wc16slen(newString.Buffer) * sizeof(newString.Buffer[0]);
    newString.MaximumLength = newString.Length + sizeof(newString.Buffer[0]);

cleanup:
    if (status)
    {
        RtlCStringFree(&pszNewString);
        RtlAnsiStringFree(&newString);
    }

    *pString = newString;

    return status;
}
Ejemplo n.º 6
0
NTSTATUS
RtlDuplicateSid(
    OUT PSID* NewSid,
    IN PSID OriginalSid
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG length = RtlLengthSid(OriginalSid);
    PSID resultSid = NULL;

    status = RTL_ALLOCATE(&resultSid, SID, length);
    GOTO_CLEANUP_ON_STATUS(status);

    RtlCopyMemory(resultSid, OriginalSid, length);

cleanup:
    if (!NT_SUCCESS(status))
    {
        RTL_FREE(&resultSid);
    }

    *NewSid = resultSid;

    return status;
}
Ejemplo n.º 7
0
static
NTSTATUS
LwRtlAnsiStringAllocateAppendPrintfV(
    IN OUT PANSI_STRING pString,
    IN PCSTR Format,
    IN va_list Args
    )
{
    NTSTATUS status = 0;
    ANSI_STRING addString = { 0 };
    ANSI_STRING newString = { 0 };

    status = LwRtlAnsiStringAllocatePrintfV(&addString, Format, Args);
    GOTO_CLEANUP_ON_STATUS(status);

    if (pString->Buffer)
    {
        status = LwRtlAnsiStringAllocatePrintf(&newString,
                                                "%Z%Z",
                                                pString,
                                                &addString);
        GOTO_CLEANUP_ON_STATUS(status);
    }
    else
    {
        newString = addString;
        LwRtlZeroMemory(&addString, sizeof(addString));
    }

cleanup:
    if (status)
    {
        LW_RTL_ANSI_STRING_FREE(&newString);
    }
    else
    {
        LW_RTL_ANSI_STRING_FREE(pString);
        *pString = newString;
    }

    LW_RTL_ANSI_STRING_FREE(&addString);

    return status;
}
Ejemplo n.º 8
0
static
NTSTATUS
LwRtlWC16StringAllocateAppendPrintfV(
    IN OUT PWSTR* ppszString,
    IN PCSTR pszFormat,
    IN va_list Args
    )
{
    NTSTATUS status = 0;
    PWSTR pszAddString = NULL;
    PWSTR pszNewString = NULL;

    status = LwRtlWC16StringAllocatePrintfV(&pszAddString, pszFormat, Args);
    GOTO_CLEANUP_ON_STATUS(status);

    if (*ppszString)
    {
        status = LwRtlWC16StringAllocatePrintf(&pszNewString,
                                            "%ws%ws",
                                            *ppszString,
                                            pszAddString);
        GOTO_CLEANUP_ON_STATUS(status);
    }
    else
    {
        pszNewString = pszAddString;
        pszAddString = NULL;
    }

cleanup:
    if (status)
    {
        LwRtlWC16StringFree(&pszNewString);
    }
    else
    {
        LwRtlWC16StringFree(ppszString);
        *ppszString = pszNewString;
    }

    LwRtlWC16StringFree(&pszAddString);

    return status;
}
Ejemplo n.º 9
0
static
NTSTATUS
RtlValidateSelfRelativeSid(
    PSID pSid,
    ULONG ulOffset,
    ULONG ulRelativeSize
    )
{
    NTSTATUS status = STATUS_SUCCESS;

    status = CheckOffset(ulOffset, SID_MIN_SIZE, ulRelativeSize);
    GOTO_CLEANUP_ON_STATUS(status);

    status = CheckOffset(ulOffset, RtlLengthSid(pSid), ulRelativeSize);
    GOTO_CLEANUP_ON_STATUS(status);

cleanup:

    return status;
}
Ejemplo n.º 10
0
NTSTATUS
RtlAllocateAnsiStringFromSid(
    OUT PANSI_STRING StringSid,
    IN PSID Sid
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSTR resultBuffer = NULL;
    ANSI_STRING result = { 0 };

    if (!StringSid)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    status = RtlAllocateCStringFromSid(&resultBuffer, Sid);
    GOTO_CLEANUP_ON_STATUS(status);

    status = RtlAnsiStringInitEx(&result, resultBuffer);
    GOTO_CLEANUP_ON_STATUS(status);
    resultBuffer = NULL;

    status = STATUS_SUCCESS;

cleanup:
    if (!NT_SUCCESS(status))
    {
        RtlAnsiStringFree(&result);
    }
    RTL_FREE(&resultBuffer);

    if (StringSid)
    {
        *StringSid = result;
    }

    return status;
}
Ejemplo n.º 11
0
NTSTATUS
RtlAllocateWC16StringFromSid(
    OUT PWSTR* StringSid,
    IN PSID Sid
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PWSTR result = NULL;
    PSTR convertString = NULL;

    if (!StringSid)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    status = RtlAllocateCStringFromSid(&convertString, Sid);
    GOTO_CLEANUP_ON_STATUS(status);

    status = RtlWC16StringAllocateFromCString(&result, convertString);
    GOTO_CLEANUP_ON_STATUS(status);

cleanup:
    if (!NT_SUCCESS(status))
    {
        RTL_FREE(&result);
    }
    RTL_FREE(&convertString);

    if (StringSid)
    {
        *StringSid = result;
    }

    return status;
    
}
Ejemplo n.º 12
0
static
NTSTATUS
LwIoNormalizePath(
    IN PUNICODE_STRING Path,
    OUT PUNICODE_STRING NormalPath
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING normalPath = { 0 };
    ULONG inputIndex = 0;
    ULONG outputIndex = 0;
    ULONG count = 0;

    status = LwRtlUnicodeStringDuplicate(&normalPath, Path);
    GOTO_CLEANUP_ON_STATUS(status);

    count = LW_RTL_STRING_NUM_CHARS(&normalPath);
    for (inputIndex = outputIndex = 0; inputIndex < count; inputIndex++)
    {
        switch (normalPath.Buffer[inputIndex])
        {
        case '\\':
        case '/':
            normalPath.Buffer[outputIndex++] = '/';
            while (((inputIndex + 1) < count) &&
                   IoRtlPathIsSeparator(normalPath.Buffer[inputIndex+1]))
            {
                inputIndex++;
            }
            break;
        default:
            normalPath.Buffer[outputIndex++] = normalPath.Buffer[inputIndex];
            break;
        }
    }

    normalPath.Length = LwRtlPointerToOffset(normalPath.Buffer, &normalPath.Buffer[outputIndex]);
    normalPath.MaximumLength = normalPath.Length;

cleanup:
    if (status)
    {
        LwRtlUnicodeStringFree(&normalPath);
    }

    *NormalPath = normalPath;

    return status;
}
Ejemplo n.º 13
0
static
NTSTATUS
LwIoFindPathCreds(
    IN PUNICODE_STRING Path,
    IN BOOLEAN bPrecise,
    OUT PIO_PATH_CREDS* ppCreds
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING normalPath = { 0 };
    PIO_PATH_CREDS pFoundCreds = NULL;
    PLW_LIST_LINKS pLink = NULL;

    status = LwIoNormalizePath(Path, &normalPath);
    GOTO_CLEANUP_ON_STATUS(status);

    while ((pLink = LwListTraverse(&gPathCreds, pLink)))
    {
        PIO_PATH_CREDS pCreds = LW_STRUCT_FROM_FIELD(pLink, IO_PATH_CREDS, link);

        if ((bPrecise && LwRtlUnicodeStringIsEqual(&normalPath, &pCreds->PathPrefix, TRUE)) ||
            (!bPrecise && LwRtlUnicodeStringIsPrefix(&pCreds->PathPrefix, &normalPath, TRUE)))
        {
            pFoundCreds = pCreds;
            break;
        }
    }

cleanup:
    if (status)
    {
        pFoundCreds = NULL;
    }

    LwRtlUnicodeStringFree(&normalPath);

    *ppCreds = pFoundCreds;

    return status;
}
Ejemplo n.º 14
0
NTSTATUS
RtlAccessTokenToSelfRelativeAccessToken(
    IN PACCESS_TOKEN pToken,
    OUT OPTIONAL PACCESS_TOKEN_SELF_RELATIVE pRelative,
    IN OUT PULONG pulSize
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN isLocked = FALSE;
    ULONG ulRelativeSize = RtlAccessTokenRelativeSize(pToken);
    PSID_AND_ATTRIBUTES_SELF_RELATIVE pGroups = NULL;
    PBYTE pBuffer = NULL;
    ULONG ulOffset = 0;
    ULONG i = 0;

    if (pRelative)
    {
        if (*pulSize < ulRelativeSize)
        {
            status = STATUS_BUFFER_TOO_SMALL;
            GOTO_CLEANUP_ON_STATUS(status);
        }

        pBuffer = (PBYTE) pRelative;
        
        SHARED_LOCK_RWLOCK(&pToken->RwLock, isLocked);

        pRelative->Flags = pToken->Flags;
        pRelative->User.Attributes = pToken->User.Attributes;
        pRelative->GroupCount = pToken->GroupCount;
        pRelative->PrivilegeCount = pToken->PrivilegeCount;
        pRelative->Uid = pToken->Uid;
        pRelative->Gid = pToken->Gid;
        pRelative->Umask = pToken->Umask;
        
        ulOffset += sizeof(*pRelative);
        Align32(&ulOffset);
        
        pRelative->User.SidOffset = ulOffset;
        memcpy(pBuffer + ulOffset, pToken->User.Sid, RtlLengthSid(pToken->User.Sid));
        ulOffset += RtlLengthSid(pToken->User.Sid);
        Align32(&ulOffset);
        
        if (pToken->Groups)
        {
            pRelative->GroupsOffset = ulOffset;
            pGroups = (PSID_AND_ATTRIBUTES_SELF_RELATIVE) (pBuffer + ulOffset);
            ulOffset += sizeof(SID_AND_ATTRIBUTES_SELF_RELATIVE) * pToken->GroupCount;
            Align32(&ulOffset);
            
            for (i = 0; i < pToken->GroupCount; i++)
            {
                pGroups[i].Attributes = pToken->Groups[i].Attributes;
                pGroups[i].SidOffset = ulOffset;
                memcpy(pBuffer + ulOffset, pToken->Groups[i].Sid, RtlLengthSid(pToken->Groups[i].Sid));
                ulOffset += RtlLengthSid(pToken->Groups[i].Sid);
                Align32(&ulOffset);
            }
        }
        else
        {
            pRelative->GroupsOffset = 0;
        }
        
        if (pToken->Privileges)
        {
            pRelative->PrivilegesOffset = ulOffset;
            memcpy(pBuffer + ulOffset,
                   pToken->Privileges,
                   sizeof(pToken->Privileges[0]) * pToken->PrivilegeCount);
            ulOffset += sizeof(pToken->Privileges[0]) * pToken->PrivilegeCount;
            Align32(&ulOffset);
        }
        else
        {
            pRelative->PrivilegesOffset = 0;
        }

        if (pToken->Owner)
        {
            pRelative->OwnerOffset = ulOffset;
            memcpy(pBuffer + ulOffset, pToken->Owner, RtlLengthSid(pToken->Owner));
            ulOffset += RtlLengthSid(pToken->Owner);
            Align32(&ulOffset);
        }
        else
        {
            pRelative->OwnerOffset = 0;
        }
        
        if (pToken->PrimaryGroup)
        {
            pRelative->PrimaryGroupOffset = ulOffset;
            memcpy(pBuffer + ulOffset, pToken->PrimaryGroup, RtlLengthSid(pToken->PrimaryGroup));
            ulOffset += RtlLengthSid(pToken->PrimaryGroup);
            Align32(&ulOffset);
        }
        else
        {
            pRelative->PrimaryGroupOffset = 0;
        }
        
        if (pToken->DefaultDacl)
        {
            pRelative->DefaultDaclOffset = ulOffset;
            memcpy(pBuffer + ulOffset, pToken->DefaultDacl, RtlGetAclSize(pToken->DefaultDacl));
            ulOffset += RtlGetAclSize(pToken->DefaultDacl);
            Align32(&ulOffset);
        }
        else
        {
            pRelative->DefaultDaclOffset = 0;
        }
        

        assert(ulOffset == ulRelativeSize);
    }

cleanup:
    UNLOCK_RWLOCK(&pToken->RwLock, isLocked);

    *pulSize = ulRelativeSize;

    return status;
}
Ejemplo n.º 15
0
NTSTATUS
RtlSelfRelativeAccessTokenToAccessToken(
    IN PACCESS_TOKEN_SELF_RELATIVE pRelative,
    IN ULONG ulRelativeSize,
    OUT PACCESS_TOKEN* ppToken
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    ULONG ulOffset = 0;
    PBYTE pBuffer = (PBYTE) pRelative;
    PSID pSid = NULL;
    PSID_AND_ATTRIBUTES_SELF_RELATIVE pGroups = NULL;
    ULONG ulSize = 0;
    ULONG ulRealSize = 0;
    ULONG i = 0;
    TOKEN_USER User = {{0}};
    TOKEN_OWNER Owner = {0};
    TOKEN_PRIMARY_GROUP PrimaryGroup = {0};
    TOKEN_UNIX Unix = {0};
    PTOKEN_GROUPS pTokenGroups = NULL;
    PTOKEN_PRIVILEGES pTokenPrivileges = NULL;
    TOKEN_DEFAULT_DACL DefaultDacl = {0};

    status = CheckOffset(0, sizeof(*pRelative), ulRelativeSize);
    GOTO_CLEANUP_ON_STATUS(status);

    if (pRelative->Flags & ACCESS_TOKEN_FLAG_UNIX_PRESENT)
    {
        Unix.Uid = pRelative->Uid;
        Unix.Gid = pRelative->Gid;
        Unix.Umask = pRelative->Umask;
    }

    User.User.Attributes = pRelative->User.Attributes;
    ulOffset = pRelative->User.SidOffset;
    pSid = (PSID) (pBuffer + ulOffset);
    status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize);
    GOTO_CLEANUP_ON_STATUS(status);
    
    User.User.Sid = pSid;

    ulOffset = pRelative->GroupsOffset;
    if (ulOffset)
    {
        status = LwRtlSafeMultiplyULONG(
            &ulSize,
            sizeof(SID_AND_ATTRIBUTES_SELF_RELATIVE),
            pRelative->GroupCount);
        GOTO_CLEANUP_ON_STATUS(status);

        status = LwRtlSafeMultiplyULONG(
            &ulRealSize,
            sizeof(SID_AND_ATTRIBUTES),
            pRelative->GroupCount);
        GOTO_CLEANUP_ON_STATUS(status);

        status = LwRtlSafeAddULONG(
            &ulRealSize,
            ulRealSize,
            sizeof(TOKEN_GROUPS));
        GOTO_CLEANUP_ON_STATUS(status);

        status = CheckOffset(ulOffset, ulSize, ulRelativeSize);
        GOTO_CLEANUP_ON_STATUS(status);

        pGroups = (PSID_AND_ATTRIBUTES_SELF_RELATIVE) (pBuffer + ulOffset);
        
        status = RTL_ALLOCATE(&pTokenGroups, TOKEN_GROUPS, ulRealSize);
        GOTO_CLEANUP_ON_STATUS(status);
        
        pTokenGroups->GroupCount = pRelative->GroupCount;

        for (i = 0; i < pRelative->GroupCount; i++)
        {
            pTokenGroups->Groups[i].Attributes = pGroups[i].Attributes;
            
            ulOffset = pGroups[i].SidOffset;
            pSid = (PSID) (pBuffer + ulOffset);
            status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize);
            GOTO_CLEANUP_ON_STATUS(status);
            
            pTokenGroups->Groups[i].Sid = pSid;
        }
    }

    ulOffset = pRelative->PrivilegesOffset;
    if (ulOffset)
    {
        status = LwRtlSafeMultiplyULONG(
            &ulSize,
            sizeof(LUID_AND_ATTRIBUTES),
            pRelative->PrivilegeCount);
        GOTO_CLEANUP_ON_STATUS(status);

        status = LwRtlSafeMultiplyULONG(
            &ulRealSize,
            sizeof(LUID_AND_ATTRIBUTES),
            pRelative->PrivilegeCount);
        GOTO_CLEANUP_ON_STATUS(status);

        status = LwRtlSafeAddULONG(
            &ulRealSize,
            ulRealSize,
            sizeof(TOKEN_PRIVILEGES));
        GOTO_CLEANUP_ON_STATUS(status);

        status = CheckOffset(ulOffset, ulSize, ulRelativeSize);
        GOTO_CLEANUP_ON_STATUS(status);

        status = RTL_ALLOCATE(&pTokenPrivileges, TOKEN_PRIVILEGES, ulRealSize);
        GOTO_CLEANUP_ON_STATUS(status);

        pTokenPrivileges->PrivilegeCount = pRelative->PrivilegeCount;
        memcpy(pTokenPrivileges->Privileges,
               pBuffer + ulOffset,
               sizeof(LUID_AND_ATTRIBUTES) * pTokenPrivileges->PrivilegeCount);
        
    }

    ulOffset = pRelative->OwnerOffset;
    if (ulOffset)
    {
        pSid = (PSID) (pBuffer + ulOffset);
        status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize);
        GOTO_CLEANUP_ON_STATUS(status);
    
        Owner.Owner = pSid;
    }

    ulOffset = pRelative->PrimaryGroupOffset;
    if (ulOffset)
    {
        pSid = (PSID) (pBuffer + ulOffset);
        status = RtlValidateSelfRelativeSid(pSid, ulOffset, ulRelativeSize);
        GOTO_CLEANUP_ON_STATUS(status);
        
        PrimaryGroup.PrimaryGroup = pSid;
    }

    status = RtlCreateAccessToken(
        ppToken,
        &User,
        pTokenGroups,
        pTokenPrivileges,
        &Owner,
        &PrimaryGroup,
        &DefaultDacl,
        pRelative->Flags & ACCESS_TOKEN_FLAG_UNIX_PRESENT ? &Unix : NULL);
    GOTO_CLEANUP_ON_STATUS(status);

cleanup:

    RTL_FREE(&pTokenGroups);

    if (!NT_SUCCESS(status))
    {
        *ppToken = NULL;
    }

    return status;
}
Ejemplo n.º 16
0
NTSTATUS
RtlCreateAccessToken(
    OUT PACCESS_TOKEN* AccessToken,
    IN PTOKEN_USER User,
    IN PTOKEN_GROUPS Groups,
    IN PTOKEN_PRIVILEGES Privileges,
    IN PTOKEN_OWNER Owner,
    IN PTOKEN_PRIMARY_GROUP PrimaryGroup,
    IN PTOKEN_DEFAULT_DACL DefaultDacl,
    IN OPTIONAL PTOKEN_UNIX Unix
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    int unixError = 0;
    ULONG requiredSize = 0;
    PACCESS_TOKEN token = NULL;
    ULONG i = 0;
    ULONG size = 0;
    PVOID location = NULL;

    if (!User || !User->User.Sid ||
        !Groups ||
        !Owner ||
        !PrimaryGroup ||
        !DefaultDacl)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!RtlValidSid(User->User.Sid) ||
        (Owner->Owner && !RtlValidSid(Owner->Owner)) ||
        (PrimaryGroup->PrimaryGroup && !RtlValidSid(PrimaryGroup->PrimaryGroup)))
    {
        status = STATUS_INVALID_SID;
        GOTO_CLEANUP();
    }

    // No user attributes currently exist.
    if (User->User.Attributes != 0)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    for (i = 0; i < Groups->GroupCount; i++)
    {
        // TODO-Perhaps validate Group attributes
        if (!Groups->Groups[i].Sid)
        {
            status = STATUS_INVALID_PARAMETER;
            GOTO_CLEANUP();
        }
        if (!RtlValidSid(Groups->Groups[i].Sid))
        {
            status = STATUS_INVALID_SID;
            GOTO_CLEANUP();
        }
    }

    if (DefaultDacl->DefaultDacl &&
        !RtlValidAcl(DefaultDacl->DefaultDacl, NULL))
    {
        status = STATUS_INVALID_ACL;
        GOTO_CLEANUP();
    }

    // Compute size required

    requiredSize = sizeof(*token);

    size = RtlLengthSid(User->User.Sid);
    status = RtlSafeAddULONG(&requiredSize, requiredSize, size);
    GOTO_CLEANUP_ON_STATUS(status);

    if (Owner->Owner)
    {
        size = RtlLengthSid(Owner->Owner);
        status = RtlSafeAddULONG(&requiredSize, requiredSize, size);
        GOTO_CLEANUP_ON_STATUS(status);
    }

    if (PrimaryGroup->PrimaryGroup)
    {
        size = RtlLengthSid(PrimaryGroup->PrimaryGroup);
        status = RtlSafeAddULONG(&requiredSize, requiredSize, size);
        GOTO_CLEANUP_ON_STATUS(status);
    }

    if (DefaultDacl->DefaultDacl)
    {
        status = RtlSafeAddULONG(&requiredSize, requiredSize,
                                 DefaultDacl->DefaultDacl->AclSize);
        GOTO_CLEANUP_ON_STATUS(status);
    }

    status = RtlSafeMultiplyULONG(&size, sizeof(Groups->Groups[0]), Groups->GroupCount);
    GOTO_CLEANUP_ON_STATUS(status);

    status = RtlSafeAddULONG(&requiredSize, requiredSize, size);
    GOTO_CLEANUP_ON_STATUS(status);

    for (i = 0; i < Groups->GroupCount; i++)
    {
        size = RtlLengthSid(Groups->Groups[i].Sid);

        status = RtlSafeAddULONG(&requiredSize, requiredSize, size);
        GOTO_CLEANUP_ON_STATUS(status);
    }

    status = RtlSafeMultiplyULONG(&size,
                                  sizeof(Privileges->Privileges[0]),
                                  Privileges->PrivilegeCount);
    GOTO_CLEANUP_ON_STATUS(status);

    status = RtlSafeAddULONG(&requiredSize, requiredSize, size);
    GOTO_CLEANUP_ON_STATUS(status);

    status = RTL_ALLOCATE(&token, ACCESS_TOKEN, requiredSize);
    GOTO_CLEANUP_ON_STATUS(status);

    location = LW_PTR_ADD(token, sizeof(*token));

    // Initialize

    token->ReferenceCount = 1;
    token->Flags = 0;
    unixError = pthread_rwlock_init(&token->RwLock, NULL);
    if (unixError)
    {
        LW_RTL_LOG_ERROR("Failed to init rwlock in access token "
                         "(error = %d).", unixError);
        status = LwErrnoToNtStatus(unixError);
        GOTO_CLEANUP();
    }
    token->pRwLock = &token->RwLock;

    token->User.Attributes = User->User.Attributes;
    token->User.Sid = (PSID) location;
    location = RtlpAppendData(location,
                              User->User.Sid,
                              RtlLengthSid(User->User.Sid));

    token->GroupCount = Groups->GroupCount;
    token->Groups = (PSID_AND_ATTRIBUTES) location;
    location = LwRtlOffsetToPointer(location, sizeof(Groups->Groups[0]) * Groups->GroupCount);
    for (i = 0; i < Groups->GroupCount; i++)
    {
        token->Groups[i].Attributes = Groups->Groups[i].Attributes;
        token->Groups[i].Sid = (PSID) location;
        location = RtlpAppendData(location,
                                  Groups->Groups[i].Sid,
                                  RtlLengthSid(Groups->Groups[i].Sid));
    }

    token->PrivilegeCount = Privileges->PrivilegeCount;
    token->Privileges = (PLUID_AND_ATTRIBUTES) location;
    location = LwRtlOffsetToPointer(
                location,
                sizeof(Privileges->Privileges[0]) * Privileges->PrivilegeCount);
    memcpy(token->Privileges,
           Privileges->Privileges,
           sizeof(token->Privileges[0]) * token->PrivilegeCount);

    if (Owner->Owner)
    {
        token->Owner = (PSID) location;
        location = RtlpAppendData(location,
                                  Owner->Owner,
                                  RtlLengthSid(Owner->Owner));
    }

    if (PrimaryGroup->PrimaryGroup)
    {
        token->PrimaryGroup = (PSID) location;
        location = RtlpAppendData(location,
                                  PrimaryGroup->PrimaryGroup,
                                  RtlLengthSid(PrimaryGroup->PrimaryGroup));
    }

    if (DefaultDacl->DefaultDacl)
    {
        token->DefaultDacl = (PACL) location;
        location = RtlpAppendData(location,
                                  DefaultDacl->DefaultDacl,
                                  DefaultDacl->DefaultDacl->AclSize);
    }

    if (Unix)
    {
        SetFlag(token->Flags, ACCESS_TOKEN_FLAG_UNIX_PRESENT);
        token->Uid = Unix->Uid;
        token->Gid = Unix->Gid;
        token->Umask = Unix->Umask;
    }

    if (location != LW_PTR_ADD(token, requiredSize))
    {
        status = STATUS_ASSERTION_FAILURE;
        GOTO_CLEANUP();
    }

    status = STATUS_SUCCESS;

cleanup:
    if (!NT_SUCCESS(status))
    {
        RtlReleaseAccessToken(&token);
    }

    *AccessToken = token;

    return status;
}
Ejemplo n.º 17
0
NTSTATUS
RtlQueryAccessTokenInformation(
    IN PACCESS_TOKEN AccessToken,
    IN TOKEN_INFORMATION_CLASS TokenInformationClass,
    OUT OPTIONAL PVOID TokenInformation,
    IN ULONG TokenInformationLength,
    OUT PULONG ReturnedLength
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN isLocked = FALSE;
    ULONG requiredSize = 0;
    ULONG i = 0;
    PVOID location = NULL;

    if (!AccessToken || !ReturnedLength)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!TokenInformation && (TokenInformationLength != 0))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    SHARED_LOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    // Check required size
    switch (TokenInformationClass)
    {
        case TokenUser:
            status = RtlSafeAddULONG(
                            &requiredSize,
                            sizeof(TOKEN_USER),
                            RtlLengthSid(AccessToken->User.Sid));
            GOTO_CLEANUP_ON_STATUS(status);
            break;
        case TokenGroups:
            status = RtlSafeMultiplyULONG(
                        &requiredSize,
                        sizeof(AccessToken->Groups[0]),
                        AccessToken->GroupCount);
            GOTO_CLEANUP_ON_STATUS(status);

            status = RtlSafeAddULONG(&requiredSize, requiredSize, sizeof(TOKEN_GROUPS));
            GOTO_CLEANUP_ON_STATUS(status);

            for (i = 0; i < AccessToken->GroupCount; i++)
            {
                status = RtlSafeAddULONG(
                                &requiredSize,
                                requiredSize,
                                RtlLengthSid(AccessToken->Groups[i].Sid));
                GOTO_CLEANUP_ON_STATUS(status);
            }
            break;
        case TokenPrivileges:
            status = RtlSafeMultiplyULONG(
                            &requiredSize,
                            sizeof(AccessToken->Privileges[0]),
                            AccessToken->PrivilegeCount);
            GOTO_CLEANUP_ON_STATUS(status);

            status = RtlSafeAddULONG(&requiredSize, requiredSize, sizeof(TOKEN_PRIVILEGES));
            GOTO_CLEANUP_ON_STATUS(status);
            break;
        case TokenOwner:
            status = RtlSafeAddULONG(
                            &requiredSize,
                            sizeof(TOKEN_OWNER),
                            RtlLengthSid(AccessToken->Owner));
            GOTO_CLEANUP_ON_STATUS(status);
            break;
        case TokenPrimaryGroup:
            status = RtlSafeAddULONG(
                            &requiredSize,
                            sizeof(TOKEN_PRIMARY_GROUP),
                            RtlLengthSid(AccessToken->PrimaryGroup));
            GOTO_CLEANUP_ON_STATUS(status);
            break;
        case TokenDefaultDacl:
            status = RtlSafeAddULONG(
                            &requiredSize,
                            sizeof(TOKEN_DEFAULT_DACL),
                            (AccessToken->DefaultDacl ?
                             AccessToken->DefaultDacl->AclSize :
                             0));
            GOTO_CLEANUP_ON_STATUS(status);
            break;
        default:
            status = STATUS_INVALID_PARAMETER;
            GOTO_CLEANUP();
    }

    if (requiredSize > TokenInformationLength)
    {
        status = STATUS_BUFFER_TOO_SMALL;
        GOTO_CLEANUP();
    }

    if (!TokenInformation)
    {
        status = STATUS_ASSERTION_FAILURE;
        GOTO_CLEANUP();
    }

    // Copy data
    switch (TokenInformationClass)
    {
        case TokenUser:
        {
            PTOKEN_USER tokenInfo = (PTOKEN_USER) TokenInformation;
            location = LW_PTR_ADD(TokenInformation, sizeof(TOKEN_USER));
            tokenInfo->User.Attributes = AccessToken->User.Attributes;
            tokenInfo->User.Sid = (PSID) location;
            location = RtlpAppendData(location,
                                      AccessToken->User.Sid,
                                      RtlLengthSid(AccessToken->User.Sid));
            break;
        }
        case TokenGroups:
        {
            PTOKEN_GROUPS tokenInfo = (PTOKEN_GROUPS) TokenInformation;
            location = LW_PTR_ADD(TokenInformation,
                                  (sizeof(TOKEN_GROUPS) + 
                                   (sizeof(AccessToken->Groups[0]) * AccessToken->GroupCount)));
            tokenInfo->GroupCount = AccessToken->GroupCount;
            for (i = 0; i < AccessToken->GroupCount; i++)
            {
                tokenInfo->Groups[i].Attributes = AccessToken->Groups[i].Attributes;
                tokenInfo->Groups[i].Sid = (PSID) location;
                location = RtlpAppendData(location,
                                          AccessToken->Groups[i].Sid,
                                          RtlLengthSid(AccessToken->Groups[i].Sid));
            }
            break;
        }
        case TokenPrivileges:
        {
            PTOKEN_PRIVILEGES tokenInfo = (PTOKEN_PRIVILEGES) TokenInformation;
            location = LW_PTR_ADD(TokenInformation,
                                  (sizeof(TOKEN_PRIVILEGES) +
                                   (sizeof(AccessToken->Privileges[0]) * AccessToken->PrivilegeCount)));
            tokenInfo->PrivilegeCount = AccessToken->PrivilegeCount;
            if (AccessToken->PrivilegeCount)
            {
                memcpy(tokenInfo->Privileges,
                       AccessToken->Privileges,
                       sizeof(tokenInfo->Privileges[0]) * tokenInfo->PrivilegeCount);
            }
            break;
        }
        case TokenOwner:
        {
            PTOKEN_OWNER tokenInfo = (PTOKEN_OWNER) TokenInformation;
            location = LW_PTR_ADD(TokenInformation, sizeof(TOKEN_OWNER));
            tokenInfo->Owner = (PSID) location;
            location = RtlpAppendData(location,
                                      AccessToken->Owner,
                                      RtlLengthSid(AccessToken->Owner));
            break;
        }
        case TokenPrimaryGroup:
        {
            PTOKEN_PRIMARY_GROUP tokenInfo = (PTOKEN_PRIMARY_GROUP) TokenInformation;
            location = LW_PTR_ADD(TokenInformation, sizeof(TOKEN_PRIMARY_GROUP));
            tokenInfo->PrimaryGroup = (PSID) location;
            location = RtlpAppendData(location,
                                      AccessToken->PrimaryGroup,
                                      RtlLengthSid(AccessToken->PrimaryGroup));
            break;
        }
        case TokenDefaultDacl:
        {
            PTOKEN_DEFAULT_DACL tokenInfo = (PTOKEN_DEFAULT_DACL) TokenInformation;
            location = LW_PTR_ADD(TokenInformation, sizeof(TOKEN_DEFAULT_DACL));
            if (AccessToken->DefaultDacl)
            {
                tokenInfo->DefaultDacl = (PACL) location;
                location = RtlpAppendData(location,
                                          AccessToken->DefaultDacl,
                                          AccessToken->DefaultDacl->AclSize);
            }
            break;
        }
        default:
            // We should have already checked.
            status = STATUS_ASSERTION_FAILURE;
            GOTO_CLEANUP();
    }

    if (location != LW_PTR_ADD(TokenInformation, requiredSize))
    {
        status = STATUS_ASSERTION_FAILURE;
        GOTO_CLEANUP();
    }

    status = STATUS_SUCCESS;

cleanup:
    UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (ReturnedLength)
    {
        *ReturnedLength = requiredSize;
    }

    return status;
}
Ejemplo n.º 18
0
BOOLEAN
RtlAccessCheckEx(
    IN PSECURITY_DESCRIPTOR_ABSOLUTE SecurityDescriptor,
    IN PACCESS_TOKEN AccessToken,
    IN ACCESS_MASK DesiredAccess,
    IN ACCESS_MASK PreviouslyGrantedAccess,
    IN PGENERIC_MAPPING GenericMapping,
    OUT PACCESS_MASK RemainingDesiredAccess,
    OUT PACCESS_MASK GrantedAccess,
    OUT PNTSTATUS AccessStatus
    )
{
    NTSTATUS status = STATUS_ACCESS_DENIED;
    BOOLEAN isLocked = FALSE;
    ACCESS_MASK grantedAccess = PreviouslyGrantedAccess;
    ACCESS_MASK deniedAccess = 0;
    ACCESS_MASK desiredAccess = DesiredAccess;
    BOOLEAN wantMaxAllowed = FALSE;
    USHORT aclSizeUsed = 0;
    USHORT aceOffset = 0;
    PACE_HEADER aceHeader = NULL;
    union {
        SID Sid;
        BYTE Buffer[SID_MAX_SIZE];
    } sidBuffer;
    ULONG ulSidSize = sizeof(sidBuffer);

    if (!SecurityDescriptor || !AccessToken || !GenericMapping)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!LW_IS_VALID_FLAGS(DesiredAccess, VALID_DESIRED_ACCESS_MASK))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!LW_IS_VALID_FLAGS(PreviouslyGrantedAccess, VALID_GRANTED_ACCESS_MASK))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if ((SecurityDescriptor->Owner == NULL) || 
        (SecurityDescriptor->Group == NULL))
    {
        status = STATUS_INVALID_SECURITY_DESCR;
        GOTO_CLEANUP();
    }

    wantMaxAllowed = IsSetFlag(desiredAccess, MAXIMUM_ALLOWED);
    ClearFlag(desiredAccess, MAXIMUM_ALLOWED);

    RtlMapGenericMask(&desiredAccess, GenericMapping);

    //
    // NT AUTHORITY\SYSTEM is always allowed an access
    //
    status = RtlCreateWellKnownSid(WinLocalSystemSid,
                                   NULL,
                                   &sidBuffer.Sid,
                                   &ulSidSize);
    GOTO_CLEANUP_ON_STATUS(status);

    SHARED_LOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
    {
        if (wantMaxAllowed)
        {
            SetFlag(desiredAccess, STANDARD_RIGHTS_ALL);
            SetFlag(desiredAccess, GENERIC_ALL);
            RtlMapGenericMask(&desiredAccess, GenericMapping);
        }
        SetFlag(grantedAccess, desiredAccess);
        desiredAccess = 0;

        status = STATUS_SUCCESS;
        GOTO_CLEANUP();
    }

    if (wantMaxAllowed || IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY))
    {
        // TODO-Handle ACCESS_SYSTEM_SECURITY by checking SE_SECURITY_NAME
        // privilege.  For now, requesting ACCESS_SYSTEM_SECURITY is not
        // allowed.

        ulSidSize = sizeof(sidBuffer);
        status = RtlCreateWellKnownSid(
                     WinBuiltinAdministratorsSid,
                     NULL,
                     &sidBuffer.Sid,
                     &ulSidSize);
        GOTO_CLEANUP_ON_STATUS(status);

        if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
        {
            SetFlag(grantedAccess, ACCESS_SYSTEM_SECURITY);
            ClearFlag(desiredAccess, ACCESS_SYSTEM_SECURITY);
        }
        else if (IsSetFlag(desiredAccess, ACCESS_SYSTEM_SECURITY))
        {
            status = STATUS_PRIVILEGE_NOT_HELD;
            GOTO_CLEANUP();
        }
    }

    if (wantMaxAllowed || IsSetFlag(desiredAccess, WRITE_OWNER))
    {
        // TODO-Allow WRITE_OWNER if have SE_TAKE_OWNERSHIP_NAME regardless
        // of DACL.

        //
        // BUILTIN\Administrators are always allowed WRITE_OWNER
        //

        ulSidSize = sizeof(sidBuffer);
        status = RtlCreateWellKnownSid(
                     WinBuiltinAdministratorsSid,
                     NULL,
                     &sidBuffer.Sid,
                     &ulSidSize);
        GOTO_CLEANUP_ON_STATUS(status);

        if (RtlIsSidMemberOfToken(AccessToken, &sidBuffer.Sid))
        {
            SetFlag(grantedAccess, WRITE_OWNER);
            ClearFlag(desiredAccess, WRITE_OWNER);
        }
    }

    //
    // Owner can always read the SD and write the DACL.
    //

    if (wantMaxAllowed || IsSetFlag(desiredAccess, READ_CONTROL | WRITE_DAC))
    {
        if (RtlIsSidMemberOfToken(AccessToken, SecurityDescriptor->Owner))
        {
            if (wantMaxAllowed)
            {
                desiredAccess |= (READ_CONTROL | WRITE_DAC);
            }
                
            SetFlag(grantedAccess, (READ_CONTROL | WRITE_DAC) & desiredAccess);
            ClearFlag(desiredAccess, grantedAccess);
        }
    }

    // TODO-MAXIMUM_ALLOWED wrt privileges and WRITE_OWNER and
    // ACCESS_SYSTEM_SECURITY above.

    if (!SecurityDescriptor->Dacl)
    {
        // TODO-Interplay with special bits above?
        if (wantMaxAllowed)
        {
            SetFlag(desiredAccess, STANDARD_RIGHTS_ALL);
            SetFlag(desiredAccess, GENERIC_ALL);
            RtlMapGenericMask(&desiredAccess, GenericMapping);
        }
        SetFlag(grantedAccess, desiredAccess);
        desiredAccess = 0;

        status = STATUS_SUCCESS;
        GOTO_CLEANUP();
    }

    if (!RtlValidAcl(SecurityDescriptor->Dacl, &aclSizeUsed))
    {
        status = STATUS_INVALID_ACL;
        GOTO_CLEANUP();
    }

    while (wantMaxAllowed || desiredAccess)
    {
        status = RtlIterateAce(SecurityDescriptor->Dacl,
                               aclSizeUsed,
                               &aceOffset,
                               &aceHeader);
        if (STATUS_NO_MORE_ENTRIES == status)
        {
            break;
        }
        GOTO_CLEANUP_ON_STATUS(status);

        // Check ACE
        switch (aceHeader->AceType)
        {
            case ACCESS_ALLOWED_ACE_TYPE:
            {
                PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader;
                ACCESS_MASK mask = ace->Mask;

                RtlMapGenericMask(&mask, GenericMapping);

                if (wantMaxAllowed || IsSetFlag(desiredAccess, mask))
                {
                    // SID in token => add bits to granted bits
                    PSID sid = RtlpGetSidAccessAllowedAce(ace);

                    if (RtlIsSidMemberOfToken(AccessToken, sid))
                    {
                        if (wantMaxAllowed)
                        {
                            SetFlag(grantedAccess, mask & ~deniedAccess);
                        }
                        else
                        {
                            SetFlag(grantedAccess, mask & desiredAccess);
                        }

                        ClearFlag(desiredAccess, grantedAccess);
                    }
                }
                break;
            }
            case ACCESS_DENIED_ACE_TYPE:
            {
                // Allowed and deny ACEs are isomorphic.
                PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE) aceHeader;
                ACCESS_MASK mask = ace->Mask;

                RtlMapGenericMask(&mask, GenericMapping);

                if (wantMaxAllowed || IsSetFlag(desiredAccess, mask))
                {
                    // SID in token => exit with STATUS_ACCESS_DENIED
                    PSID sid = RtlpGetSidAccessAllowedAce(ace);

                    if (RtlIsSidMemberOfToken(AccessToken, sid))
                    {
                        if (wantMaxAllowed)
                        {
                            SetFlag(deniedAccess, mask);
                        }
                        else
                        {
                            status = STATUS_ACCESS_DENIED;
                            GOTO_CLEANUP();
                        }

                        ClearFlag(desiredAccess, deniedAccess);
                    }
                }
                break;
            }
            default:
                // ignore
                break;
        }
    }

    status = desiredAccess ? STATUS_ACCESS_DENIED : STATUS_SUCCESS;

cleanup:
    UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (NT_SUCCESS(status) &&
        !LW_IS_VALID_FLAGS(grantedAccess, VALID_GRANTED_ACCESS_MASK))
    {
        status = STATUS_ASSERTION_FAILURE;
    }
    if (!NT_SUCCESS(status))
    {
        grantedAccess = PreviouslyGrantedAccess;
    }

    if (RemainingDesiredAccess)
    {
        *RemainingDesiredAccess = desiredAccess;
    }

    *GrantedAccess = grantedAccess;
    *AccessStatus = status;

    return NT_SUCCESS(status) ? TRUE : FALSE;
}
Ejemplo n.º 19
0
NTSTATUS
RtlAllocateCStringFromSid(
    OUT PSTR* StringSid,
    IN PSID Sid
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSTR result = NULL;
    size_t size = 0;
    int count = 0;
    ULONG i = 0;

    if (!StringSid || !RtlValidSid(Sid))
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    size = RTLP_STRING_SID_MAX_CHARS(Sid->SubAuthorityCount);

    status = RTL_ALLOCATE(&result, CHAR, size);
    GOTO_CLEANUP_ON_STATUS(status);

    if (Sid->IdentifierAuthority.Value[0] || Sid->IdentifierAuthority.Value[1])
    {
        count += snprintf(result + count,
                          size - count,
                          "S-%u-0x%.2X%.2X%.2X%.2X%.2X%.2X",
                          Sid->Revision,
                          Sid->IdentifierAuthority.Value[0],
                          Sid->IdentifierAuthority.Value[1],
                          Sid->IdentifierAuthority.Value[2],
                          Sid->IdentifierAuthority.Value[3],
                          Sid->IdentifierAuthority.Value[4],
                          Sid->IdentifierAuthority.Value[5]);
    }
    else
    {
        ULONG value = 0;

        value |= (ULONG) Sid->IdentifierAuthority.Value[5];
        value |= (ULONG) Sid->IdentifierAuthority.Value[4] << 8;
        value |= (ULONG) Sid->IdentifierAuthority.Value[3] << 16;
        value |= (ULONG) Sid->IdentifierAuthority.Value[2] << 24;

        count += snprintf(result + count,
                          size - count,
                          "S-%u-%u",
                          Sid->Revision,
                          value);
    }

    for (i = 0; i < Sid->SubAuthorityCount; i++)
    {
        count += snprintf(result + count,
                          size - count,
                          "-%u", 
                          Sid->SubAuthority[i]);
    }

    status = STATUS_SUCCESS;

cleanup:
    if (!NT_SUCCESS(status))
    {
        RTL_FREE(&result);
    }

    if (StringSid)
    {
        *StringSid = result;
    }

    return status;
}
Ejemplo n.º 20
0
NTSTATUS
IopIrpDispatch(
    IN PIRP pIrp,
    IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock,
    OUT PIO_STATUS_BLOCK pIoStatusBlock
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN isAsyncCall = FALSE;
    LW_RTL_EVENT event = LW_RTL_EVENT_ZERO_INITIALIZER;
    PIRP pExtraIrpReference = NULL;
    PIRP_INTERNAL irpInternal = IopIrpGetInternal(pIrp);
    BOOLEAN needCancel = FALSE;
    IRP_TYPE irpType = pIrp->Type;

    LWIO_ASSERT(pIoStatusBlock);

    isAsyncCall = AsyncControlBlock ? TRUE : FALSE;
    if (isAsyncCall)
    {
        LWIO_ASSERT(!AsyncControlBlock->AsyncCancelContext);
        LWIO_ASSERT(AsyncControlBlock->Callback);

        irpInternal->Completion.Async.Callback = AsyncControlBlock->Callback;
        irpInternal->Completion.Async.CallbackContext = AsyncControlBlock->CallbackContext;
        irpInternal->Completion.Async.pIoStatusBlock = pIoStatusBlock;

        // Assert that caller has set required out params via IopIrpSetOutput*().
        LWIO_ASSERT(!IopIrpIsCreate(pIrp) || irpInternal->Completion.Async.OpOut.Create.pFileHandle);
        LWIO_ASSERT(!IopIrpIsPrepareZctReadWrite(pIrp) || irpInternal->Completion.Async.OpOut.PrepareZctReadWrite.pCompletionContext);

        // Reference IRP since we may need to return an an async cancel context.
        IopIrpReference(pIrp);
        pExtraIrpReference = pIrp;
    }
    else
    {
        // Since sync, assert IopIrpSetOutput*() has not actually set anything.
        LWIO_ASSERT(!irpInternal->Completion.IsAsyncCall);

        status = LwRtlInitializeEvent(&event);
        GOTO_CLEANUP_ON_STATUS(status);

        irpInternal->Completion.Sync.Event = &event;
    }

    irpInternal->Completion.IsAsyncCall = isAsyncCall;

    // We have to dispatch once we add the IRP as "dipatched"
    // and we have to call IopIrpCompleteInternal() so that
    // it gets subtracted.

    status = IopFileObjectAddDispatched(pIrp->FileHandle, pIrp->Type);
    GOTO_CLEANUP_ON_STATUS(status);

    SetFlag(irpInternal->Flags, IRP_FLAG_DISPATCHED);

    status = IopDeviceCallDriver(pIrp->DeviceHandle, pIrp);
    // Handle synchronous completion
    if (STATUS_PENDING != status)
    {
        IopIrpCompleteInternal(pIrp, FALSE);
    }
    // Handle asynchronous dispatch
    else
    {
        IopIrpAcquireCancelLock(pIrp);

        LWIO_ASSERT(IsSetFlag(irpInternal->Flags, IRP_FLAG_PENDING));
        LWIO_ASSERT(irpInternal->Cancel.Callback);

        needCancel = IsSetFlag(irpInternal->Flags, IRP_FLAG_CANCEL_PENDING);

        IopIrpReleaseCancelLock(pIrp);

        if (needCancel)
        {
            IopIrpCancel(pIrp);
        }

        // Handle waiting for asynchronous completion for synchronous caller
        if (!isAsyncCall)
        {
            LwRtlWaitEvent(&event, NULL);

            LWIO_ASSERT(pIrp->IoStatusBlock.Status != STATUS_PENDING);
            status = pIrp->IoStatusBlock.Status;
        }
    }

    //
    // At this point, we are either complete or this is
    // an async call that returned STATUS_PENDING.
    //

    LWIO_ASSERT((STATUS_PENDING == status) || (pIrp->IoStatusBlock.Status == status));

cleanup:
    LwRtlCleanupEvent(&event);

    if (STATUS_PENDING == status)
    {
        LWIO_ASSERT(isAsyncCall);

        AsyncControlBlock->AsyncCancelContext = IopIrpGetAsyncCancelContextFromIrp(pIrp);
    }
    else
    {
        if (isAsyncCall)
        {
            //
            // Remove async cancel context reference added earlier since we
            // are returning synchronously w/o an async cancel context.
            //

            IopIrpDereference(&pExtraIrpReference);
        }

        pIrp->IoStatusBlock.Status = status;
        *pIoStatusBlock = pIrp->IoStatusBlock;
    }

    LWIO_ASSERT(IS_BOTH_OR_NEITHER(pExtraIrpReference, (STATUS_PENDING == status)));
    LWIO_ASSERT((STATUS_PENDING != status) || isAsyncCall);
    LWIO_ASSERT(IsValidStatusForIrpType(status, irpType));
    return status;
}
Ejemplo n.º 21
0
LW_NTSTATUS
LwIoRdrGetPhysicalPath(
    IO_FILE_HANDLE File,
    LW_PWSTR* ppResolved
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    IO_STATUS_BLOCK ioStatus;
    ULONG length = RESOLVED_PATH_LENGTH;
    PBYTE pBuffer = NULL;
    PBYTE pNewBuffer = NULL;
    PWSTR pResolved = NULL;

    status = RTL_ALLOCATE(&pBuffer, BYTE, length);
    GOTO_CLEANUP_ON_STATUS(status);

    do
    {
        status =
            LwNtDeviceIoControlFile(
                File,
                NULL,
                &ioStatus,
                RDR_DEVCTL_GET_PHYSICAL_PATH,
                NULL,
                0,
                pBuffer,
                length);

        if (status == STATUS_BUFFER_TOO_SMALL)
        {
            length *= 2;
            pNewBuffer = LwRtlMemoryRealloc(pBuffer, length);
            if (!pNewBuffer)
            {
                status = STATUS_INSUFFICIENT_RESOURCES;
                GOTO_CLEANUP_ON_STATUS(status);
            }
            pBuffer = pNewBuffer;
        }
    } while (status == STATUS_BUFFER_TOO_SMALL);

    GOTO_CLEANUP_ON_STATUS(status);

    if (ioStatus.BytesTransferred > 0)
    {
        status = LW_RTL_ALLOCATE(
            &pResolved,
            WCHAR,
            ioStatus.BytesTransferred + sizeof(WCHAR));
        GOTO_CLEANUP_ON_STATUS(status);

#ifdef WORDS_BIGENDIAN
        swab(pBuffer, pResolved, ioStatus.BytesTransferred);
#else
        memcpy(pResolved, pBuffer, ioStatus.BytesTransferred);
#endif
    }

cleanup:

    *ppResolved = pResolved;

    RTL_FREE(&pBuffer);

    return status;
}