Beispiel #1
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;
}
Beispiel #2
0
static
VOID
RdrNegotiateGssContextWorkItem(
    PVOID pParam
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRDR_OP_CONTEXT pContext = pParam;
    PRDR_SESSION pSession = pContext->State.TreeConnect.pSession;
    PRDR_SOCKET pSocket = pSession->pSocket;
    PSMB_PACKET pPacket = pContext->State.TreeConnect.pPacket;
    PWSTR pwszNativeOS = NULL;
    PWSTR pwszNativeLanman = NULL;
    PWSTR pwszNativeDomain = NULL;
    PBYTE pInBlob = NULL;
    DWORD dwInBlobLength = 0;
    PBYTE pOutBlob = NULL;
    DWORD dwOutBlobLength = 0;
    PSESSION_SETUP_RESPONSE_HEADER_WC_4 pResponseHeader = NULL;
    BOOLEAN bSessionLocked = FALSE;

    if (pPacket)
    {
        status = UnmarshallSessionSetupResponse_WC_4(
            pPacket->pParams,
            pPacket->bufferLen - pPacket->bufferUsed,
            0,
            &pResponseHeader,
            &pInBlob,
            &pwszNativeOS,
            &pwszNativeLanman,
            &pwszNativeDomain);
        BAIL_ON_NT_STATUS(status);

        dwInBlobLength = pResponseHeader->securityBlobLength;
    }
    else
    {
        pInBlob = pSession->pSocket->pSecurityBlob;
        dwInBlobLength = pSession->pSocket->securityBlobLen;
    }

    if (pContext->State.TreeConnect.pszCachePath)
    {
        status = SMBKrb5SetDefaultCachePath(
            pContext->State.TreeConnect.pszCachePath,
            NULL);
        BAIL_ON_NT_STATUS(status);
    }

    if (!pContext->State.TreeConnect.hGssContext)
    {
        status = SMBGSSContextBuild(
            pSocket->pwszCanonicalName,
            pContext->State.TreeConnect.pCreds,
            &pContext->State.TreeConnect.hGssContext);
        BAIL_ON_NT_STATUS(status);
    }

    status = SMBGSSContextNegotiate(
        pContext->State.TreeConnect.hGssContext,
        pInBlob,
        dwInBlobLength,
        &pOutBlob,
        &dwOutBlobLength);
    BAIL_ON_NT_STATUS(status);

    if (!SMBGSSContextNegotiateComplete(pContext->State.TreeConnect.hGssContext))
    {
        pContext->Continue = RdrProcessSessionSetupResponse;

        status = RdrTransceiveSessionSetup(
            pContext,
            pSession,
            pOutBlob,
            dwOutBlobLength);
        BAIL_ON_NT_STATUS(status);
    }
    else
    {
        LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

        if (pContext->Packet.haveSignature &&
            (!memcmp(pPacket->pSMBHeader->extra.securitySignature,
                     pContext->Packet.pSMBHeader->extra.securitySignature,
                     sizeof(pContext->Packet.pSMBHeader->extra.securitySignature))))
        {
            LWIO_LOG_WARNING("Server is exhibiting signing bug; ignoring signatures from server");
            RdrSocketSetIgnoreServerSignatures(pSocket, TRUE);
        }

        status = SMBGSSContextGetSessionKey(
            pContext->State.TreeConnect.hGssContext,
            &pSession->pSessionKey,
            &pSession->dwSessionKeyLength);
        BAIL_ON_NT_STATUS(status);

        if (!pSocket->pSessionKey && pSession->pSessionKey &&
            !(pContext->State.TreeConnect.pCreds->type == IO_CREDS_TYPE_PLAIN &&
              pContext->State.TreeConnect.pCreds->payload.plain.pwszUsername[0] == '\0'))
        {
            status = LwIoAllocateMemory(
                pSession->dwSessionKeyLength,
                OUT_PPVOID(&pSocket->pSessionKey));
            BAIL_ON_NT_STATUS(status);

            memcpy(pSocket->pSessionKey, pSession->pSessionKey, pSession->dwSessionKeyLength);
            pSocket->dwSessionKeyLength = pSession->dwSessionKeyLength;
            RdrSocketBeginSequence(pSocket);
        }

        status = RdrSocketAddSessionByUID(pSocket, pSession);
        BAIL_ON_NT_STATUS(status);

        pSession->state = RDR_SESSION_STATE_READY;

        RdrNotifyContextList(
            &pSession->StateWaiters,
            bSessionLocked,
            &pSession->mutex,
            status,
            pSession);

        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

        RdrSessionSetupComplete(pContext, status, pSession);

        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

    RTL_FREE(&pOutBlob);

    if (status != STATUS_PENDING)
    {
        if (pContext->State.TreeConnect.hGssContext)
        {
            SMBGSSContextFree(pContext->State.TreeConnect.hGssContext);
        }

        RdrSessionInvalidate(pSession, status);
        RdrSessionRelease(pSession);

        RdrSessionSetupComplete(pContext, status, NULL);
    }

    return;

error:

    goto cleanup;
}
Beispiel #3
0
NTSTATUS
SMBPacketVerifySignature(
    PSMB_PACKET pPacket,
    ULONG       ulExpectedSequence,
    PBYTE       pSessionKey,
    ULONG       ulSessionKeyLength
    )
{
    NTSTATUS ntStatus = 0;
    uint8_t digest[16];
    uint8_t origSignature[8];
    MD5_CTX md5Value;
    uint32_t littleEndianSequence = SMB_HTOL32(ulExpectedSequence);

    assert (sizeof(origSignature) == sizeof(pPacket->pSMBHeader->extra.securitySignature));

    memcpy(origSignature,
           pPacket->pSMBHeader->extra.securitySignature,
           sizeof(pPacket->pSMBHeader->extra.securitySignature));

    memset(&pPacket->pSMBHeader->extra.securitySignature[0],
           0,
           sizeof(pPacket->pSMBHeader->extra.securitySignature));

    memcpy(&pPacket->pSMBHeader->extra.securitySignature[0],
           &littleEndianSequence,
           sizeof(littleEndianSequence));

    MD5_Init(&md5Value);

    if (pSessionKey)
    {
        MD5_Update(&md5Value, pSessionKey, ulSessionKeyLength);
    }

    MD5_Update(&md5Value,
               (PBYTE)pPacket->pSMBHeader,
               pPacket->pNetBIOSHeader->len);
    MD5_Final(digest, &md5Value);

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

    // restore signature
    memcpy(&pPacket->pSMBHeader->extra.securitySignature[0],
           &origSignature[0],
           sizeof(origSignature));

    BAIL_ON_NT_STATUS(ntStatus);

cleanup:

    return ntStatus;

error:

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

    goto cleanup;
}