Esempio n. 1
0
NTSTATUS
SrvSessionCreate(
    USHORT            uid,
    PLWIO_SRV_SESSION* ppSession
    )
{
    NTSTATUS ntStatus = 0;
    PLWIO_SRV_SESSION pSession = NULL;

    LWIO_LOG_DEBUG("Creating session [uid:%u]", uid);

    ntStatus = SrvAllocateMemory(
                    sizeof(LWIO_SRV_SESSION),
                    (PVOID*)&pSession);
    BAIL_ON_NT_STATUS(ntStatus);

    pSession->refcount = 1;

    pthread_rwlock_init(&pSession->mutex, NULL);
    pSession->pMutex = &pSession->mutex;

    pSession->uid = uid;

    ntStatus = WireGetCurrentNTTime(&pSession->llBirthTime);
    BAIL_ON_NT_STATUS(ntStatus);

    pSession->llLastActivityTime = pSession->llBirthTime;

    LWIO_LOG_DEBUG("Associating session [object:0x%x][uid:%u]", pSession, uid);

    ntStatus = LwRtlRBTreeCreate(
                    &SrvSessionTreeCompare,
                    NULL,
                    &SrvSessionTreeRelease,
                    &pSession->pTreeCollection);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = SrvFinderCreateRepository(
                    &pSession->hFinderRepository);
    BAIL_ON_NT_STATUS(ntStatus);

    SRV_ELEMENTS_INCREMENT_SESSIONS;

    *ppSession = pSession;

cleanup:

    return ntStatus;

error:

    *ppSession = NULL;

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

    goto cleanup;
}
Esempio n. 2
0
NTSTATUS
SrvConnectionFindSession_SMB_V1(
    PSRV_EXEC_CONTEXT_SMB_V1 pSmb1Context,
    PLWIO_SRV_CONNECTION     pConnection,
    USHORT                   usUid,
    PLWIO_SRV_SESSION*       ppSession
    )
{
    NTSTATUS          ntStatus = STATUS_SUCCESS;
    PLWIO_SRV_SESSION pSession = NULL;

    if (usUid)
    {
        if (pSmb1Context->pSession)
        {
            if (pSmb1Context->pSession->uid != usUid)
            {
                ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
                BAIL_ON_NT_STATUS(ntStatus);
            }
            else
            {
                pSession = SrvSessionAcquire(pSmb1Context->pSession);
            }
        }
        else
        {
            ntStatus = SrvConnectionFindSession(
                            pConnection,
                            usUid,
                            &pSession);
            BAIL_ON_NT_STATUS(ntStatus);

            pSmb1Context->pSession = SrvSessionAcquire(pSession);
        }
    }
    else if (pSmb1Context->pSession)
    {
        pSession = SrvSessionAcquire(pSmb1Context->pSession);
    }
    else
    {
        ntStatus = STATUS_NO_SUCH_LOGON_SESSION;
        BAIL_ON_NT_STATUS(ntStatus);
    }

    *ppSession = pSession;

cleanup:

    return ntStatus;

error:

    *ppSession = NULL;

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

    goto cleanup;
}
Esempio n. 3
0
NTSTATUS
SrvProcessLogoffAndX(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus        = 0;
    PLWIO_SRV_CONNECTION       pConnection     = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol    = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1        = pCtxProtocol->pSmb1Context;
    ULONG                      iMsg            = pCtxSmb1->iMsg;
    PSRV_MESSAGE_SMB_V1        pSmbRequest     = &pCtxSmb1->pRequests[iMsg];
    PSRV_MESSAGE_SMB_V1        pSmbResponse    = &pCtxSmb1->pResponses[iMsg];
    PLOGOFF_RESPONSE_HEADER    pResponseHeader = NULL; // Do not free
    PBYTE pOutBuffer       = pSmbResponse->pBuffer;
    ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable;
    ULONG ulOffset         = 0;
    ULONG ulTotalBytesUsed = 0;
    PLWIO_SRV_SESSION pSession = NULL;

    ntStatus = SrvConnectionFindSession(
                    pConnection,
                    pSmbRequest->pHeader->uid,
                    &pSession);
    BAIL_ON_NT_STATUS(ntStatus);

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

    SRV_LOG_DEBUG(
            pExecContext->pLogContext,
            SMB_PROTOCOL_VERSION_1,
            pSmbRequest->pHeader->command,
            "Logging off session: command(%u),uid(%u),mid(%u),pid(%u),tid(%u)",
            pSmbRequest->pHeader->command,
            pSmbRequest->pHeader->uid,
            pSmbRequest->pHeader->mid,
            SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader),
            pSmbRequest->pHeader->tid);

    SrvSessionRundown(pSession);

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

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

    *pSmbResponse->pWordCount = 2;

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

    pResponseHeader = (PLOGOFF_RESPONSE_HEADER)pOutBuffer;

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

    pResponseHeader->byteCount = 0;

    pSmbResponse->ulMessageSize = ulTotalBytesUsed;

cleanup:
    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

    return ntStatus;

error:

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

    pSmbResponse->ulMessageSize = 0;

    goto cleanup;
}
Esempio n. 4
0
NTSTATUS
SrvProcessOpenAndX(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus     = 0;
    PLWIO_SRV_CONNECTION       pConnection  = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PLWIO_SRV_SESSION          pSession     = NULL;
    PLWIO_SRV_TREE             pTree        = NULL;
    PSRV_OPEN_STATE_SMB_V1     pOpenState   = NULL;
    BOOLEAN                    bInLock      = FALSE;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;
    if (pOpenState)
    {
        InterlockedIncrement(&pOpenState->refCount);
    }
    else
    {
        ULONG               iMsg        = pCtxSmb1->iMsg;
        PSRV_MESSAGE_SMB_V1 pSmbRequest = &pCtxSmb1->pRequests[iMsg];
        PBYTE pBuffer          = pSmbRequest->pBuffer + pSmbRequest->usHeaderSize;
        ULONG ulOffset         = pSmbRequest->usHeaderSize;
        ULONG ulBytesAvailable = pSmbRequest->ulMessageSize - pSmbRequest->usHeaderSize;
        POPEN_REQUEST_HEADER pRequestHeader = NULL; // Do not free
        PWSTR                pwszFilename = NULL;   // Do not free

        if (pCtxSmb1->pFile)
        {
            ntStatus = STATUS_INVALID_NETWORK_RESPONSE;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        ntStatus = SrvConnectionFindSession_SMB_V1(
                            pCtxSmb1,
                            pConnection,
                            pSmbRequest->pHeader->uid,
                            &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

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

        ntStatus = SrvSessionFindTree_SMB_V1(
                        pCtxSmb1,
                        pSession,
                        pSmbRequest->pHeader->tid,
                        &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = WireUnmarshallOpenRequest(
                        pBuffer,
                        ulBytesAvailable,
                        ulOffset,
                        &pRequestHeader,
                        &pwszFilename);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvBuildOpenState(
                        pExecContext,
                        pRequestHeader,
                        pwszFilename,
                        &pOpenState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb1->hState = pOpenState;
        InterlockedIncrement(&pOpenState->refCount);
        pCtxSmb1->pfnStateRelease = &SrvReleaseOpenStateHandle;
    }

    LWIO_LOCK_MUTEX(bInLock, &pOpenState->mutex);

    switch (pOpenState->stage)
    {
        case SRV_OPEN_STAGE_SMB_V1_INITIAL:

            SRV_LOG_CALL_DEBUG(
                    pExecContext->pLogContext,
                    SMB_PROTOCOL_VERSION_1,
                    pCtxSmb1->pRequests[pCtxSmb1->iMsg].pHeader->command,
                    &SrvLogOpenState_SMB_V1,
                    pOpenState);

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_OPEN_FILE_COMPLETED;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = SrvIoCreateFile(
                            pOpenState->pTree->pShareInfo,
                            &pOpenState->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pSession->pIoSecurityContext,
                            pOpenState->pFilename,
                            pOpenState->pSecurityDescriptor,
                            pOpenState->pSecurityQOS,
                            pOpenState->ulDesiredAccessMask,
                            pOpenState->pRequestHeader->ulAllocationSize,
                            pOpenState->pRequestHeader->usFileAttributes,
                            pOpenState->usShareAccess,
                            pOpenState->ulCreateDisposition,
                            pOpenState->usCreateOptions,
                            NULL, /* EA Buffer */
                            0,    /* EA Length */
                            pOpenState->pEcpList);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_OPEN_FILE_COMPLETED:

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

            pOpenState->ulCreateAction =
                            pOpenState->ioStatusBlock.CreateResult;

            ntStatus = SrvTreeCreateFile(
                            pOpenState->pTree,
                            pOpenState->pwszFilename,
                            &pOpenState->hFile,
                            &pOpenState->pFilename,
                            pOpenState->pRequestHeader->usDesiredAccess,
                            pOpenState->pRequestHeader->ulAllocationSize,
                            pOpenState->pRequestHeader->usFileAttributes,
                            pOpenState->usShareAccess,
                            pOpenState->ulCreateDisposition,
                            pOpenState->usCreateOptions,
                            &pOpenState->pFile);
            BAIL_ON_NT_STATUS(ntStatus);

            pOpenState->pFile->pfnCancelAsyncOperationsFile = SrvCancelFileAsyncOperations;

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_ATTEMPT_QUERY_INFO;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_ATTEMPT_QUERY_INFO:

            ntStatus = SrvQueryFileOpenInformation(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_REQUEST_OPLOCK;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_REQUEST_OPLOCK:

            ntStatus = SrvRequestOpenXOplocks(pExecContext);
            // Don't fail on the account on not being granted an oplock

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_QUERY_INFO_COMPLETED;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_QUERY_INFO_COMPLETED:

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

            if (!pOpenState->pFile->hCancellableBRLStateList)
            {
                PSRV_BYTE_RANGE_LOCK_STATE_LIST pBRLStateList = NULL;

                ntStatus = SrvCreatePendingLockStateList(&pBRLStateList);
                BAIL_ON_NT_STATUS(ntStatus);

                pOpenState->pFile->hCancellableBRLStateList =
                                (HANDLE)pBRLStateList;

                pOpenState->pFile->pfnFreeBRLStateList =
                                &SrvFreePendingLockStateListHandle;
            }

            ntStatus = SrvBuildOpenResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvElementsRegisterResource(
                            &pOpenState->pFile->resource,
                            NULL);
            BAIL_ON_NT_STATUS(ntStatus);

            pOpenState->stage = SRV_OPEN_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_OPEN_STAGE_SMB_V1_DONE:

            if (pOpenState->pRequestHeader->usDesiredAccess & FILE_READ_DATA)
            {
                pOpenState->pFile->ulPermissions |= SRV_PERM_FILE_READ;
            }
            if (pOpenState->pRequestHeader->usDesiredAccess & FILE_WRITE_DATA)
            {
                pOpenState->pFile->ulPermissions |= SRV_PERM_FILE_WRITE;
            }
            if (pOpenState->ulCreateAction == FILE_CREATED)
            {
                pOpenState->pFile->ulPermissions |= SRV_PERM_FILE_CREATE;
            }

            // transfer file so we do not run it down
            pCtxSmb1->pFile = pOpenState->pFile;
            pOpenState->pFile = NULL;

            break;
    }

cleanup:

    if (pTree)
    {
        SrvTreeRelease(pTree);
    }

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

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

        SrvReleaseOpenState(pOpenState);
    }

    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 (pOpenState)
            {
                SrvReleaseOpenStateAsync(pOpenState);
            }

            break;
    }

    goto cleanup;
}
Esempio n. 5
0
NTSTATUS
SrvProcessRename(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus     = 0;
    PLWIO_SRV_CONNECTION       pConnection  = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PLWIO_SRV_SESSION          pSession     = NULL;
    PLWIO_SRV_TREE             pTree        = NULL;
    PSRV_RENAME_STATE_SMB_V1   pRenameState = NULL;
    BOOLEAN                    bInLock      = FALSE;

    pRenameState = (PSRV_RENAME_STATE_SMB_V1)pCtxSmb1->hState;
    if (pRenameState)
    {
        InterlockedIncrement(&pRenameState->refCount);
    }
    else
    {
        ULONG               iMsg         = pCtxSmb1->iMsg;
        PSRV_MESSAGE_SMB_V1 pSmbRequest  = &pCtxSmb1->pRequests[iMsg];
        PBYTE pBuffer          = pSmbRequest->pBuffer + pSmbRequest->usHeaderSize;
        ULONG ulOffset         = pSmbRequest->usHeaderSize;
        ULONG ulBytesAvailable = pSmbRequest->ulMessageSize - pSmbRequest->usHeaderSize;
        PSMB_RENAME_REQUEST_HEADER pRequestHeader = NULL; // Do not free
        PWSTR                      pwszOldName    = NULL; // Do not free
        PWSTR                      pwszNewName    = NULL; // Do not free

        ntStatus = SrvConnectionFindSession_SMB_V1(
                        pCtxSmb1,
                        pConnection,
                        pSmbRequest->pHeader->uid,
                        &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

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

        ntStatus = SrvSessionFindTree_SMB_V1(
                        pCtxSmb1,
                        pSession,
                        pSmbRequest->pHeader->tid,
                        &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = WireUnmarshallRenameRequest(
                        pBuffer,
                        ulBytesAvailable,
                        ulOffset,
                        &pRequestHeader,
                        &pwszOldName,
                        &pwszNewName);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = SrvBuildRenameState(
                        pRequestHeader,
                        pwszOldName,
                        pwszNewName,
                        &pRenameState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb1->hState = pRenameState;
        InterlockedIncrement(&pRenameState->refCount);
        pCtxSmb1->pfnStateRelease = &SrvReleaseRenameStateHandle;
    }

    LWIO_LOCK_MUTEX(bInLock, &pRenameState->mutex);

    switch (pRenameState->stage)
    {
        case SRV_RENAME_STAGE_SMB_V1_INITIAL:

            ntStatus = SrvBuildTreeRelativePath(
                            pCtxSmb1->pTree,
                            pRenameState->pwszOldName,
                            &pRenameState->oldName);
            BAIL_ON_NT_STATUS(ntStatus);

            ntStatus = SrvBuildTreeRelativePath(
                            pCtxSmb1->pTree,
                            NULL,
                            &pRenameState->dirPath);
            BAIL_ON_NT_STATUS(ntStatus);

            pRenameState->newName.FileName = pRenameState->pwszNewName;

            pRenameState->stage = SRV_RENAME_STAGE_SMB_V1_ATTEMPT_RENAME;

            // intentional fall through

        case SRV_RENAME_STAGE_SMB_V1_ATTEMPT_RENAME:

            ntStatus = SrvExecuteRename(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pRenameState->stage = SRV_RENAME_STAGE_SMB_V1_BUILD_RESPONSE;

            // intentional fall through

        case SRV_RENAME_STAGE_SMB_V1_BUILD_RESPONSE:

            ntStatus = SrvBuildRenameResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pRenameState->stage = SRV_RENAME_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_RENAME_STAGE_SMB_V1_DONE:

            break;
    }

cleanup:

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

    if (pTree)
    {
        SrvTreeRelease(pTree);
    }

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

        SrvReleaseRenameState(pRenameState);
    }

    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 (pRenameState)
            {
                SrvReleaseRenameStateAsync(pRenameState);
            }

            break;
    }

    goto cleanup;
}
Esempio n. 6
0
NTSTATUS
SrvProcessCheckDirectory(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus       = 0;
    PLWIO_SRV_CONNECTION       pConnection    = pExecContext->pConnection;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol   = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1       = pCtxProtocol->pSmb1Context;
    PLWIO_SRV_SESSION          pSession       = NULL;
    PLWIO_SRV_TREE             pTree          = NULL;
    PSRV_CHECKDIR_STATE_SMB_V1 pCheckdirState = NULL;
    BOOLEAN                    bInLock        = FALSE;

    pCheckdirState = (PSRV_CHECKDIR_STATE_SMB_V1)pCtxSmb1->hState;
    if (pCheckdirState)
    {
        InterlockedIncrement(&pCheckdirState->refCount);
    }
    else
    {
        ULONG               iMsg         = pCtxSmb1->iMsg;
        PSRV_MESSAGE_SMB_V1 pSmbRequest  = &pCtxSmb1->pRequests[iMsg];
        PBYTE pBuffer          = pSmbRequest->pBuffer + pSmbRequest->usHeaderSize;
        ULONG ulOffset         = pSmbRequest->usHeaderSize;
        ULONG ulBytesAvailable = pSmbRequest->ulMessageSize - pSmbRequest->usHeaderSize;
        PWSTR pwszPathFragment = NULL; // Do not free
        PSMB_CHECK_DIRECTORY_REQUEST_HEADER pRequestHeader = NULL;// Do not free

        ntStatus = SrvConnectionFindSession_SMB_V1(
                        pCtxSmb1,
                        pConnection,
                        pSmbRequest->pHeader->uid,
                        &pSession);
        BAIL_ON_NT_STATUS(ntStatus);

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

        ntStatus = SrvSessionFindTree_SMB_V1(
                        pCtxSmb1,
                        pSession,
                        pSmbRequest->pHeader->tid,
                        &pTree);
        BAIL_ON_NT_STATUS(ntStatus);

        ntStatus = WireUnmarshallCheckDirectoryRequest(
                        pBuffer,
                        ulBytesAvailable,
                        ulOffset,
                        &pRequestHeader,
                        &pwszPathFragment);
        BAIL_ON_NT_STATUS(ntStatus);

        if (!pwszPathFragment || !*pwszPathFragment)
        {
            ntStatus = STATUS_INVALID_PARAMETER;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        ntStatus = SrvBuildCheckdirState(
                        pRequestHeader,
                        pwszPathFragment,
                        &pCheckdirState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb1->hState = pCheckdirState;
        InterlockedIncrement(&pCheckdirState->refCount);
        pCtxSmb1->pfnStateRelease = &SrvReleaseCheckdirStateHandle;
    }

    LWIO_LOCK_MUTEX(bInLock, &pCheckdirState->mutex);

    switch (pCheckdirState->stage)
    {
        case SRV_CHECKDIR_STAGE_SMB_V1_INITIAL:

            SRV_LOG_CALL_DEBUG(
                    pExecContext->pLogContext,
                    SMB_PROTOCOL_VERSION_1,
                    pCtxSmb1->pRequests[pCtxSmb1->iMsg].pHeader->command,
                    &SrvLogCheckDirState_SMB_V1,
                    pCheckdirState);

            ntStatus = SrvBuildTreeRelativePath(
                            pCtxSmb1->pTree,
                            pCheckdirState->pwszPathFragment,
                            &pCheckdirState->fileName);
            BAIL_ON_NT_STATUS(ntStatus);

            pCheckdirState->stage = SRV_CHECKDIR_STAGE_SMB_V1_ATTEMPT_CHECK;

            // Intentional fall through

        case SRV_CHECKDIR_STAGE_SMB_V1_ATTEMPT_CHECK:

            // Catch failed CreateFile calls when they come back around

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

            if (!pCheckdirState->hFile)
            {
                SrvPrepareCheckdirStateAsync(pCheckdirState, pExecContext);

                ntStatus = SrvIoCreateFile(
                                pCtxSmb1->pTree->pShareInfo,
                                &pCheckdirState->hFile,
                                pCheckdirState->pAcb,
                                &pCheckdirState->ioStatusBlock,
                                pCtxSmb1->pSession->pIoSecurityContext,
                                &pCheckdirState->fileName,
                                pCheckdirState->pSecurityDescriptor,
                                pCheckdirState->pSecurityQOS,
                                FILE_LIST_DIRECTORY,
                                0, /* allocation size */
                                FILE_ATTRIBUTE_NORMAL,
                                FILE_SHARE_READ|FILE_SHARE_WRITE,
                                FILE_OPEN,
                                FILE_DIRECTORY_FILE,
                                NULL, /* EA Buffer */
                                0,    /* EA Length */
                                pCheckdirState->pEcpList);
                BAIL_ON_NT_STATUS(ntStatus);

                SrvReleaseCheckdirStateAsync(pCheckdirState); // completed sync
            }

            pCheckdirState->stage = SRV_CHECKDIR_STAGE_SMB_V1_BUILD_RESPONSE;

            // intentional fall through

        case SRV_CHECKDIR_STAGE_SMB_V1_BUILD_RESPONSE:

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

            ntStatus = SrvBuildCheckDirectoryResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pCheckdirState->stage = SRV_CHECKDIR_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_CHECKDIR_STAGE_SMB_V1_DONE:

            break;
    }

cleanup:

    if (pTree)
    {
        SrvTreeRelease(pTree);
    }

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

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

        SrvReleaseCheckdirState(pCheckdirState);
    }

    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 (pCheckdirState)
            {
                SrvReleaseCheckdirStateAsync(pCheckdirState);
            }

            break;
    }

    goto cleanup;
}
Esempio n. 7
0
static
VOID
SrvFreeDeleteState(
    PSRV_DELETE_STATE_SMB_V1 pDeleteState
    )
{
    if (pDeleteState->pAcb && pDeleteState->pAcb->AsyncCancelContext)
    {
        IoDereferenceAsyncCancelContext(
                &pDeleteState->pAcb->AsyncCancelContext);
    }

    if (pDeleteState->pEcpList)
    {
        IoRtlEcpListFree(&pDeleteState->pEcpList);
    }

    if (pDeleteState->hSearchSpace)
    {
        NTSTATUS ntStatus2 = 0;

        ntStatus2 = SrvFinderCloseSearchSpace(
                        pDeleteState->pSession->hFinderRepository,
                        pDeleteState->usSearchId);
        if (ntStatus2)
        {
            LWIO_LOG_ERROR("Failed to close search space [Id:%d][code:%d]",
                          pDeleteState->usSearchId,
                          ntStatus2);
        }

        SrvFinderReleaseSearchSpace(pDeleteState->hSearchSpace);
    }

    if (pDeleteState->pTree)
    {
        SrvTreeRelease(pDeleteState->pTree);
    }

    if (pDeleteState->pSession)
    {
        SrvSessionRelease(pDeleteState->pSession);
    }

    if (pDeleteState->pwszFilesystemPath)
    {
        SrvFreeMemory(pDeleteState->pwszFilesystemPath);
    }

    if (pDeleteState->pwszSearchPattern2)
    {
        SrvFreeMemory(pDeleteState->pwszSearchPattern2);
    }

    if (pDeleteState->hFile)
    {
        IoCloseFile(pDeleteState->hFile);
    }

    if (pDeleteState->pData)
    {
        SrvFreeMemory(pDeleteState->pData);
    }

    SRV_FREE_UNICODE_STRING(&pDeleteState->fileName.Name);

    if (pDeleteState->pMutex)
    {
        pthread_mutex_destroy(&pDeleteState->mutex);
    }

    SrvFreeMemory(pDeleteState);
}