Пример #1
0
static
NTSTATUS
NtpCtxGetBufferResult(
    OUT PIO_STATUS_BLOCK pIoStatusBlock,
    OUT PVOID Buffer,
    IN ULONG Length,
    IN PNT_IPC_MESSAGE_GENERIC_FILE_BUFFER_RESULT pResponse
    )
{
    pIoStatusBlock->Status = pResponse->Status;
    pIoStatusBlock->BytesTransferred = pResponse->BytesTransferred;
    assert(pResponse->BytesTransferred <= Length);
    memcpy(Buffer, pResponse->Buffer, SMB_MIN(pResponse->BytesTransferred, Length));
    return pIoStatusBlock->Status;
}
Пример #2
0
NTSTATUS
SMB2PacketSign(
    PSMB_PACKET pPacket,
    PBYTE       pSessionKey,
    ULONG       ulSessionKeyLength
    )
{
    NTSTATUS ntStatus = 0;

    if (pSessionKey)
    {
        BYTE  sessionKey[16];
        PBYTE pBuffer = (PBYTE)pPacket->pSMB2Header;
        ULONG ulBytesAvailable = htonl(pPacket->pNetBIOSHeader->len);

        memset(&sessionKey[0], 0, sizeof(sessionKey));
        memcpy(&sessionKey[0],
               pSessionKey,
               SMB_MIN(ulSessionKeyLength, sizeof(sessionKey)));

        while (pBuffer)
        {
            UCHAR ucDigest[EVP_MAX_MD_SIZE];
            ULONG ulDigest = sizeof(ucDigest);
            PSMB2_HEADER pHeader = NULL;
            ULONG ulPacketSize = ulBytesAvailable;

            if (ulBytesAvailable < sizeof(SMB2_HEADER))
            {
                ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
                BAIL_ON_NT_STATUS(ntStatus);
            }

            pHeader = (PSMB2_HEADER)pBuffer;

            if (pHeader->ulChainOffset)
            {
                if (ulBytesAvailable < pHeader->ulChainOffset)
                {
                    ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
                    BAIL_ON_NT_STATUS(ntStatus);
                }

                ulPacketSize = pHeader->ulChainOffset;
            }

            pHeader->ulFlags |= SMB2_FLAGS_SIGNED;

            memset(&pHeader->signature[0],
                   0,
                   sizeof(pHeader->signature));

            HMAC(EVP_sha256(),
                 &sessionKey[0],
                 sizeof(sessionKey),
                 (PBYTE)pHeader,
                 ulPacketSize,
                 &ucDigest[0],
                 &ulDigest);

            memcpy(&pHeader->signature[0],
                   &ucDigest[0],
                   sizeof(pHeader->signature));

            if (pHeader->ulChainOffset)
            {
                pBuffer          += pHeader->ulChainOffset;
                ulBytesAvailable -= pHeader->ulChainOffset;
            }
            else
            {
                pBuffer = NULL;
            }
        }
    }

error:

    return ntStatus;
}
Пример #3
0
static
NTSTATUS
SrvBuildOpenResponse(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                    ntStatus          = 0;
    PLWIO_SRV_CONNECTION        pConnection    = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT  pCtxProtocol   = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1    pCtxSmb1        = pCtxProtocol->pSmb1Context;
    ULONG                       iMsg            = pCtxSmb1->iMsg;
    PSRV_MESSAGE_SMB_V1         pSmbRequest     = &pCtxSmb1->pRequests[iMsg];
    PSRV_MESSAGE_SMB_V1         pSmbResponse    = &pCtxSmb1->pResponses[iMsg];
    POPEN_RESPONSE_HEADER       pResponseHeader = NULL; // Do not free
    PBYTE pOutBuffer       = pSmbResponse->pBuffer;
    ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable;
    ULONG ulOffset         = 0;
    ULONG ulTotalBytesUsed = 0;
    PSRV_OPEN_STATE_SMB_V1 pOpenState = NULL;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;

    if (!pSmbResponse->ulSerialNum)
    {
        ntStatus = SrvMarshalHeader_SMB_V1(
                        pOutBuffer,
                        ulOffset,
                        ulBytesAvailable,
                        COM_OPEN_ANDX,
                        STATUS_SUCCESS,
                        TRUE,
                        pConnection->serverProperties.Capabilities,
                        pOpenState->pTree->tid,
                        SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader),
                        pCtxSmb1->pSession->uid,
                        pSmbRequest->pHeader->mid,
                        pConnection->serverProperties.bRequireSecuritySignatures,
                        &pSmbResponse->pHeader,
                        &pSmbResponse->pWordCount,
                        &pSmbResponse->pAndXHeader,
                        &pSmbResponse->usHeaderSize);
    }
    else
    {
        ntStatus = SrvMarshalHeaderAndX_SMB_V1(
                        pOutBuffer,
                        ulOffset,
                        ulBytesAvailable,
                        COM_OPEN_ANDX,
                        &pSmbResponse->pWordCount,
                        &pSmbResponse->pAndXHeader,
                        &pSmbResponse->usHeaderSize);
    }
    BAIL_ON_NT_STATUS(ntStatus);

    pOutBuffer       += pSmbResponse->usHeaderSize;
    ulOffset         += pSmbResponse->usHeaderSize;
    ulBytesAvailable -= pSmbResponse->usHeaderSize;
    ulTotalBytesUsed += pSmbResponse->usHeaderSize;

    *pSmbResponse->pWordCount = 15;

    if (ulBytesAvailable < sizeof(OPEN_RESPONSE_HEADER))
    {
        ntStatus = STATUS_INVALID_BUFFER_SIZE;
        BAIL_ON_NT_STATUS(ntStatus);
    }

    pResponseHeader = (POPEN_RESPONSE_HEADER)pOutBuffer;

    // pOutBuffer       += sizeof(OPEN_RESPONSE_HEADER);
    // ulOffset         += sizeof(OPEN_RESPONSE_HEADER);
    // ulBytesAvailable -= sizeof(OPEN_RESPONSE_HEADER);
    ulTotalBytesUsed += sizeof(OPEN_RESPONSE_HEADER);

    pResponseHeader->usFid        = pOpenState->pFile->fid;
    pResponseHeader->ulServerFid  = pOpenState->pFile->fid;

    pResponseHeader->usOpenAction = pOpenState->ulCreateAction;
    switch (pOpenState->ucOplockLevel)
    {
        case SMB_OPLOCK_LEVEL_I:

            // file is opened only by this user at the current time
            pResponseHeader->usOpenAction |= 0x8000;

            break;

        default:

            pResponseHeader->usOpenAction &= ~0x8000;

            break;
    }

    // TODO: Mirroring this field is close, but probably not exactly correct
    pResponseHeader->usGrantedAccess = pOpenState->pRequestHeader->usDesiredAccess;

    pResponseHeader->usFileAttributes = pOpenState->networkOpenInfo.FileAttributes;

    ntStatus = WireNTTimeToSMBUTime(
                    pOpenState->networkOpenInfo.LastWriteTime,
                    &pResponseHeader->ulLastWriteTime);
    BAIL_ON_NT_STATUS(ntStatus);

    pResponseHeader->ulDataSize = SMB_MIN(  UINT32_MAX,
                                            pOpenState->networkOpenInfo.EndOfFile);

    if (SrvTreeIsNamedPipe(pOpenState->pTree))
    {
        ntStatus = SrvMarshallPipeInfo(
                        pOpenState->pFilePipeInfo,
                        pOpenState->pFilePipeLocalInfo,
                        &pResponseHeader->usDeviceState);
        BAIL_ON_NT_STATUS(ntStatus);

        pResponseHeader->usFileType = (USHORT)pOpenState->filePipeInfo.ReadMode;
    }
    else
    {
        pResponseHeader->usFileType = 0;
        pResponseHeader->usDeviceState = 0;
    }
    pResponseHeader->usReserved  = 0;
    pResponseHeader->usByteCount = 0;

    pSmbResponse->ulMessageSize = ulTotalBytesUsed;

cleanup:

    return ntStatus;

error:

    if (ulTotalBytesUsed)
    {
        pSmbResponse->pHeader = NULL;
        pSmbResponse->pAndXHeader = NULL;
        memset(pSmbResponse->pBuffer, 0, ulTotalBytesUsed);
    }

    pSmbResponse->ulMessageSize = 0;

    goto cleanup;
}
Пример #4
0
NTSTATUS
SMB2PacketVerifySignature(
    PSMB_PACKET pPacket,
    PBYTE       pSessionKey,
    ULONG       ulSessionKeyLength
    )
{
    NTSTATUS ntStatus = 0;

    if (pSessionKey)
    {
        BYTE    sessionKey[16];
        PBYTE   pBuffer          = pPacket->pRawBuffer + sizeof(NETBIOS_HEADER);
        ULONG   ulBytesAvailable = pPacket->pNetBIOSHeader->len;
        uint8_t origSignature[16];
        UCHAR   ucDigest[EVP_MAX_MD_SIZE];
        ULONG   ulDigest = sizeof(ucDigest);

        if (!pBuffer)
        {
            ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        memset(&sessionKey[0], 0, sizeof(sessionKey));
        memcpy(&sessionKey[0],
               pSessionKey,
               SMB_MIN(ulSessionKeyLength, sizeof(sessionKey)));

        while (pBuffer)
        {
            PSMB2_HEADER pHeader      = NULL;
            ULONG        ulPacketSize = ulBytesAvailable;

            if (ulBytesAvailable < sizeof(SMB2_HEADER))
            {
                ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
                BAIL_ON_NT_STATUS(ntStatus);
            }

            pHeader = (PSMB2_HEADER)pBuffer;

            if (pHeader->ulChainOffset)
            {
                if (ulBytesAvailable < pHeader->ulChainOffset)
                {
                    ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
                    BAIL_ON_NT_STATUS(ntStatus);
                }

                ulPacketSize = pHeader->ulChainOffset;
            }

            memcpy(origSignature,
                   &pHeader->signature[0],
                   sizeof(pHeader->signature));

            memset(&pHeader->signature[0],
                   0,
                   sizeof(pHeader->signature));

            HMAC(EVP_sha256(),
                 &sessionKey[0],
                 sizeof(sessionKey),
                 pBuffer,
                 ulPacketSize,
                 &ucDigest[0],
                 &ulDigest);

            if (memcmp(&origSignature[0], &ucDigest[0], sizeof(origSignature)))
            {
                ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
            }

            // restore signature
            memcpy(&pHeader->signature[0],
                   &origSignature[0],
                   sizeof(origSignature));

            BAIL_ON_NT_STATUS(ntStatus);

            if (pHeader->ulChainOffset)
            {
                pBuffer          += pHeader->ulChainOffset;
                ulBytesAvailable -= pHeader->ulChainOffset;
            }
            else
            {
                pBuffer = NULL;
            }
        }
    }

cleanup:

    return ntStatus;

error:

    LWIO_LOG_WARNING("SMB2 Packet verification failed (status = 0x%08X)", ntStatus);

    goto cleanup;
}