Пример #1
0
NTSTATUS
SMBPacketAllocate(
    IN PLWIO_PACKET_ALLOCATOR pPacketAllocator,
    OUT PSMB_PACKET* ppPacket
    )
{
    NTSTATUS ntStatus = 0;
    PSMB_PACKET pPacket = NULL;

    if (pPacketAllocator)
    {
        ntStatus = SMBPacketAllocatePooled(pPacketAllocator, &pPacket);
        BAIL_ON_NT_STATUS(ntStatus);
    }
    else
    {
        ntStatus = LwIoAllocateMemory(sizeof(SMB_PACKET), (PVOID *) &pPacket);
        BAIL_ON_NT_STATUS(ntStatus);

        InterlockedIncrement(&pPacket->refCount);
    }

    *ppPacket = pPacket;

cleanup:

    return ntStatus;

error:

    *ppPacket = NULL;

    goto cleanup;
}
Пример #2
0
NTSTATUS
SMBPacketCreateAllocator(
    IN ULONG ulNumMaxPackets,
    OUT PLWIO_PACKET_ALLOCATOR* ppPacketAllocator
    )
{
    NTSTATUS ntStatus = 0;
    PLWIO_PACKET_ALLOCATOR pPacketAllocator = NULL;

    ntStatus = LwIoAllocateMemory(
                    sizeof(LWIO_PACKET_ALLOCATOR),
                    (PVOID*)&pPacketAllocator);
    BAIL_ON_NT_STATUS(ntStatus);

    pthread_mutex_init(&pPacketAllocator->mutex, NULL);
    pPacketAllocator->pMutex = &pPacketAllocator->mutex;
    pPacketAllocator->ulNumMaxPackets = ulNumMaxPackets;

    *ppPacketAllocator = pPacketAllocator;

cleanup:

    return ntStatus;

error:

    *ppPacketAllocator = NULL;

    goto cleanup;
}
Пример #3
0
NTSTATUS
LwIoGetThreadState(
    OUT PIO_THREAD_STATE* ppState
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_THREAD_STATE pState = NULL;

    Status = LwIoThreadInit();
    BAIL_ON_NT_STATUS(Status);

    pState = pthread_getspecific(gStateKey);

    if (!pState)
    {
        Status = LwIoAllocateMemory(sizeof(*pState), OUT_PPVOID(&pState));
        BAIL_ON_NT_STATUS(Status);
        
        if (pthread_setspecific(gStateKey, pState))
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            BAIL_ON_NT_STATUS(Status);
        }
    }

    *ppState = pState;

error:

    return Status;
}
Пример #4
0
LW_NTSTATUS
LwIoGetSessionKey(
    IO_FILE_HANDLE File,
    LW_PUSHORT pKeyLength,
    LW_PBYTE* ppKeyBuffer
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    IO_STATUS_BLOCK IoStatus;
    BYTE Buffer[MAX_KEY_LENGTH];
    PBYTE pKeyBuffer = NULL;

    Status = 
        LwNtFsControlFile(
            File,
            NULL,
            &IoStatus,
            IO_FSCTL_SMB_GET_SESSION_KEY,
            NULL,
            0,
            Buffer,
            sizeof(Buffer));
    BAIL_ON_NT_STATUS(Status);

    if (IoStatus.BytesTransferred > 0)
    {
        Status = LwIoAllocateMemory(IoStatus.BytesTransferred, OUT_PPVOID(&pKeyBuffer));
        BAIL_ON_NT_STATUS(Status);

        memcpy(pKeyBuffer, Buffer, IoStatus.BytesTransferred);

        *pKeyLength = IoStatus.BytesTransferred;
        *ppKeyBuffer = pKeyBuffer;
    }
    else
    {
        *pKeyLength = 0;
        *ppKeyBuffer = NULL;
    }

cleanup:

    return Status;

error:

    *pKeyLength = 0;
    *ppKeyBuffer = NULL;

    goto cleanup;
}
Пример #5
0
static
NTSTATUS
SMBPacketAllocatePooled(
    IN PLWIO_PACKET_ALLOCATOR pPacketAllocator,
    OUT PSMB_PACKET* ppPacket
    )
{
    NTSTATUS ntStatus = 0;
    BOOLEAN bInLock = FALSE;
    PSMB_PACKET pPacket = NULL;

    LWIO_LOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

    if (pPacketAllocator->pFreePacketStack)
    {
        pPacket = (PSMB_PACKET) pPacketAllocator->pFreePacketStack;

        SMBStackPopNoFree(&pPacketAllocator->pFreePacketStack);

        pPacketAllocator->freePacketCount--;

        LWIO_UNLOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

        memset(pPacket, 0, sizeof(SMB_PACKET));
    }
    else
    {
        LWIO_UNLOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

        ntStatus = LwIoAllocateMemory(sizeof(SMB_PACKET), (PVOID *) &pPacket);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    InterlockedIncrement(&pPacket->refCount);

    *ppPacket = pPacket;

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

    return ntStatus;

error:

    *ppPacket = NULL;

    goto cleanup;
}
Пример #6
0
NTSTATUS
LwIoCreatePlainCredsW(
    PCWSTR pwszUsername,
    PCWSTR pwszDomain,
    PCWSTR pwszPassword,
    PIO_CREDS* ppCreds
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_CREDS pCreds = NULL;

    Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds));
    BAIL_ON_NT_STATUS(Status);

    pCreds->type = IO_CREDS_TYPE_PLAIN;

    Status = RtlWC16StringDuplicate(
                 &pCreds->payload.plain.pwszUsername,
                 pwszUsername);
    BAIL_ON_NT_STATUS(Status);

    Status = RtlWC16StringDuplicate(
                 &pCreds->payload.plain.pwszDomain,
                 pwszDomain);

    Status = RtlWC16StringDuplicate(
                 &pCreds->payload.plain.pwszPassword,
                 pwszPassword);
    BAIL_ON_NT_STATUS(Status);

    *ppCreds = pCreds;

cleanup:

    return Status;

error:

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    goto cleanup;
}
Пример #7
0
NTSTATUS
SMBPacketBufferAllocate(
    IN  PLWIO_PACKET_ALLOCATOR pPacketAllocator,
    IN  size_t                 len,
    OUT uint8_t**              ppBuffer,
    OUT size_t*                pAllocatedLen
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PBYTE    pBuffer = NULL;
    size_t   allocatedLen = len;

    if (pPacketAllocator)
    {
        ntStatus = SMBPacketBufferAllocatePooled(
                        pPacketAllocator,
                        len,
                        &pBuffer,
                        &allocatedLen);
    }
    else
    {
        // server code needs zero initialized response packets
        ntStatus = LwIoAllocateMemory(len, (PVOID *) &pBuffer);
    }
    BAIL_ON_NT_STATUS(ntStatus);

    *ppBuffer = pBuffer;
    *pAllocatedLen = allocatedLen;

cleanup:

    return ntStatus;

error:

    *ppBuffer = NULL;
    *pAllocatedLen = 0;

    goto cleanup;
}
Пример #8
0
NTSTATUS
LwIoCreateKrb5CredsW(
    PCWSTR pwszPrincipal,
    PCWSTR pwszCachePath,
    PIO_CREDS* ppCreds
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_CREDS pCreds = NULL;

    Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds));
    BAIL_ON_NT_STATUS(Status);

    pCreds->type = IO_CREDS_TYPE_KRB5_CCACHE;

    Status = RtlWC16StringDuplicate(
                 &pCreds->payload.krb5Ccache.pwszPrincipal,
                 pwszPrincipal);
    BAIL_ON_NT_STATUS(Status);

    Status = RtlWC16StringDuplicate(
                 &pCreds->payload.krb5Ccache.pwszCachePath,
                 pwszCachePath);
    BAIL_ON_NT_STATUS(Status);

    *ppCreds = pCreds;

cleanup:

    return Status;

error:

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    goto cleanup;
}
Пример #9
0
DWORD
SMBAllocateString(
    PCSTR  pszInputString,
    PSTR* ppszOutputString
    )
{
    DWORD dwError = 0;
    DWORD dwLen = 0;
    PSTR  pszOutputString = NULL;

    if (!pszInputString) {
        dwError = LWIO_ERROR_INVALID_PARAMETER;
        BAIL_ON_LWIO_ERROR(dwError);
    }

    dwLen = strlen(pszInputString);

    dwError = LwIoAllocateMemory(dwLen+1, (PVOID *)&pszOutputString);
    BAIL_ON_LWIO_ERROR(dwError);

    if (dwLen) {
       memcpy(pszOutputString, pszInputString, dwLen);
    }

    *ppszOutputString = pszOutputString;

cleanup:

    return dwError;

error:

    LWIO_SAFE_FREE_STRING(pszOutputString);

    *ppszOutputString = NULL;

    goto cleanup;
}
Пример #10
0
BOOLEAN
RdrCreateTreeConnect2Complete(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_TREE2 pTree = pParam;
    PIRP pIrp = pContext->pIrp;
    ACCESS_MASK DesiredAccess = pIrp->Args.Create.DesiredAccess;
    LONG64 AllocationSize = pIrp->Args.Create.AllocationSize;
    FILE_SHARE_FLAGS ShareAccess = pIrp->Args.Create.ShareAccess;
    FILE_CREATE_DISPOSITION CreateDisposition = pIrp->Args.Create.CreateDisposition;
    FILE_CREATE_OPTIONS CreateOptions = pIrp->Args.Create.CreateOptions;
    FILE_ATTRIBUTES FileAttributes =  pIrp->Args.Create.FileAttributes;
    PIO_CREDS pCreds = IoSecurityGetCredentials(pIrp->Args.Create.SecurityContext);
    PIO_SECURITY_CONTEXT_PROCESS_INFORMATION pProcessInfo =
        IoSecurityGetProcessInfo(pIrp->Args.Create.SecurityContext);
    PRDR_CCB2 pFile = NULL;

    BAIL_ON_NT_STATUS(status);

    status = LwIoAllocateMemory(
        sizeof(RDR_CCB2),
        (PVOID*)&pFile);
    BAIL_ON_NT_STATUS(status);

    status = LwErrnoToNtStatus(pthread_mutex_init(&pFile->mutex, NULL));
    BAIL_ON_NT_STATUS(status);

    pFile->bMutexInitialized = TRUE;
    pFile->version = SMB_PROTOCOL_VERSION_2;
    pFile->pTree = pTree;
    pTree = NULL;

    status = LwRtlWC16StringDuplicate(&pFile->pwszPath, pContext->State.Create.pwszFilename);
    BAIL_ON_NT_STATUS(status);

    status = LwRtlWC16StringDuplicate(&pFile->pwszCanonicalPath, pContext->State.Create.pwszCanonicalPath);
    BAIL_ON_NT_STATUS(status);

    pContext->Continue = RdrFinishCreate2;

    pContext->State.Create.pFile2 = pFile;

    status = RdrTransceiveCreate2(
        pContext,
        pFile,
        DesiredAccess,
        AllocationSize,
        FileAttributes,
        ShareAccess,
        CreateDisposition,
        CreateOptions);
    switch (status)
    {
    case STATUS_SUCCESS:
    case STATUS_PENDING:
        break;
    default:
        pContext->Continue = RdrCreateTreeConnectComplete;
        pContext->State.Create.pFile2 = NULL;

        status = RdrDfsConnect(
            pFile->pTree->pSession->pSocket,
            pIrp->Args.Create.FileName.FileName,
            pCreds,
            pProcessInfo->Uid,
            status,
            &pContext->usTry,
            &pContext->State.Create.pwszFilename,
            &pContext->State.Create.pwszCanonicalPath,
            pContext);

        RdrReleaseFile2(pFile);
        pFile = NULL;

    }
    BAIL_ON_NT_STATUS(status);

cleanup:

    RTL_FREE(&pContext->State.Create.pwszFilename);
    RTL_FREE(&pContext->State.Create.pwszCanonicalPath);

    if (status != STATUS_PENDING)
    {
        RdrFreeContext(pContext);
        pIrp->IoStatusBlock.Status = status;
        IoIrpComplete(pIrp);
    }

    return FALSE;

error:

    if (status != STATUS_PENDING && pFile)
    {
        RdrReleaseFile2(pFile);
    }

    if (status != STATUS_PENDING && pTree)
    {
        RdrTree2Release(pTree);
    }

    goto cleanup;
}
Пример #11
0
static
VOID
RdrNegotiateGssContextWorkItem2(
    PVOID pParam
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRDR_OP_CONTEXT pContext = pParam;
    PRDR_SESSION2 pSession = pContext->State.TreeConnect.pSession2;
    PRDR_SOCKET pSocket = pSession->pSocket;
    PSMB_PACKET pPacket = pContext->State.TreeConnect.pPacket;
    PBYTE pInBlob = NULL;
    DWORD dwInBlobLength = 0;
    PBYTE pOutBlob = NULL;
    DWORD dwOutBlobLength = 0;
    BOOLEAN bSessionLocked = FALSE;

    if (pPacket)
    {
        /* Capture session id */

        if (pSession->ullSessionId == 0)
        {
            pSession->ullSessionId = pPacket->pSMB2Header->ullSessionId;
        }
        else if (pSession->ullSessionId != pPacket->pSMB2Header->ullSessionId)
        {
            status = STATUS_INVALID_NETWORK_RESPONSE;
            BAIL_ON_NT_STATUS(status);
        }

        status = RdrSmb2DecodeSessionSetupResponse(
            pPacket,
            NULL,
            &pInBlob,
            &dwInBlobLength);
        BAIL_ON_NT_STATUS(status);
    }
    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 = RdrProcessSessionSetupResponse2;

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

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

        if (!pSocket->pSessionKey && pSession->pSessionKey)
        {
            status = LwIoAllocateMemory(
                pSession->dwSessionKeyLength,
                OUT_PPVOID(&pSocket->pSessionKey));
            BAIL_ON_NT_STATUS(status);

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

        status = RdrSocketAddSession2ById(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);

        RdrSessionSetupComplete2(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 (pSession)
        {
            RdrSession2Invalidate(pSession, status);
            RdrSession2Release(pSession);
        }

        RdrSessionSetupComplete2(pContext, status, NULL);
    }

    return;

error:

    goto cleanup;
}
Пример #12
0
BOOLEAN
RdrProcessNegotiateResponse2(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pContext->State.TreeConnect.pSocket;
    PSMB_PACKET pPacket = pParam;
    BOOLEAN bFreeContext = FALSE;
    BOOLEAN bSocketLocked = FALSE;
    PRDR_SMB2_NEGOTIATE_RESPONSE_HEADER pHeader = NULL;
    PBYTE pNegHint = NULL;
    ULONG ulNegHintLength = 0;

    BAIL_ON_NT_STATUS(status);

    status = pPacket->pSMB2Header->error;
    BAIL_ON_NT_STATUS(status);

    LWIO_LOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    status = RdrSmb2DecodeNegotiateResponse(
        pPacket,
        &pHeader,
        &pNegHint,
        &ulNegHintLength);
    BAIL_ON_NT_STATUS(status);

    pSocket->ulMaxTransactSize = pHeader->ulMaxTransactionSize;
    pSocket->ulMaxReadSize = pHeader->ulMaxReadSize;
    pSocket->ulMaxWriteSize = pHeader->ulMaxWriteSize;
    pSocket->capabilities = pHeader->ulCapabilities;
    pSocket->ucSecurityMode = pHeader->ucSecurityMode;

    pSocket->securityBlobLen = ulNegHintLength;

    status = LwIoAllocateMemory(
                    pSocket->securityBlobLen,
                    (PVOID *) &pSocket->pSecurityBlob);
    BAIL_ON_NT_STATUS(status);

    memcpy(pSocket->pSecurityBlob,
           pNegHint,
           pSocket->securityBlobLen);

    status = RdrSocketSetProtocol(pSocket, SMB_PROTOCOL_VERSION_2);
    BAIL_ON_NT_STATUS(status);

    pSocket->state = RDR_SOCKET_STATE_READY;

    RdrNotifyContextList(
        &pSocket->StateWaiters,
        bSocketLocked,
        &pSocket->mutex,
        STATUS_SUCCESS,
        pSocket);

    LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    RdrNegotiateComplete2(pContext, STATUS_SUCCESS, pSocket);
    status = STATUS_PENDING;
    BAIL_ON_NT_STATUS(status);

 cleanup:

    LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    if (status != STATUS_PENDING)
    {
        RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL);
        bFreeContext = TRUE;
    }

    if (bFreeContext)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    RdrFreePacket(pPacket);

    return FALSE;

error:

    if (status != STATUS_PENDING && pSocket)
    {
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);
        RdrSocketInvalidate(pSocket, status);
        RdrSocketRelease(pSocket);
    }

    goto cleanup;
}
Пример #13
0
static
BOOLEAN
RdrProcessNegotiateResponse(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pContext->State.TreeConnect.pSocket;
    PSMB_PACKET pPacket = pParam;
    BOOLEAN bSocketLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;
    PBYTE pGUID = NULL;
    PBYTE pSecurityBlob = NULL;
    DWORD securityBlobLen = 0;
    NEGOTIATE_RESPONSE_HEADER* pHeader = NULL;

    BAIL_ON_NT_STATUS(status);

    /* As a special case, it is possible to receive an SMB2 negotiate response
     * from an SMB1 negotiate request.
     */
    if (pPacket->protocolVer == SMB_PROTOCOL_VERSION_2)
    {
        /* Short-circuit to SMB2 code path in connect2.c */
        return RdrProcessNegotiateResponse2(pContext, status, pParam);
    }

    LWIO_LOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    status = pPacket->pSMBHeader->error;
    BAIL_ON_NT_STATUS(status);

    status = UnmarshallNegotiateResponse(
        pPacket->pParams,
        pPacket->bufferUsed - (pPacket->pParams - pPacket->pRawBuffer),
        &pHeader,
        &pGUID,
        &pSecurityBlob,
        &securityBlobLen);
    BAIL_ON_NT_STATUS(status);

    // byte order conversions
    SMB_LTOH16_INPLACE(pHeader->dialectIndex);
    SMB_LTOH8_INPLACE(pHeader->securityMode);
    SMB_LTOH16_INPLACE(pHeader->maxMpxCount);
    SMB_LTOH16_INPLACE(pHeader->maxNumberVcs);
    SMB_LTOH32_INPLACE(pHeader->maxBufferSize);
    SMB_LTOH32_INPLACE(pHeader->maxRawSize);
    SMB_LTOH32_INPLACE(pHeader->sessionKey);
    SMB_LTOH32_INPLACE(pHeader->capabilities);
    SMB_LTOH32_INPLACE(pHeader->systemTimeLow);
    SMB_LTOH32_INPLACE(pHeader->systemTimeHigh);
    SMB_LTOH16_INPLACE(pHeader->serverTimeZone);
    SMB_LTOH8_INPLACE(pHeader->encryptionKeyLength);
    SMB_LTOH16_INPLACE(pHeader->byteCount);

    pSocket->ulMaxTransactSize = pHeader->maxBufferSize;
    pSocket->maxRawSize = pHeader->maxRawSize;
    pSocket->sessionKey = pHeader->sessionKey;
    pSocket->capabilities = pHeader->capabilities;
    pSocket->ucSecurityMode = pHeader->securityMode;
    pSocket->usMaxSlots = pHeader->maxMpxCount;
    pSocket->securityBlobLen = securityBlobLen;

    status = LwIoAllocateMemory(
                    pSocket->securityBlobLen,
                    (PVOID *) &pSocket->pSecurityBlob);
    BAIL_ON_NT_STATUS(status);

    memcpy(pSocket->pSecurityBlob,
           pSecurityBlob,
           pSocket->securityBlobLen);

    status = RdrSocketSetProtocol(pSocket, SMB_PROTOCOL_VERSION_1);
    BAIL_ON_NT_STATUS(status);

    pSocket->state = RDR_SOCKET_STATE_READY;

    RdrNotifyContextList(
        &pSocket->StateWaiters,
        bSocketLocked,
        &pSocket->mutex,
        STATUS_SUCCESS,
        pSocket);

    LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    RdrNegotiateComplete(pContext, STATUS_SUCCESS, pSocket);
    status = STATUS_PENDING;
    BAIL_ON_NT_STATUS(status);

cleanup:

    LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    if (status != STATUS_PENDING)
    {
        RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL);
        bFreeContext = TRUE;
    }

    if (bFreeContext)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    RdrFreePacket(pPacket);

    return FALSE;

error:

    if (status != STATUS_PENDING)
    {
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);
        RdrSocketInvalidate(pSocket, status);
        RdrSocketRelease(pSocket);
    }

    goto cleanup;
}
Пример #14
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;
}
Пример #15
0
static
NTSTATUS
LwIoCreateDefaultKrb5Creds(
    PIO_CREDS* ppCreds
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    krb5_context pKrb5Context = NULL;
    krb5_error_code krb5Error = 0;
    krb5_ccache pKrb5Cache = NULL;
    krb5_principal pKrb5Principal = NULL;
    char* pszPrincipalName = NULL;
    const char* pszCredCachePath = NULL;
    PIO_CREDS pCreds = NULL;

    *ppCreds = NULL;

    krb5Error = krb5_init_context(&pKrb5Context);
    if (krb5Error)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        BAIL_ON_NT_STATUS(Status);
    }

    pszCredCachePath = krb5_cc_default_name(pKrb5Context);
    if (!pszCredCachePath)
    {
        /* If there is no default path, give up */
        goto cleanup;
    }

    krb5Error = krb5_cc_resolve(pKrb5Context, pszCredCachePath, &pKrb5Cache);
    if (krb5Error)
    {
        /* If we can't access the cache, give up */
        goto cleanup;
    }

    krb5Error = krb5_cc_get_principal(pKrb5Context, pKrb5Cache, &pKrb5Principal);
    if (krb5Error)
    {
        /* If there is no principal, give up */
        goto cleanup;
    }

    krb5Error = krb5_unparse_name(pKrb5Context, pKrb5Principal, &pszPrincipalName);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }
    
    Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds));
    BAIL_ON_NT_STATUS(Status);

    pCreds->type = IO_CREDS_TYPE_KRB5_CCACHE;

    Status = LwRtlWC16StringAllocateFromCString(
        &pCreds->payload.krb5Ccache.pwszPrincipal,
        pszPrincipalName
        );
    BAIL_ON_NT_STATUS(Status);
    
    Status = LwRtlWC16StringAllocateFromCString(
        &pCreds->payload.krb5Ccache.pwszCachePath,
        pszCredCachePath
        );
    BAIL_ON_NT_STATUS(Status);

    *ppCreds = pCreds;

cleanup:

    if (pszPrincipalName)
    {
        krb5_free_unparsed_name(pKrb5Context, pszPrincipalName);
    }
    if (pKrb5Principal)
    {
        krb5_free_principal(pKrb5Context, pKrb5Principal);
    }
    if (pKrb5Cache)
    {
        krb5_cc_close(pKrb5Context, pKrb5Cache);
    }
    if (pKrb5Context)
    {
        krb5_free_context(pKrb5Context);
    }

    return Status;

error:

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    goto cleanup;
}
Пример #16
0
DWORD
SMBGSSContextBuild(
    PCWSTR     pwszServerName,
    PIO_CREDS  pCreds,
    PHANDLE    phSMBGSSContext
    )
{
    DWORD dwError = 0;
    DWORD dwMajorStatus = 0;
    DWORD dwMinorStatus = 0;
    PSMB_GSS_SEC_CONTEXT pContext = NULL;
    PSTR pszTargetName = NULL;
    PSTR pszServerName = NULL;
    PSTR pszUsername = NULL;
    PSTR pszDomain = NULL;
    PSTR pszPassword = NULL;
    gss_buffer_desc usernameBuffer = {0};
    gss_buffer_desc inputNameBuffer = {0};
    gss_buffer_desc authDataBuffer = {0};
    gss_name_t pUsername = NULL;
    gss_OID_set_desc desiredMechs;
    gss_OID_set actualMechs;
    OM_uint32 timeRec = 0;
    SEC_WINNT_AUTH_IDENTITY authData;
    static gss_OID_desc gssCredOptionPasswordOidDesc =
    {
        .length = GSS_CRED_OPT_PW_LEN,
        .elements = GSS_CRED_OPT_PW
    };
    static gss_OID_desc gssNtlmOidDesc =
    {
        .length = GSS_MECH_NTLM_LEN,
        .elements = GSS_MECH_NTLM
    };
    size_t sCopyServerChars = 0;

    dwError = LwRtlCStringAllocateFromWC16String(&pszServerName, pwszServerName);
    BAIL_ON_LWIO_ERROR(dwError);
    
    LWIO_LOG_DEBUG("Build GSS Context for server [%s]", LWIO_SAFE_LOG_STRING(pszServerName));

    dwError = LwIoAllocateMemory(
        sizeof(SMB_GSS_SEC_CONTEXT),
        (PVOID*)&pContext);
    BAIL_ON_LWIO_ERROR(dwError);

    pContext->state = SMB_GSS_SEC_CONTEXT_STATE_INITIAL;
    
    if (pCreds)
    {
        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_CCACHE:
            dwError = STATUS_ACCESS_DENIED;
            BAIL_ON_LWIO_ERROR(dwError);
            break;
        case IO_CREDS_TYPE_KRB5_TGT:
            sCopyServerChars = strlen(pszServerName);
            if (sCopyServerChars > 0 &&
                    pszServerName[sCopyServerChars - 1] == '.')
            {
                // Strip the trailing dot
                sCopyServerChars --;
            }
            
            if (sCopyServerChars > INT_MAX)
            {
                dwError = STATUS_INTEGER_OVERFLOW;
                BAIL_ON_LWIO_ERROR(dwError);
            }

            dwError = SMBAllocateStringPrintf(
                            &pszTargetName,
                            "cifs/%.*s@",
                            (int)sCopyServerChars,
                            pszServerName);
            BAIL_ON_LWIO_ERROR(dwError);

            inputNameBuffer.value = pszTargetName;
            inputNameBuffer.length = strlen(pszTargetName) + 1;
            
            dwMajorStatus = gss_import_name(
                (OM_uint32 *)&dwMinorStatus,
                &inputNameBuffer,
                (gss_OID) gss_nt_krb5_name,
                &pContext->target_name);

            smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus);

            BAIL_ON_SEC_ERROR(dwMajorStatus);

            dwError = LwRtlCStringAllocateFromWC16String(
                &pszUsername,
                pCreds->payload.krb5Tgt.pwszClientPrincipal);
            BAIL_ON_NT_STATUS(dwError);

            usernameBuffer.value = pszUsername;
            usernameBuffer.length = strlen(pszUsername) + 1;

            dwMajorStatus = gss_import_name(
                (OM_uint32 *)&dwMinorStatus,
                &usernameBuffer,
                GSS_C_NT_USER_NAME,
                &pUsername);
            BAIL_ON_SEC_ERROR(dwMajorStatus);

            desiredMechs.count = 1;
            desiredMechs.elements = (gss_OID) gss_mech_krb5;

            dwMajorStatus = gss_acquire_cred(
                (OM_uint32 *)&dwMinorStatus,
                pUsername,
                0,
                &desiredMechs,
                GSS_C_INITIATE,
                &pContext->credHandle,
                &actualMechs,
                &timeRec);
            BAIL_ON_SEC_ERROR(dwMajorStatus);
            break;

        case IO_CREDS_TYPE_PLAIN:
            inputNameBuffer.value = (void*) "unset";
            inputNameBuffer.length = strlen("unset");
            
            dwMajorStatus = gss_import_name(
                (OM_uint32 *)&dwMinorStatus,
                &inputNameBuffer,
                (gss_OID) gss_nt_krb5_name,
                &pContext->target_name);

            smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus);
            
            BAIL_ON_SEC_ERROR(dwMajorStatus);
            
            if (pCreds->payload.plain.pwszUsername)
            {
                dwError = LwRtlCStringAllocateFromWC16String(&pszUsername, pCreds->payload.plain.pwszUsername);
                BAIL_ON_LWIO_ERROR(dwError);
                
                usernameBuffer.value = pszUsername;
                usernameBuffer.length = strlen(pszUsername);
                
                // If "" is passed in, that means to use anonymous
                // authentication. gss_import_name fails on "" though
                if (usernameBuffer.length)
                {
                    dwMajorStatus = gss_import_name(
                        (OM_uint32 *)&dwMinorStatus,
                        &usernameBuffer,
                        GSS_C_NT_USER_NAME,
                        &pUsername);
                    BAIL_ON_SEC_ERROR(dwMajorStatus);
                }
            }
            
            desiredMechs.count = 1;
            desiredMechs.elements = (gss_OID) &gssNtlmOidDesc;
            
            dwMajorStatus = gss_acquire_cred(
                (OM_uint32 *)&dwMinorStatus,
                pUsername,
                0,
                &desiredMechs,
                GSS_C_INITIATE,
                &pContext->credHandle,
                &actualMechs,
                &timeRec);
            BAIL_ON_SEC_ERROR(dwMajorStatus);

            if (pCreds->payload.plain.pwszUsername &&
                pCreds->payload.plain.pwszPassword &&
                pCreds->payload.plain.pwszDomain)
            {
                dwError = LwRtlCStringAllocateFromWC16String(&pszDomain, pCreds->payload.plain.pwszDomain);
                BAIL_ON_LWIO_ERROR(dwError);
                
                dwError = LwRtlCStringAllocateFromWC16String(&pszPassword, pCreds->payload.plain.pwszPassword);
                BAIL_ON_LWIO_ERROR(dwError);
                
                authData.User = pszUsername;
                authData.UserLength = strlen(pszUsername);
                authData.Domain = pszDomain;
                authData.DomainLength = strlen(pszDomain);
                authData.Password = pszPassword;
                authData.PasswordLength = strlen(pszPassword);
                authData.Flags = 0;
                
                authDataBuffer.value = &authData;
                authDataBuffer.length = sizeof(authData);
                
                dwMajorStatus = gssspi_set_cred_option(
                    (OM_uint32 *)&dwMinorStatus,
                    pContext->credHandle,
                    (gss_OID) &gssCredOptionPasswordOidDesc,
                    &authDataBuffer);
                BAIL_ON_SEC_ERROR(dwMajorStatus);
            }
            break;
        }
    }
    
    dwError = LwIoAllocateMemory(
        sizeof(CtxtHandle),
        (PVOID*)&pContext->pGSSContext);
    BAIL_ON_LWIO_ERROR(dwError);
    
    *pContext->pGSSContext = GSS_C_NO_CONTEXT;
    
    *phSMBGSSContext = (HANDLE)pContext;
    
cleanup:
    
    if (pUsername != NULL)
    {
        gss_release_name((OM_uint32 *)&dwMinorStatus, &pUsername);
    }

    LWIO_SAFE_FREE_STRING(pszTargetName);
    LWIO_SAFE_FREE_STRING(pszServerName);
    LWIO_SAFE_FREE_STRING(pszUsername);
    LWIO_SAFE_FREE_STRING(pszDomain);
    LWIO_SAFE_FREE_STRING(pszPassword);
    
    return dwError;
    
sec_error:
    
    dwError = LWIO_ERROR_GSS;

error:

    *phSMBGSSContext = NULL;

    if (pContext)
    {
        SMBGSSContextFree(pContext);
    }

    goto cleanup;
}
Пример #17
0
DWORD
SMBGSSContextNegotiate(
    HANDLE hSMBGSSContext,
    PBYTE  pSecurityInputBlob,
    DWORD  dwSecurityInputBlobLen,
    PBYTE* ppSecurityBlob,
    PDWORD pdwSecurityBlobLength
    )
{
    DWORD dwError = 0;
    DWORD dwMajorStatus = 0;
    DWORD dwMinorStatus = 0;
    PSMB_GSS_SEC_CONTEXT pContext = (PSMB_GSS_SEC_CONTEXT)hSMBGSSContext;
    gss_buffer_desc input_desc = {0};
    gss_buffer_desc output_desc = {0};
    DWORD ret_flags = 0;
    PBYTE pSecurityBlob = NULL;
    DWORD dwSecurityBlobLength = 0;

    static gss_OID_desc gss_spnego_mech_oid_desc =
      {6, (void *)"\x2b\x06\x01\x05\x05\x02"};

    if (pContext->state == SMB_GSS_SEC_CONTEXT_STATE_COMPLETE)
    {
        goto cleanup;
    }

    input_desc.value = pSecurityInputBlob;
    input_desc.length = dwSecurityInputBlobLen;

    dwMajorStatus = gss_init_sec_context(
                        (OM_uint32 *)&dwMinorStatus,
                        pContext->credHandle,
                        pContext->pGSSContext,
                        pContext->target_name,
                        &gss_spnego_mech_oid_desc,
                        GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG |
                        GSS_C_CONF_FLAG |
                        GSS_C_INTEG_FLAG,
                        0,
                        NULL,
                        &input_desc,
                        NULL,
                        &output_desc,
                        &ret_flags,
                        NULL);

    smb_display_status("gss_init_sec_context", dwMajorStatus, dwMinorStatus);

    switch (dwMajorStatus)
    {
        case GSS_S_CONTINUE_NEEDED:

            pContext->state = SMB_GSS_SEC_CONTEXT_STATE_NEGOTIATE;

            break;

        case GSS_S_COMPLETE:

            pContext->state = SMB_GSS_SEC_CONTEXT_STATE_COMPLETE;

            break;

        case GSS_S_FAILURE:
            switch (dwMinorStatus)
            {
                case ((DWORD) KRB5KRB_AP_ERR_SKEW):
                    dwError = LWIO_ERROR_CLOCK_SKEW;
                    break;
                case ((DWORD) KRB5KDC_ERR_TGT_REVOKED):
                    dwError = LW_STATUS_KDC_CERT_REVOKED;
                    break;
                case ((DWORD) KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN):
                    dwError = STATUS_ACCESS_DENIED;
                    break;
                default:
                    dwError = LWIO_ERROR_GSS;
            }
            BAIL_ON_LWIO_ERROR(dwError);
            break;

        default:

            dwError = LWIO_ERROR_GSS;
            BAIL_ON_LWIO_ERROR(dwError);

            break;
    }

    if (output_desc.length)
    {
        dwError = LwIoAllocateMemory(
                        output_desc.length,
                        (PVOID*)&pSecurityBlob);
        BAIL_ON_LWIO_ERROR(dwError);

        memcpy(pSecurityBlob, output_desc.value, output_desc.length);

        dwSecurityBlobLength = output_desc.length;
    }

    *ppSecurityBlob = pSecurityBlob;
    *pdwSecurityBlobLength = dwSecurityBlobLength;

cleanup:

    gss_release_buffer(&dwMinorStatus, &output_desc);

    return dwError;

error:

    *ppSecurityBlob = NULL;
    *pdwSecurityBlobLength = 0;

    LWIO_SAFE_FREE_MEMORY(pSecurityBlob);

    goto cleanup;
}
Пример #18
0
static
NTSTATUS
LwIoCredentialCacheToTgt(
    PIO_CREDS pCacheToken,
    PIO_CREDS* ppCreds
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    krb5_context pContext = NULL;
    krb5_error_code krb5Error = 0;
    krb5_ccache pCache = NULL;
    PSTR pszClientPrincipalName = NULL;
    PSTR pszServerPrincipalName = NULL;
    PSTR pszDesiredPrincipal = NULL;
    PSTR pszCredCachePath = NULL;
    PIO_CREDS pCreds = NULL;
    BOOLEAN bFoundTgt = FALSE;
    BOOLEAN bStartSeq = FALSE;
    krb5_creds creds;
    krb5_cc_cursor cursor;

    Status = LwRtlCStringAllocateFromWC16String(
                 &pszDesiredPrincipal,
                 pCacheToken->payload.krb5Ccache.pwszPrincipal);
    BAIL_ON_NT_STATUS(Status);

    Status = LwRtlCStringAllocateFromWC16String(
                 &pszCredCachePath,
                 pCacheToken->payload.krb5Ccache.pwszCachePath);
    BAIL_ON_NT_STATUS(Status);

    /* Open credentials cache */
    krb5Error = krb5_init_context(&pContext);
    if (krb5Error)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        BAIL_ON_NT_STATUS(Status);
    }

    krb5Error = krb5_cc_resolve(pContext, pszCredCachePath, &pCache);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Look for a TGT */
    krb5Error = krb5_cc_start_seq_get(pContext, pCache, &cursor);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    bStartSeq = TRUE;

    while ((krb5Error = krb5_cc_next_cred(pContext, pCache, &cursor, &creds)) == 0)
    {
        /* Look tickets with the intial flag set */
        if (creds.ticket_flags & TKT_FLG_INITIAL)
        {
            /* Extract and compare client principal with desired principal */
            krb5Error = krb5_unparse_name(pContext, creds.client, &pszClientPrincipalName);
            if (krb5Error)
            {
                Status = STATUS_UNSUCCESSFUL;
                BAIL_ON_NT_STATUS(Status);
            }
            if (!strcmp(pszClientPrincipalName, pszDesiredPrincipal))
            {
                bFoundTgt = TRUE;
                break;
            }

            krb5_free_unparsed_name(pContext, pszClientPrincipalName);
            pszClientPrincipalName = NULL;
        }

        krb5_free_cred_contents(pContext, &creds);
    }

    if (!bFoundTgt)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Extract server principal name */
    krb5Error = krb5_unparse_name(pContext, creds.server, &pszServerPrincipalName);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Construct token from krb5 credential data */
    Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds));
    BAIL_ON_NT_STATUS(Status);

    pCreds->type = IO_CREDS_TYPE_KRB5_TGT;

    /* Copy principal names */
    Status = LwRtlWC16StringAllocateFromCString(
                 &pCreds->payload.krb5Tgt.pwszClientPrincipal,
                 pszClientPrincipalName);
    BAIL_ON_NT_STATUS(Status);

    Status = LwRtlWC16StringAllocateFromCString(
                 &pCreds->payload.krb5Tgt.pwszServerPrincipal,
                 pszServerPrincipalName);
    BAIL_ON_NT_STATUS(Status);

    /* Set time fields */
    pCreds->payload.krb5Tgt.authTime = creds.times.authtime;
    pCreds->payload.krb5Tgt.startTime = creds.times.starttime;
    pCreds->payload.krb5Tgt.endTime = creds.times.endtime;
    pCreds->payload.krb5Tgt.renewTillTime = creds.times.renew_till;

    /* Copy encryption key */
    pCreds->payload.krb5Tgt.keyType = creds.keyblock.enctype;
    pCreds->payload.krb5Tgt.ulKeySize = creds.keyblock.length;
    Status = LwIoAllocateMemory(
                 creds.keyblock.length,
                 OUT_PPVOID(&pCreds->payload.krb5Tgt.pKeyData));
    BAIL_ON_NT_STATUS(Status);
    memcpy(
        pCreds->payload.krb5Tgt.pKeyData,
        creds.keyblock.contents,
        creds.keyblock.length);

    /* Copy tgt */
    pCreds->payload.krb5Tgt.tgtFlags = creds.ticket_flags;
    pCreds->payload.krb5Tgt.ulTgtSize = creds.ticket.length;
    Status = LwIoAllocateMemory(
                 creds.ticket.length,
                 OUT_PPVOID(&pCreds->payload.krb5Tgt.pTgtData));
    BAIL_ON_NT_STATUS(Status);
    memcpy(
        pCreds->payload.krb5Tgt.pTgtData,
        creds.ticket.data,
        creds.ticket.length);

    *ppCreds = pCreds;

cleanup:

    LWIO_SAFE_FREE_MEMORY(pszDesiredPrincipal);
    LWIO_SAFE_FREE_MEMORY(pszCredCachePath);

    if (pszClientPrincipalName)
    {
        krb5_free_unparsed_name(pContext, pszClientPrincipalName);
    }

    if (pszServerPrincipalName)
    {
        krb5_free_unparsed_name(pContext, pszServerPrincipalName);
    }

    if (bFoundTgt)
    {
        krb5_free_cred_contents(pContext, &creds);
    }

    if (bStartSeq)
    {
        krb5_cc_end_seq_get(pContext, pCache, &cursor);
    }

    if (pCache)
    {
        krb5_cc_close(pContext, pCache);
    }

    if (pContext)
    {
        krb5_free_context(pContext);
    }

    return Status;

error:

    *ppCreds = NULL;

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    goto cleanup;
}
Пример #19
0
NTSTATUS
LwIoCopyCreds(
    PIO_CREDS pCreds,
    PIO_CREDS* ppCredsCopy
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_CREDS pCredsCopy = NULL;

    if (pCreds)
    {
        Status = LwIoAllocateMemory(sizeof(*pCredsCopy), OUT_PPVOID(&pCredsCopy));
        BAIL_ON_NT_STATUS(Status);

        pCredsCopy->type = pCreds->type;

        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_PLAIN:
            Status = RtlWC16StringDuplicate(
                         &pCredsCopy->payload.plain.pwszUsername,
                         pCreds->payload.plain.pwszUsername);
            BAIL_ON_NT_STATUS(Status);
            Status = RtlWC16StringDuplicate(
                         &pCredsCopy->payload.plain.pwszDomain,
                         pCreds->payload.plain.pwszDomain);
            BAIL_ON_NT_STATUS(Status);
            Status = RtlWC16StringDuplicate(
                         &pCredsCopy->payload.plain.pwszPassword,
                         pCreds->payload.plain.pwszPassword);
            BAIL_ON_NT_STATUS(Status);
            break;
        case IO_CREDS_TYPE_KRB5_CCACHE:
            Status = RtlWC16StringDuplicate(
                         &pCredsCopy->payload.krb5Ccache.pwszPrincipal,
                         pCreds->payload.krb5Ccache.pwszPrincipal);
            BAIL_ON_NT_STATUS(Status);
            Status = RtlWC16StringDuplicate(
                         &pCredsCopy->payload.krb5Ccache.pwszCachePath,
                         pCreds->payload.krb5Ccache.pwszCachePath);
            BAIL_ON_NT_STATUS(Status);
            break;
        case IO_CREDS_TYPE_KRB5_TGT:
            Status = RtlWC16StringDuplicate(
                         &pCredsCopy->payload.krb5Tgt.pwszClientPrincipal,
                         pCreds->payload.krb5Tgt.pwszClientPrincipal);
            BAIL_ON_NT_STATUS(Status);
            Status = RtlWC16StringDuplicate(
                         &pCredsCopy->payload.krb5Tgt.pwszServerPrincipal,
                         pCreds->payload.krb5Tgt.pwszServerPrincipal);
            BAIL_ON_NT_STATUS(Status);
            pCredsCopy->payload.krb5Tgt.authTime = pCreds->payload.krb5Tgt.authTime;
            pCredsCopy->payload.krb5Tgt.startTime = pCreds->payload.krb5Tgt.startTime;
            pCredsCopy->payload.krb5Tgt.endTime = pCreds->payload.krb5Tgt.endTime;
            pCredsCopy->payload.krb5Tgt.renewTillTime = pCreds->payload.krb5Tgt.renewTillTime;
            pCredsCopy->payload.krb5Tgt.keyType = pCreds->payload.krb5Tgt.keyType;
            pCredsCopy->payload.krb5Tgt.ulKeySize = pCreds->payload.krb5Tgt.ulKeySize;
            Status = LwIoAllocateMemory(
                         pCreds->payload.krb5Tgt.ulKeySize,
                         OUT_PPVOID(&pCredsCopy->payload.krb5Tgt.pKeyData));
            BAIL_ON_NT_STATUS(Status);
            memcpy(
                pCredsCopy->payload.krb5Tgt.pKeyData,
                pCreds->payload.krb5Tgt.pKeyData,
                pCreds->payload.krb5Tgt.ulKeySize);
            pCredsCopy->payload.krb5Tgt.tgtFlags = pCreds->payload.krb5Tgt.tgtFlags;
            pCredsCopy->payload.krb5Tgt.ulTgtSize = pCreds->payload.krb5Tgt.ulTgtSize;
            Status = LwIoAllocateMemory(
                         pCreds->payload.krb5Tgt.ulTgtSize,
                         OUT_PPVOID(&pCredsCopy->payload.krb5Tgt.pTgtData));
            BAIL_ON_NT_STATUS(Status);
            memcpy(
                pCredsCopy->payload.krb5Tgt.pTgtData,
                pCreds->payload.krb5Tgt.pTgtData,
                pCreds->payload.krb5Tgt.ulTgtSize);
            break;
        }

        *ppCredsCopy = pCredsCopy;
    }
    else
    {
        *ppCredsCopy = NULL;
    }

cleanup:

    return Status;

error:

    if (pCredsCopy)
    {
        LwIoDeleteCreds(pCredsCopy);
    }

    goto cleanup;
}
Пример #20
0
static
NTSTATUS
SMBPacketBufferAllocatePooled(
    IN  PLWIO_PACKET_ALLOCATOR pPacketAllocator,
    IN  size_t                 len,
    OUT uint8_t**              ppBuffer,
    OUT size_t*                pAllocatedLen
    )
{
    NTSTATUS ntStatus = 0;
    uint8_t* pBuffer = NULL;
    size_t   allocatedLen  = 0;
    BOOLEAN bInLock = FALSE;

    LWIO_LOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

    /* If the len is greater than our current allocator len, adjust */
    if (len > pPacketAllocator->freeBufferLen)
    {
        SMBStackFree(pPacketAllocator->pFreeBufferStack);

        pPacketAllocator->pFreeBufferStack = NULL;
        pPacketAllocator->freeBufferLen = len;
    }

    if (pPacketAllocator->pFreeBufferStack)
    {
        pBuffer = (uint8_t *) pPacketAllocator->pFreeBufferStack;
        allocatedLen = pPacketAllocator->freeBufferLen;

        SMBStackPopNoFree(&pPacketAllocator->pFreeBufferStack);

        pPacketAllocator->freeBufferCount--;

        LWIO_UNLOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

        memset(pBuffer, 0, allocatedLen);
    }
    else
    {
        allocatedLen = pPacketAllocator->freeBufferLen;

        LWIO_UNLOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

        ntStatus = LwIoAllocateMemory(allocatedLen, (PVOID *) &pBuffer);
        BAIL_ON_NT_STATUS(ntStatus);
    }

    *ppBuffer = pBuffer;
    *pAllocatedLen = allocatedLen;

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pPacketAllocator->mutex);

    return ntStatus;

error:

    *ppBuffer = NULL;
    *pAllocatedLen = 0;

    goto cleanup;
}
Пример #21
0
NTSTATUS
RdrTree2Create(
    PRDR_TREE2* ppTree
    )
{
    NTSTATUS status = 0;
    PRDR_TREE2 pTree = NULL;
    BOOLEAN bDestroyMutex = FALSE;
    pthread_mutexattr_t mutexAttr;
    pthread_mutexattr_t* pMutexAttr = NULL;

    status = LwIoAllocateMemory(
                sizeof(RDR_TREE2),
                (PVOID*)&pTree);
    BAIL_ON_NT_STATUS(status);

    LwListInit(&pTree->StateWaiters);

    status = pthread_mutexattr_init(&mutexAttr);
    BAIL_ON_NT_STATUS(status);

    pMutexAttr = &mutexAttr;

    status = pthread_mutexattr_settype(pMutexAttr, PTHREAD_MUTEX_RECURSIVE);
    BAIL_ON_NT_STATUS(status);

    pthread_mutex_init(&pTree->mutex, pMutexAttr);
    bDestroyMutex = TRUE;

    /* Pre-allocate resources to send a tree disconnect */
    status = RdrCreateContext(NULL, &pTree->pDisconnectContext);
    BAIL_ON_NT_STATUS(status);

    status = RdrAllocateContextPacket(pTree->pDisconnectContext, RDR_SMB2_STUB_SIZE);
    BAIL_ON_NT_STATUS(status);

    pTree->refCount = 1;
    pTree->pSession = NULL;
    pTree->ulTid = 0;
    pTree->pwszPath = NULL;
    pTree->version = SMB_PROTOCOL_VERSION_2;

    *ppTree = pTree;

cleanup:

    if (pMutexAttr)
    {
        pthread_mutexattr_destroy(pMutexAttr);
    }

    return status;

error:

    if (bDestroyMutex)
    {
        pthread_mutex_destroy(&pTree->mutex);
    }

    if (pTree)
    {
        RdrTree2DestroyContents(pTree);
    }
    LWIO_SAFE_FREE_MEMORY(pTree);

    *ppTree = NULL;

    goto cleanup;
}