예제 #1
0
파일: driver.c 프로젝트: virtual-void/pbis
VOID
RdrNotifyContextList(
    PLW_LIST_LINKS pList,
    BOOLEAN bLocked,
    pthread_mutex_t* pMutex,
    NTSTATUS status,
    PVOID pParam
    )
{
    LW_LIST_LINKS List;
    PLW_LIST_LINKS pLink = NULL;
    BOOLEAN bWasLocked = bLocked;

    LWIO_LOCK_MUTEX(bLocked, pMutex);

    LwListInit(&List);

    while ((pLink = LwListRemoveHead(pList)))
    {
        LwListInsertTail(&List, pLink);
    }

    LWIO_UNLOCK_MUTEX(bLocked, pMutex);
    RdrContinueContextList(&List, status, pParam);
    LWIO_LOCK_MUTEX(bLocked, pMutex);

    while ((pLink = LwListRemoveHead(&List)))
    {
        LwListInsertTail(pList, pLink);
    }

    if (!bWasLocked)
    {
        LWIO_UNLOCK_MUTEX(bLocked, pMutex);
    }
}
예제 #2
0
VOID
SrvCancelChangeNotify_SMB_V2(
    PLWIO_ASYNC_STATE pAsyncState
    )
{
    BOOLEAN bInLock = FALSE;
    PSRV_NOTIFY_STATE_SMB_V2 pNotifyState =
                        (PSRV_NOTIFY_STATE_SMB_V2)pAsyncState->hAsyncState;

    LWIO_LOCK_MUTEX(bInLock, &pNotifyState->mutex);

    SrvCancelNotifyState_SMB_V2_inlock(pNotifyState);

    LWIO_UNLOCK_MUTEX(bInLock, &pNotifyState->mutex);
}
예제 #3
0
VOID
SrvNotifyStateCancel(
    HANDLE hNotifyState
    )
{
    BOOLEAN bInLock = FALSE;
    PSRV_CHANGE_NOTIFY_STATE_SMB_V1 pNotifyState =
            (PSRV_CHANGE_NOTIFY_STATE_SMB_V1)hNotifyState;

    LWIO_LOCK_MUTEX(bInLock, &pNotifyState->mutex);

    SrvNotifyStateCancel_inlock(pNotifyState);

    LWIO_UNLOCK_MUTEX(bInLock, &pNotifyState->mutex);
}
예제 #4
0
NTSTATUS
PvfsZctCompleteRead(
    IN PPVFS_IRP_CONTEXT pIrpContext
    )
{
    PPVFS_ZCT_CONTEXT pZctContext = (PPVFS_ZCT_CONTEXT) pIrpContext->pIrp->Args.ReadWrite.ZctCompletionContext;
    PPVFS_CCB pCcb = pZctContext->pCcb;
    BOOLEAN bMutexLocked = FALSE;

    LWIO_LOCK_MUTEX(bMutexLocked, &pCcb->FileMutex);
    PvfsFreeZctContext(&pZctContext);
    LWIO_UNLOCK_MUTEX(bMutexLocked, &pCcb->FileMutex);

    return STATUS_SUCCESS;
}
예제 #5
0
BOOLEAN
PvfsIrpContextCheckFlag(
    PPVFS_IRP_CONTEXT pIrpContext,
    USHORT BitToCheck
    )
{
    BOOLEAN bLocked = FALSE;
    BOOLEAN bIsSet = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pIrpContext->Mutex);
    bIsSet = IsSetFlag(pIrpContext->Flags, BitToCheck);
    LWIO_UNLOCK_MUTEX(bLocked, &pIrpContext->Mutex);

    return bIsSet;
}
예제 #6
0
static
VOID
SrvCancelNotifyState_SMB_V2(
    HANDLE hNotifyState
    )
{
    BOOLEAN bInLock = FALSE;
    PSRV_NOTIFY_STATE_SMB_V2 pNotifyState =
                        (PSRV_NOTIFY_STATE_SMB_V2)hNotifyState;

    LWIO_LOCK_MUTEX(bInLock, &pNotifyState->mutex);

    SrvCancelNotifyState_SMB_V2_inlock(pNotifyState);

    LWIO_UNLOCK_MUTEX(bInLock, &pNotifyState->mutex);
}
예제 #7
0
파일: driver.c 프로젝트: virtual-void/pbis
VOID
RdrSwapDomainHints(
    PLW_HASHMAP* ppMap
    )
{
    PLW_HASHMAP pExisting = NULL;
    BOOLEAN bLocked = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &gRdrRuntime.Lock);

    pExisting = gRdrRuntime.pDomainHints;
    gRdrRuntime.pDomainHints = *ppMap;

    LWIO_UNLOCK_MUTEX(bLocked, &gRdrRuntime.Lock);

    *ppMap = pExisting;
}
예제 #8
0
NTSTATUS
SrvElementsGetBootTime(
    PULONG64 pullBootTime
    )
{
    LONG64   llBootTime = 0LL;
    BOOLEAN  bInLock    = FALSE;

    LWIO_LOCK_MUTEX(bInLock, &gSrvElements.mutex);

    llBootTime = gSrvElements.llBootTime;

    LWIO_UNLOCK_MUTEX(bInLock, &gSrvElements.mutex);

    *pullBootTime = llBootTime;

    return STATUS_SUCCESS;
}
예제 #9
0
LW_NTSTATUS
LwIoGetActiveCreds(
    IN OPTIONAL LW_PUNICODE_STRING PathPrefix,
    OUT LW_PIO_CREDS* ppToken
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_PATH_CREDS pPathCreds = NULL;
    PIO_CREDS pCreds = NULL;
    BOOL bInLock = FALSE;

    Status = LwIoGetThreadCreds(&pCreds);
    BAIL_ON_NT_STATUS(Status);

    if (!pCreds && PathPrefix)
    {
        LWIO_LOCK_MUTEX(bInLock, &gLock);

        Status = LwIoFindPathCreds(PathPrefix, FALSE, &pPathCreds);
        BAIL_ON_NT_STATUS(Status);

        if (pPathCreds)
        {
            Status = LwIoCopyCreds(pPathCreds->pCreds, &pCreds);
            BAIL_ON_NT_STATUS(Status);
        }
    }

    if (!pCreds && gpProcessCreds)
    {
        Status = LwIoCopyCreds(gpProcessCreds, &pCreds);
        BAIL_ON_NT_STATUS(Status);
    }

    *ppToken = pCreds;

error:

    LWIO_UNLOCK_MUTEX(bInLock, &gLock);

    return Status;
}
예제 #10
0
static
VOID
PvfsNotifyFullReportBuffer(
    PPVFS_FCB pFcb,
    PPVFS_FCB pReportParentFcb,
    PPVFS_NOTIFY_REPORT_RECORD pReport
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bLocked = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    for (pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, NULL);
         pFilterLink;
         pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, pFilterLink))
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        /* Match the filter and depth */

        if ((pFilter->NotifyFilter & pReport->Filter) &&
            ((pFcb == pReportParentFcb) || pFilter->bWatchTree))
        {
            ntError = PvfsNotifyReportBuffer(
                          &pFilter->Buffer,
                          pReport->Action,
                          pReport->pszFilename);
            break;
        }
    }

    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    return;
}
예제 #11
0
NTSTATUS
SrvFinderGetSearchSpace(
    IN  HANDLE  hFinderRepository,
    IN  USHORT  usSearchId,
    OUT PHANDLE phFinder
    )
{
    NTSTATUS ntStatus = 0;
    PSRV_FINDER_REPOSITORY pFinderRepository = NULL;
    PSRV_SEARCH_SPACE pSearchSpace = NULL;
    BOOLEAN bInLock = FALSE;

    pFinderRepository = (PSRV_FINDER_REPOSITORY)hFinderRepository;

    LWIO_LOCK_MUTEX(bInLock, &pFinderRepository->mutex);

    ntStatus = LwRtlRBTreeFind(
                    pFinderRepository->pSearchSpaceCollection,
                    &usSearchId,
                    (PVOID*)&pSearchSpace);
    BAIL_ON_NT_STATUS(ntStatus);

    InterlockedIncrement(&pSearchSpace->refCount);

    *phFinder = pSearchSpace;

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pFinderRepository->mutex);

    return ntStatus;

error:

    *phFinder = NULL;

    goto cleanup;
}
예제 #12
0
static
VOID
SrvExecuteRenameAsyncCB(
    PVOID pContext
    )
{
    NTSTATUS                   ntStatus         = STATUS_SUCCESS;
    PSRV_EXEC_CONTEXT          pExecContext     = (PSRV_EXEC_CONTEXT)pContext;
    PSRV_PROTOCOL_EXEC_CONTEXT pProtocolContext = pExecContext->pProtocolContext;
    PSRV_RENAME_STATE_SMB_V1   pRenameState     = NULL;
    BOOLEAN                    bInLock          = FALSE;

    pRenameState =
            (PSRV_RENAME_STATE_SMB_V1)pProtocolContext->pSmb1Context->hState;

    LWIO_LOCK_MUTEX(bInLock, &pRenameState->mutex);

    if (pRenameState->pAcb->AsyncCancelContext)
    {
        IoDereferenceAsyncCancelContext(
                &pRenameState->pAcb->AsyncCancelContext);
    }

    pRenameState->pAcb = NULL;

    LWIO_UNLOCK_MUTEX(bInLock, &pRenameState->mutex);

    ntStatus = SrvProdConsEnqueue(gProtocolGlobals_SMB_V1.pWorkQueue, pContext);
    if (ntStatus != STATUS_SUCCESS)
    {
        LWIO_LOG_ERROR("Failed to enqueue execution context [status:0x%x]",
                       ntStatus);

        SrvReleaseExecContext(pExecContext);
    }
}
예제 #13
0
VOID
SrvShareDbReleaseContext(
    PSRV_SHARE_DB_CONTEXT pDbContext
    )
{
    BOOLEAN bInLock = FALSE;
    PSRV_SHARE_DB_GLOBALS pGlobals = &gShareRepository_lwshare;

    LWIO_LOCK_MUTEX(bInLock, &pGlobals->mutex);

    if (pGlobals->ulNumDbContexts < pGlobals->ulMaxNumDbContexts)
    {
        SrvShareDbFreeContext(pDbContext);
    }
    else
    {
        pDbContext->pNext = pGlobals->pDbContextList;
        pGlobals->pDbContextList = pDbContext;

        pGlobals->ulNumDbContexts++;
    }

    LWIO_UNLOCK_MUTEX(bInLock, &pGlobals->mutex);
}
예제 #14
0
파일: connect2.c 프로젝트: borland667/pbis
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;
}
예제 #15
0
파일: connect2.c 프로젝트: borland667/pbis
static
BOOLEAN
RdrSessionSetupComplete2(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SESSION2 pSession = pParam;
    PRDR_TREE2 pTree = NULL;
    BOOLEAN bTreeLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;

    BAIL_ON_NT_STATUS(status);

    status = RdrTree2FindOrCreate(
        &pSession,
        pContext->State.TreeConnect.pwszSharename,
        &pTree);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pTree2 = pTree;

    LWIO_LOCK_MUTEX(bTreeLocked, &pTree->mutex);

    switch (pTree->state)
    {
    case RDR_TREE_STATE_NOT_READY:
        pTree->state = RDR_TREE_STATE_INITIALIZING;

        pContext->Continue = RdrFinishTreeConnect2;

        status = RdrTransceiveTreeConnect2(pContext, pTree, pTree->pwszPath);
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_TREE_STATE_INITIALIZING:
        pContext->Continue = RdrTreeConnect2Complete;
        LwListInsertTail(&pTree->StateWaiters, &pContext->Link);
        bFreeContext = TRUE;
        status = STATUS_PENDING;
        break;
    case RDR_TREE_STATE_READY:
        RdrTreeConnect2Complete(pContext, status, pTree);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_TREE_STATE_ERROR:
        status = pTree->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

 cleanup:

    LWIO_UNLOCK_MUTEX(bTreeLocked, &pTree->mutex);

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

    if (bFreeContext)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return FALSE;

 error:

    if (status != STATUS_PENDING && pTree)
    {
        LWIO_UNLOCK_MUTEX(bTreeLocked, &pTree->mutex);
        RdrTree2Invalidate(pTree, status);
        RdrTree2Release(pTree);
    }

    if (status != STATUS_PENDING && pSession)
    {
        RdrSession2Release(pSession);
    }

    goto cleanup;
}
예제 #16
0
파일: connect2.c 프로젝트: borland667/pbis
static
NTSTATUS
RdrTree2FindOrCreate(
    IN OUT PRDR_SESSION2* ppSession,
    IN PCWSTR pwszPath,
    OUT PRDR_TREE2* ppTree
    )
{
    NTSTATUS  ntStatus = 0;
    PRDR_TREE2 pTree = NULL;
    BOOLEAN   bInLock = FALSE;
    PRDR_SESSION2 pSession = *ppSession;

    LWIO_LOCK_MUTEX(bInLock, &pSession->mutex);

    ntStatus = SMBHashGetValue(
                pSession->pTreeHashByPath,
                pwszPath,
                (PVOID *) &pTree);

    if (!ntStatus)
    {
        pTree->refCount++;
        RdrTree2Revive(pTree);
        RdrSession2Release(pSession);
        *ppSession = NULL;
    }
    else
    {
        ntStatus = RdrTree2Create(&pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        pTree->pSession = pSession;

        ntStatus = RtlWC16StringDuplicate(
            &pTree->pwszPath,
            pwszPath);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SMBHashSetValue(
            pSession->pTreeHashByPath,
            pTree->pwszPath,
            pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        pTree->bParentLink = TRUE;

        *ppSession = NULL;
    }

    LWIO_UNLOCK_MUTEX(bInLock, &pSession->mutex);

    *ppTree = pTree;

cleanup:

    return ntStatus;

error:

    LWIO_UNLOCK_MUTEX(bInLock, &pSession->mutex);

    *ppTree = NULL;

    if (pTree)
    {
        RdrTree2Release(pTree);
    }

    goto cleanup;
}
예제 #17
0
파일: connect2.c 프로젝트: borland667/pbis
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;
}
예제 #18
0
파일: connect2.c 프로젝트: borland667/pbis
static
BOOLEAN
RdrProcessSessionSetupResponse2(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SESSION2 pSession = pContext->State.TreeConnect.pSession2;
    PSMB_PACKET pPacket = pParam;
    BOOLEAN bSessionLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;

    BAIL_ON_NT_STATUS(status);

    LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

    if (pPacket)
    {
        status = pPacket->pSMB2Header->error;
        if (status == STATUS_MORE_PROCESSING_REQUIRED)
        {
            status = STATUS_SUCCESS;
        }
        BAIL_ON_NT_STATUS(status);

        pSession->ullSessionId = pPacket->pSMB2Header->ullSessionId;
    }

    /* Save the packet on the context for RdrNegotiateGssContextWorkItem2 */
    pContext->State.TreeConnect.pPacket = pPacket;
    pPacket = NULL;

    /* Dispatch a work item to negotiate the GSS context in a separate thread.
       Because GSS-API could potentially block in a network call (KRB5)
       or an IPC call (NTLM), calling into it directly from the socket task
       could cause a deadlock. */
    status = LwRtlQueueWorkItem(
        gRdrRuntime.pThreadPool,
        RdrNegotiateGssContextWorkItem2,
        pContext,
        0);
    BAIL_ON_NT_STATUS(status);

    status = STATUS_PENDING;
    BAIL_ON_NT_STATUS(status);

cleanup:

    LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->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 && pSession)
    {
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrSession2Invalidate(pSession, status);
        RdrSession2Release(pSession);
    }

    goto cleanup;
}
예제 #19
0
파일: connect2.c 프로젝트: borland667/pbis
BOOLEAN
RdrNegotiateComplete2(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pParam;
    PRDR_SESSION2 pSession = NULL;
    BOOLEAN bSessionLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;
    PIO_CREDS pCreds = pContext->State.TreeConnect.pCreds;

    BAIL_ON_NT_STATUS(status);

    if (pContext->State.TreeConnect.bStopOnDfs &&
        pSocket->capabilities & RDR_SMB2_CAP_DFS)
    {
        status = STATUS_DFS_EXIT_PATH_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    status = RdrSession2FindOrCreate(
        &pSocket,
        pContext->State.TreeConnect.pCreds,
        pContext->State.TreeConnect.Uid,
        &pSession);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSession2 = pSession;

    LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

    switch (pSession->state)
    {
    case RDR_SESSION_STATE_NOT_READY:
        pSession->state = RDR_SESSION_STATE_INITIALIZING;

        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_TGT:
            status = SMBCredTokenToKrb5CredCache(
                pCreds,
                &pContext->State.TreeConnect.pszCachePath);
            BAIL_ON_NT_STATUS(status);
            break;
        case IO_CREDS_TYPE_PLAIN:
            break;
        default:
            status = STATUS_ACCESS_DENIED;
            BAIL_ON_NT_STATUS(status);
        }

        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrProcessSessionSetupResponse2(pContext, STATUS_SUCCESS, NULL);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_INITIALIZING:
        pContext->Continue = RdrSessionSetupComplete2;
        LwListInsertTail(&pSession->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrSessionSetupComplete2(pContext, status, pSession);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_ERROR:
        status = pSession->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

 cleanup:

     LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

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

     if (bFreeContext)
     {
         RdrFreeTreeConnectContext(pContext);
     }

     return FALSE;

 error:

     if (status != STATUS_PENDING && pSession)
     {
         LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
         if (status != STATUS_DFS_EXIT_PATH_FOUND)
         {
             RdrSession2Invalidate(pSession, status);
         }
         RdrSession2Release(pSession);
     }

     if (status != STATUS_PENDING && pSocket)
     {
         if (status != STATUS_DFS_EXIT_PATH_FOUND)
         {
             RdrSocketInvalidate(pSocket, status);
         }
         RdrSocketRelease(pSocket);
     }

     goto cleanup;
}
예제 #20
0
LW_NTSTATUS
LwIoSetPathCreds(
    IN LW_PUNICODE_STRING PathPrefix,
    IN OPTIONAL LW_PIO_CREDS pCreds
    )
{
    LW_NTSTATUS Status = STATUS_SUCCESS;
    PIO_PATH_CREDS pPathCreds = NULL;
    PIO_CREDS pCredCopy = NULL;
    BOOL bInLock = FALSE;

    LWIO_LOCK_MUTEX(bInLock, &gLock);

    Status = LwIoFindPathCreds(PathPrefix, TRUE, &pPathCreds);
    BAIL_ON_NT_STATUS(Status);

    if (pPathCreds)
    {
        Status = LwIoCopyCreds(pCreds, &pCredCopy);
        BAIL_ON_NT_STATUS(Status);

        if (pPathCreds->pCreds)
        {
            LwIoDeleteCreds(pPathCreds->pCreds);
        }

        pPathCreds->pCreds = pCredCopy;
        pCredCopy = NULL;
        pPathCreds = NULL;
    }
    else if (pCreds)
    {
        Status = RTL_ALLOCATE(&pPathCreds, IO_PATH_CREDS, sizeof(IO_PATH_CREDS));
        BAIL_ON_NT_STATUS(Status);

        LwListInit(&pPathCreds->link);

        Status = LwIoNormalizePath(PathPrefix, &pPathCreds->PathPrefix);
        BAIL_ON_NT_STATUS(Status);

        Status = LwIoCopyCreds(pCreds, &pPathCreds->pCreds);
        BAIL_ON_NT_STATUS(Status);

        LwListInsertBefore(&gPathCreds, &pPathCreds->link);
        pPathCreds = NULL;
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &gLock);

    if (pCredCopy)
    {
        LwIoDeleteCreds(pCredCopy);
    }

    if (pPathCreds)
    {
        LwIoDeletePathCreds(pPathCreds);
    }

    return Status;

error:

    goto cleanup;
}
예제 #21
0
NTSTATUS
SrvProcessFlush_SMB_V2(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus     = STATUS_SUCCESS;
    PLWIO_SRV_CONNECTION       pConnection  = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V2   pCtxSmb2     = pCtxProtocol->pSmb2Context;
    PSRV_FLUSH_STATE_SMB_V2    pFlushState  = NULL;
    PLWIO_SRV_SESSION_2        pSession     = NULL;
    PLWIO_SRV_TREE_2           pTree        = NULL;
    PLWIO_SRV_FILE_2           pFile        = NULL;
    BOOLEAN                    bInLock      = FALSE;

    pFlushState = (PSRV_FLUSH_STATE_SMB_V2)pCtxSmb2->hState;

    if (pFlushState)
    {
        InterlockedIncrement(&pFlushState->refCount);
    }
    else
    {
        ULONG               iMsg          = pCtxSmb2->iMsg;
        PSRV_MESSAGE_SMB_V2 pSmbRequest   = &pCtxSmb2->pRequests[iMsg];
        PSMB2_FID           pFid = NULL; // Do not free

        ntStatus = SrvConnection2FindSession_SMB_V2(
                        pCtxSmb2,
                        pConnection,
                        pSmbRequest->pHeader->ullSessionId,
                        &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSetStatSession2Info(pExecContext, pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSession2FindTree_SMB_V2(
                        pCtxSmb2,
                        pSession,
                        pSmbRequest->pHeader->ulTid,
                        &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SMB2UnmarshalFlushRequest(pSmbRequest, &pFid);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvTree2FindFile_SMB_V2(
                        pCtxSmb2,
                        pTree,
                        pFid,
                        LwIsSetFlag(
                            pSmbRequest->pHeader->ulFlags,
                            SMB2_FLAGS_RELATED_OPERATION),
                        &pFile);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvBuildFlushState_SMB_V2(
                        pFid,
                        pFile,
                        &pFlushState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb2->hState = pFlushState;
        InterlockedIncrement(&pFlushState->refCount);
        pCtxSmb2->pfnStateRelease = &SrvReleaseFlushStateHandle_SMB_V2;
    }

    LWIO_LOCK_MUTEX(bInLock, &pFlushState->mutex);

    switch (pFlushState->stage)
    {
        case SRV_FLUSH_STAGE_SMB_V2_INITIAL:

            pFlushState->stage = SRV_FLUSH_STAGE_SMB_V2_FLUSH_COMPLETED;

            SrvPrepareFlushStateAsync_SMB_V2(pFlushState, pExecContext);

            ntStatus = IoFlushBuffersFile(
                            pFlushState->pFile->hFile,
                            pFlushState->pAcb,
                            &pFlushState->ioStatusBlock);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseFlushStateAsync_SMB_V2(pFlushState); // completed synchronously

            // intentional fall through

        case SRV_FLUSH_STAGE_SMB_V2_FLUSH_COMPLETED:

            ntStatus = pFlushState->ioStatusBlock.Status;
            BAIL_ON_NT_STATUS(ntStatus);

            pFlushState->stage = SRV_FLUSH_STAGE_SMB_V2_BUILD_RESPONSE;

            // intentional fall through

        case SRV_FLUSH_STAGE_SMB_V2_BUILD_RESPONSE:

            ntStatus = SrvBuildFlushResponse_SMB_V2(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pFlushState->stage = SRV_FLUSH_STAGE_SMB_V2_DONE;

            // intentional fall through

        case SRV_FLUSH_STAGE_SMB_V2_DONE:

            break;
    }

cleanup:

    if (pFile)
    {
        SrvFile2Release(pFile);
    }

    if (pTree)
    {
        SrvTree2Release(pTree);
    }

    if (pSession)
    {
        SrvSession2Release(pSession);
    }

    if (pFlushState)
    {
        LWIO_UNLOCK_MUTEX(bInLock, &pFlushState->mutex);

        SrvReleaseFlushState_SMB_V2(pFlushState);
    }

    return ntStatus;

error:

    switch (ntStatus)
    {
        case STATUS_PENDING:

            // TODO: Add an indicator to the file object to trigger a
            //       cleanup if the connection gets closed and all the
            //       files involved have to be closed

            break;

        default:

            if (pFlushState)
            {
                SrvReleaseFlushStateAsync_SMB_V2(pFlushState);
            }

            break;
    }

    goto cleanup;
}
예제 #22
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;
}
예제 #23
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;
}
예제 #24
0
static
VOID
PvfsNotifyFullReportIrp(
    PPVFS_FCB pFcb,
    PPVFS_FCB pReportParentFcb,
    PPVFS_NOTIFY_REPORT_RECORD pReport
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bActive = FALSE;
    BOOLEAN bLocked =  FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    pFilterLink = PvfsListTraverse(pFcb->pNotifyListIrp, NULL);

    while(pFilterLink)
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        pNextLink = PvfsListTraverse(pFcb->pNotifyListIrp, pFilterLink);

        /* Continue if we don't match the filter and depth */

        if (!((pFilter->NotifyFilter & pReport->Filter) &&
              ((pFcb == pReportParentFcb) || pFilter->bWatchTree)))
        {
            pFilter = NULL;
            pFilterLink = pNextLink;

            continue;
        }

        PvfsListRemoveItem(pFcb->pNotifyListIrp, pFilterLink);

        LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

        pFilterLink = NULL;

        PvfsQueueCancelIrpIfRequested(pFilter->pIrpContext);

        bActive = PvfsIrpContextMarkIfNotSetFlag(
                      pFilter->pIrpContext,
                      PVFS_IRP_CTX_FLAG_CANCELLED,
                      PVFS_IRP_CTX_FLAG_ACTIVE);

        if (!bActive)
        {
            PvfsFreeNotifyRecord(&pFilter);
            pFilterLink = pNextLink;

            continue;
        }

        ntError = PvfsNotifyReportIrp(
                      pFilter->pIrpContext,
                      pReport->Action,
                      pReport->pszFilename);
        BAIL_ON_NT_STATUS(ntError);

        /* If we have been asked to buffer changes, move the Fitler Record
           to the buffer list */

        if (pFilter->Buffer.Length > 0)
        {
            LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);
            ntError = PvfsListAddTail(pFcb->pNotifyListBuffer, pFilterLink);
            LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

            BAIL_ON_NT_STATUS(ntError);

            pFilter = NULL;
        }

        /* We only process on matching IRP */
        break;
    }

cleanup:
    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    if (pFilter)
    {
        PvfsFreeNotifyRecord(&pFilter);
    }

    return;

error:
    goto cleanup;
}
예제 #25
0
NTSTATUS
SrvProcessGetInfo_SMB_V2(
    PSRV_EXEC_CONTEXT pExecContext
)
{
    NTSTATUS                   ntStatus      = STATUS_SUCCESS;
    PLWIO_SRV_CONNECTION       pConnection   = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol  = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V2   pCtxSmb2      = pCtxProtocol->pSmb2Context;
    PSRV_GET_INFO_STATE_SMB_V2 pGetInfoState = NULL;
    PLWIO_SRV_SESSION_2        pSession      = NULL;
    PLWIO_SRV_TREE_2           pTree         = NULL;
    PLWIO_SRV_FILE_2           pFile         = NULL;
    BOOLEAN                    bInLock       = FALSE;

    pGetInfoState = (PSRV_GET_INFO_STATE_SMB_V2)pCtxSmb2->hState;
    if (pGetInfoState)
    {
        InterlockedIncrement(&pGetInfoState->refCount);
    }
    else
    {
        ULONG                      iMsg          = pCtxSmb2->iMsg;
        PSRV_MESSAGE_SMB_V2        pSmbRequest   = &pCtxSmb2->pRequests[iMsg];
        PSMB2_GET_INFO_REQUEST_HEADER pRequestHeader = NULL; // Do not free
        PBYTE                      pInputBuffer  = NULL;
        ULONG                      ulInputBufferLength = 0;

        ntStatus = SrvConnection2FindSession_SMB_V2(
                       pCtxSmb2,
                       pConnection,
                       pSmbRequest->pHeader->ullSessionId,
                       &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSetStatSession2Info(pExecContext, pSession);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvSession2FindTree_SMB_V2(
                       pCtxSmb2,
                       pSession,
                       pSmbRequest->pHeader->ulTid,
                       &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SMB2UnmarshalGetInfoRequest(
                       pSmbRequest,
                       &pRequestHeader,
                       &pInputBuffer,
                       &ulInputBufferLength);
        BAIL_ON_NT_STATUS(ntStatus);

        SRV_LOG_DEBUG(
            pExecContext->pLogContext,
            SMB_PROTOCOL_VERSION_2,
            pSmbRequest->pHeader->command,
            "Get Info request params: "
            "command(%u),uid(%llu),cmd-seq(%llu),pid(%u),tid(%u),"
            "credits(%u),flags(0x%x),chain-offset(%u),"
            "file-id(persistent:0x%x,volatile:0x%x),"
            "info-class(0x%x),info-type(0x%x),flags(0x%x),"
            "input-buffer-length(%u),input-buffer-offset(%u),"
            "output-buffer-length(%u),additional-info(%u)",
            pSmbRequest->pHeader->command,
            (long long)pSmbRequest->pHeader->ullSessionId,
            (long long)pSmbRequest->pHeader->ullCommandSequence,
            pSmbRequest->pHeader->ulPid,
            pSmbRequest->pHeader->ulTid,
            pSmbRequest->pHeader->usCredits,
            pSmbRequest->pHeader->ulFlags,
            pSmbRequest->pHeader->ulChainOffset,
            (long long)pRequestHeader->fid.ullPersistentId,
            (long long)pRequestHeader->fid.ullVolatileId,
            pRequestHeader->ucInfoClass,
            pRequestHeader->ucInfoType,
            pRequestHeader->ulFlags,
            pRequestHeader->ulInputBufferLen,
            pRequestHeader->usInputBufferOffset,
            pRequestHeader->ulOutputBufferLen,
            pRequestHeader->ulAdditionalInfo);

        ntStatus = SrvTree2FindFile_SMB_V2(
                       pCtxSmb2,
                       pTree,
                       &pRequestHeader->fid,
                       &pFile);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvBuildGetInfoState_SMB_V2(
                       pRequestHeader,
                       pFile,
                       pInputBuffer,
                       ulInputBufferLength,
                       &pGetInfoState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb2->hState = pGetInfoState;
        InterlockedIncrement(&pGetInfoState->refCount);
        pCtxSmb2->pfnStateRelease = &SrvReleaseGetInfoStateHandle_SMB_V2;
    }

    LWIO_LOCK_MUTEX(bInLock, &pGetInfoState->mutex);

    switch (pGetInfoState->stage)
    {
    case SRV_GET_INFO_STAGE_SMB_V2_INITIAL:

        pGetInfoState->stage = SRV_GET_INFO_STAGE_SMB_V2_ATTEMPT_IO;

    // Intentional fall through

    case SRV_GET_INFO_STAGE_SMB_V2_ATTEMPT_IO:

        ntStatus = SrvQueryInfo_SMB_V2(pExecContext);
        BAIL_ON_NT_STATUS(ntStatus);

        pGetInfoState->stage = SRV_GET_INFO_STAGE_SMB_V2_BUILD_RESPONSE;

    // Intentional fall through

    case SRV_GET_INFO_STAGE_SMB_V2_BUILD_RESPONSE:

        ntStatus = SrvBuildGetInfoResponse_SMB_V2(pExecContext);
        BAIL_ON_NT_STATUS(ntStatus);

        pGetInfoState->stage = SRV_GET_INFO_STAGE_SMB_V2_DONE;

    // Intentional fall through

    case SRV_GET_INFO_STAGE_SMB_V2_DONE:

        break;
    }

cleanup:

    if (pFile)
    {
        SrvFile2Release(pFile);
    }

    if (pTree)
    {
        SrvTree2Release(pTree);
    }

    if (pSession)
    {
        SrvSession2Release(pSession);
    }

    if (pGetInfoState)
    {
        LWIO_UNLOCK_MUTEX(bInLock, &pGetInfoState->mutex);

        SrvReleaseGetInfoState_SMB_V2(pGetInfoState);
    }

    return ntStatus;

error:

    switch (ntStatus)
    {
    case STATUS_PENDING:

        // TODO: Add an indicator to the file object to trigger a
        //       cleanup if the connection gets closed and all the
        //       files involved have to be closed

        break;

    default:

        if (pGetInfoState)
        {
            SrvReleaseGetInfoStateAsync_SMB_V2(pGetInfoState);
        }

        break;
    }

    goto cleanup;
}
예제 #26
0
static
NTSTATUS
PvfsNotifyReportBufferedChanges(
    PPVFS_CCB pCcb,
    PPVFS_FCB pFcb,
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    FILE_NOTIFY_CHANGE Filter = pIrpContext->pIrp->Args.ReadDirectoryChange.NotifyFilter;
    PVOID pBuffer = pIrpContext->pIrp->Args.ReadDirectoryChange.Buffer;
    ULONG Length = pIrpContext->pIrp->Args.ReadDirectoryChange.Length;
    PLW_LIST_LINKS pFilterLink = NULL;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    BOOLEAN bLocked = FALSE;

    LWIO_LOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    /* See if we have any changes to report immediately */

    for (pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, NULL);
         pFilterLink;
         pFilterLink = PvfsListTraverse(pFcb->pNotifyListBuffer, pFilterLink))
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        /* To return the buffered changes, we have to match the handle
           and the filter */

        if ((pFilter->NotifyFilter != Filter) || (pFilter->pCcb != pCcb))
        {
            continue;
        }

        /* We have a match to check to see if we have anything */

        if ((pFilter->Buffer.Length == 0) ||
            (pFilter->Buffer.Offset == 0))
        {
            ntError = STATUS_NOT_FOUND;
            BAIL_ON_NT_STATUS(ntError);
        }

        /* We have changes....Do we have enough space?  Have we already
           overflowed the buffer? */

        ntError = pFilter->Buffer.Status;
        BAIL_ON_NT_STATUS(ntError);

        if (pFilter->Buffer.Offset > Length)
        {
            PvfsNotifyClearBufferedChanges(&pFilter->Buffer);

            ntError = STATUS_NOTIFY_ENUM_DIR;
            BAIL_ON_NT_STATUS(ntError);
        }

        memcpy(pBuffer, pFilter->Buffer.pData, pFilter->Buffer.Offset);
        pIrpContext->pIrp->IoStatusBlock.BytesTransferred = pFilter->Buffer.Offset;

        PvfsNotifyClearBufferedChanges(&pFilter->Buffer);
    }

    if (pFilterLink == NULL)
    {
        ntError = STATUS_NOT_FOUND;
        BAIL_ON_NT_STATUS(ntError);
    }


cleanup:
    LWIO_UNLOCK_MUTEX(bLocked, &pFcb->BaseControlBlock.Mutex);

    return ntError;

error:
    goto cleanup;
}
예제 #27
0
NTSTATUS
RdrTreeConnect(
    PCWSTR pwszHostname,
    PCWSTR pwszSharename,
    PIO_CREDS pCreds,
    uid_t Uid,
    BOOLEAN bStopOnDfs,
    PRDR_OP_CONTEXT pContinue
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRDR_OP_CONTEXT pContext = NULL;
    BOOLEAN bSocketLocked = FALSE;
    PRDR_SOCKET pSocket = NULL;

    status = RdrCreateContext(pContinue->pIrp, &pContext);
    BAIL_ON_NT_STATUS(status);

    LWIO_LOG_DEBUG("Tree connect context %p will continue %p\n", pContext, pContinue);

    pContext->State.TreeConnect.Uid = Uid;
    pContext->State.TreeConnect.bStopOnDfs = bStopOnDfs;
    pContext->State.TreeConnect.pContinue = pContinue;

    status = LwRtlWC16StringDuplicate(
        &pContext->State.TreeConnect.pwszSharename,
        pwszSharename);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pCreds = pCreds;

    status = RdrSocketFindOrCreate(
        pwszHostname,
        &pSocket);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSocket = pSocket;

    LWIO_LOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    switch (pSocket->state)
    {
    case RDR_SOCKET_STATE_NOT_READY:
        pSocket->state = RDR_SOCKET_STATE_CONNECTING;
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

        /* Add extra reference to socket for work item */
        RdrSocketRetain(pSocket);
        status = LwRtlQueueWorkItem(
            gRdrRuntime.pThreadPool,
            RdrSocketConnectWorkItem,
            pSocket,
            0);
        if (status)
        {
            /* Nevermind */
            RdrSocketRelease(pSocket);
        }
        BAIL_ON_NT_STATUS(status);

        pContext->Continue = RdrProcessNegotiateResponse;

        status = RdrTransceiveNegotiate(pContext, pSocket);
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_CONNECTING:
    case RDR_SOCKET_STATE_NEGOTIATING:
        pContext->Continue = RdrNegotiateComplete;
        LwListInsertTail(&pSocket->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);
        RdrNegotiateComplete(pContext, STATUS_SUCCESS, pSocket);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_ERROR:
        status = pSocket->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    if (status != STATUS_PENDING)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return status;

error:

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

    goto cleanup;
}
예제 #28
0
static NTSTATUS
PvfsQueryFileIdFullDirInfo(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PFILE_ID_FULL_DIR_INFORMATION pFileInfo = NULL;
    PFILE_ID_FULL_DIR_INFORMATION pPrevFileInfo = NULL;
    IRP_ARGS_QUERY_DIRECTORY Args = pIrpContext->pIrp->Args.QueryDirectory;
    PVOID pBuffer = NULL;
    DWORD dwBufLen = 0;
    DWORD dwOffset = 0;
    DWORD dwConsumed = 0;
    BOOLEAN bLocked = FALSE;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if (!PVFS_IS_DIR(pCcb))
    {
        ntError = STATUS_NOT_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsAccessCheckFileHandle(pCcb,  FILE_LIST_DIRECTORY);
    BAIL_ON_NT_STATUS(ntError);

    BAIL_ON_INVALID_PTR(Args.FileInformation, ntError);

    if (Args.Length < sizeof(*pFileInfo))
    {
        ntError = STATUS_BUFFER_TOO_SMALL;
        BAIL_ON_NT_STATUS(ntError);
    }

    pFileInfo = (PFILE_ID_FULL_DIR_INFORMATION)Args.FileInformation;

    /* Scen the first time through */

    ntError = STATUS_SUCCESS;

    /* Critical region to prevent inteleaving directory
       enumeration */

    LWIO_LOCK_MUTEX(bLocked, &pCcb->FileMutex);

    if (!pCcb->pDirContext->bScanned) {
        ntError = PvfsEnumerateDirectory(
                      pCcb,
                      pIrp->Args.QueryDirectory.FileSpec,
                      -1,
                      FALSE);
    }

    LWIO_UNLOCK_MUTEX(bLocked, &pCcb->FileMutex);

    BAIL_ON_NT_STATUS(ntError);

    /* Check for ending condition */

    if (pCcb->pDirContext->dwIndex == pCcb->pDirContext->dwNumEntries)
    {
        ntError = STATUS_NO_MORE_MATCHES;
        BAIL_ON_NT_STATUS(ntError);
    }


    /* Fill in the buffer */

    pBuffer = Args.FileInformation;
    dwBufLen = Args.Length;
    dwOffset = 0;
    pFileInfo = NULL;
    pPrevFileInfo = NULL;

    do
    {
        PPVFS_DIRECTORY_ENTRY pEntry = NULL;
        DWORD dwIndex;

        pFileInfo = (PFILE_ID_FULL_DIR_INFORMATION)(pBuffer + dwOffset);
        pFileInfo->NextEntryOffset = 0;

        dwIndex = pCcb->pDirContext->dwIndex;
        pEntry  = &pCcb->pDirContext->pDirEntries[dwIndex];
        ntError = FillFileIdFullDirInfoBuffer(
                      pFileInfo,
                      dwBufLen - dwOffset,
                      pCcb->pszFilename,
                      pEntry,
                      &dwConsumed);

        /* If we ran out of buffer space, reset pointer to previous
           entry and break out of loop */

        if (ntError == STATUS_BUFFER_TOO_SMALL) {
            pFileInfo = pPrevFileInfo;
            break;
        }

        /* OBJECT_NAME_NOT_FOUND - This deals with a possible race
           where the directory contents was read but the file was
           removed before we could stat() it.

           INSUFFICIENT_RESOURCES - Invalid UTF-8 name.

           ACCESS_DENIED - Special cases like $HOME/.gvfs that can't
           be read by root.  Possibly just an Ubuntu bug but don't
           fail on it.
           https://bugs.launchpad.net/ubuntu/+source/gvfs/+bug/227724

           Just skip the file and move on. */

        if (ntError == STATUS_OBJECT_NAME_NOT_FOUND ||
            ntError == STATUS_INSUFFICIENT_RESOURCES ||
            ntError == STATUS_ACCESS_DENIED)
        {
            pFileInfo = pPrevFileInfo;
            pCcb->pDirContext->dwIndex++;
            continue;
        }

        /* Catch any other errors and bail */

        BAIL_ON_NT_STATUS(ntError);

        pFileInfo->NextEntryOffset = dwConsumed;

        dwOffset += dwConsumed;
        pCcb->pDirContext->dwIndex++;

        pPrevFileInfo = pFileInfo;

        if (Args.ReturnSingleEntry) {
            break;
        }
    }
    /* Exit loop when we are out of buffer or out of entries.  The
       filling function can also break us out of the loop. */
    while (((dwBufLen - dwOffset) > sizeof(FILE_ID_FULL_DIR_INFORMATION)) &&
             (pCcb->pDirContext->dwIndex < pCcb->pDirContext->dwNumEntries));

    /* Update final offset */

    if (pFileInfo) {
        pFileInfo->NextEntryOffset = 0;
    }

    pIrp->IoStatusBlock.BytesTransferred = dwOffset;
    ntError = STATUS_SUCCESS;

cleanup:
    if (pCcb) {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    goto cleanup;
}
예제 #29
0
static
VOID
PvfsNotifyCleanIrpList(
    PVOID pContext
    )
{
    PPVFS_IRP_CONTEXT pIrpCtx = (PPVFS_IRP_CONTEXT)pContext;
    PPVFS_FCB pFcb = NULL;
    BOOLEAN bFcbLocked = FALSE;
    PPVFS_NOTIFY_FILTER_RECORD pFilter = NULL;
    PLW_LIST_LINKS pFilterLink = NULL;
    PLW_LIST_LINKS pNextLink = NULL;
    BOOLEAN bFound = FALSE;

    LWIO_ASSERT(pIrpCtx->pScb->pOwnerFcb);

    // We have the IrpCtx->Scb's reference so no need to take another
    pFcb = pIrpCtx->pScb->pOwnerFcb;

    LWIO_LOCK_MUTEX(bFcbLocked, &pFcb->BaseControlBlock.Mutex);

    pFilterLink = PvfsListTraverse(pFcb->pNotifyListIrp, NULL);

    while (pFilterLink)
    {
        pFilter = LW_STRUCT_FROM_FIELD(
                      pFilterLink,
                      PVFS_NOTIFY_FILTER_RECORD,
                      NotifyList);

        pNextLink = PvfsListTraverse(pFcb->pNotifyListIrp, pFilterLink);

        if (pFilter->pIrpContext != pIrpCtx)
        {
            pFilterLink = pNextLink;
            continue;
        }

        bFound = TRUE;

        PvfsListRemoveItem(pFcb->pNotifyListIrp, pFilterLink);
        pFilterLink = NULL;

        LWIO_UNLOCK_MUTEX(bFcbLocked, &pFcb->BaseControlBlock.Mutex);

        pFilter->pIrpContext->pIrp->IoStatusBlock.Status = STATUS_CANCELLED;

        PvfsCompleteIrpContext(pFilter->pIrpContext);

        PvfsFreeNotifyRecord(&pFilter);

        /* Can only be one IrpContext match so we are done */
    }

    LWIO_UNLOCK_MUTEX(bFcbLocked, &pFcb->BaseControlBlock.Mutex);

    if (!bFound)
    {
        pIrpCtx->pIrp->IoStatusBlock.Status = STATUS_CANCELLED;

        PvfsCompleteIrpContext(pIrpCtx);
    }

    if (pIrpCtx)
    {
        PvfsReleaseIrpContext(&pIrpCtx);
    }

    return;
}
예제 #30
0
static
BOOLEAN
RdrNegotiateComplete(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pParam;
    PRDR_SESSION pSession = NULL;
    BOOLEAN bSessionLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;
    PIO_CREDS pCreds = pContext->State.TreeConnect.pCreds;

    BAIL_ON_NT_STATUS(status);

    /* Several op contexts could be queued with this function
     * as the continue routine before we transition to SMB2 mode,
     * so we need to hand off to the correct function in this case.
     * Subsequent attempts should go straight to connect2.c
     */
    if (pSocket->version == SMB_PROTOCOL_VERSION_2)
    {
        /* Short circuit to SMB2 session setup logic in connect2.c */
        return RdrNegotiateComplete2(pContext, status, pParam);
    }

    if (pContext->State.TreeConnect.bStopOnDfs &&
        pSocket->capabilities & CAP_DFS)
    {
        /* Abort tree connect because we need to do DFS referral processing first */
        status = STATUS_DFS_EXIT_PATH_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    status = RdrSessionFindOrCreate(
        &pSocket,
        pContext->State.TreeConnect.pCreds,
        pContext->State.TreeConnect.Uid,
        &pSession);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSession = pSession;

    LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

    switch (pSession->state)
    {
    case RDR_SESSION_STATE_NOT_READY:
        pSession->state = RDR_SESSION_STATE_INITIALIZING;

        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_TGT:
            status = SMBCredTokenToKrb5CredCache(
                pCreds,
                &pContext->State.TreeConnect.pszCachePath);
            BAIL_ON_NT_STATUS(status);
            break;
        case IO_CREDS_TYPE_PLAIN:
            break;
        default:
            status = STATUS_ACCESS_DENIED;
            BAIL_ON_NT_STATUS(status);
        }

        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrProcessSessionSetupResponse(pContext, STATUS_SUCCESS, NULL);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_INITIALIZING:
        pContext->Continue = RdrSessionSetupComplete;
        LwListInsertTail(&pSession->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrSessionSetupComplete(pContext, status, pSession);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_ERROR:
        status = pSession->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

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

    if (bFreeContext)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return FALSE;

error:

    if (status != STATUS_PENDING && pSession)
    {
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        if (status != STATUS_DFS_EXIT_PATH_FOUND)
        {
            RdrSessionInvalidate(pSession, status);
        }
        RdrSessionRelease(pSession);
    }

    if (status != STATUS_PENDING && pSocket)
    {
        if (status != STATUS_DFS_EXIT_PATH_FOUND)
        {
            RdrSocketInvalidate(pSocket, status);
        }
        RdrSocketRelease(pSocket);
    }

    goto cleanup;
}