Beispiel #1
0
NTSTATUS
SrvProcessTrans2SetPathInformation(
    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_TRANS2_STATE_SMB_V1   pTrans2State = NULL;
    ACCESS_MASK                accessMask   = 0;

    pTrans2State = (PSRV_TRANS2_STATE_SMB_V1)pCtxSmb1->hState;

    switch (pTrans2State->stage)
    {
        case SRV_TRANS2_STAGE_SMB_V1_INITIAL:

            ntStatus = SrvUnmarshallSetPathInfoParams(
                            pTrans2State->pParameters,
                            pTrans2State->pRequestHeader->parameterCount,
                            &pTrans2State->pSmbInfoLevel,
                            &pTrans2State->pwszFilename);
            BAIL_ON_NT_STATUS(ntStatus);

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

            ntStatus = SrvSetStatSessionInfo(
                            pExecContext,
                            pTrans2State->pSession);
            BAIL_ON_NT_STATUS(ntStatus);

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

            ntStatus = SrvBuildTreeRelativePath(
                            pTrans2State->pTree,
                            pTrans2State->pwszFilename,
                            &pTrans2State->fileName);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_CREATE_FILE_COMPLETED;

            SrvPrepareTrans2StateAsync(pTrans2State, pExecContext);

            accessMask = SrvGetPathAccessMask(pExecContext);

            ntStatus = SrvIoCreateFile(
                            pTrans2State->pTree->pShareInfo,
                            &pTrans2State->hFile,
                            pTrans2State->pAcb,
                            &pTrans2State->ioStatusBlock,
                            pTrans2State->pSession->pIoSecurityContext,
                            &pTrans2State->fileName,
                            pTrans2State->pSecurityDescriptor,
                            pTrans2State->pSecurityQOS,
                            accessMask,
                            0,
                            FILE_ATTRIBUTE_NORMAL,
                            FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                            FILE_OPEN,
                            0,
                            NULL, /* EA Buffer */
                            0,    /* EA Length */
                            pTrans2State->pEcpList
                            );
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseTrans2StateAsync(pTrans2State); // completed synchronously

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_CREATE_FILE_COMPLETED:

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_ATTEMPT_IO;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_ATTEMPT_IO:

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

            ntStatus = SrvSetPathInfo(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_IO_COMPLETE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_IO_COMPLETE:

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

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_BUILD_RESPONSE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_BUILD_RESPONSE:

            ntStatus = SrvBuildSetInfoResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_DONE:

            break;

        default:

            ntStatus = STATUS_INTERNAL_ERROR;
            BAIL_ON_NT_STATUS(ntStatus);

            break;
    }

cleanup:

    return ntStatus;

error:

    goto cleanup;
}
Beispiel #2
0
NTSTATUS
SrvProcessTrans2QueryFileInformation(
    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_TRANS2_STATE_SMB_V1   pTrans2State = NULL;

    pTrans2State = (PSRV_TRANS2_STATE_SMB_V1)pCtxSmb1->hState;

    switch (pTrans2State->stage)
    {
        case SRV_TRANS2_STAGE_SMB_V1_INITIAL:

            ntStatus = SrvUnmarshallQueryFileInfoParams(
                            pTrans2State->pParameters,
                            pTrans2State->pRequestHeader->parameterCount,
                            &pTrans2State->usFid,
                            &pTrans2State->pSmbInfoLevel);
            BAIL_ON_NT_STATUS(ntStatus);

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

            ntStatus = SrvSetStatSessionInfo(
                            pExecContext,
                            pTrans2State->pSession);
            BAIL_ON_NT_STATUS(ntStatus);

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

            ntStatus = SrvTreeFindFile_SMB_V1(
                            pCtxSmb1,
                            pTrans2State->pTree,
                            pTrans2State->usFid,
                            &pTrans2State->pFile);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_ATTEMPT_IO;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_ATTEMPT_IO:

            ntStatus = SrvQueryInfo(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_BUILD_RESPONSE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_BUILD_RESPONSE:

            ntStatus = SrvBuildQueryInfoResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pTrans2State->stage = SRV_TRANS2_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_TRANS2_STAGE_SMB_V1_DONE:

            break;

        default:

            ntStatus = STATUS_INTERNAL_ERROR;
            BAIL_ON_NT_STATUS(ntStatus);

            break;
    }

cleanup:

    return ntStatus;

error:

    goto cleanup;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
0
NTSTATUS
SrvProcessDelete(
    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_DELETE_STATE_SMB_V1   pDeleteState = NULL;
    BOOLEAN                    bInLock      = FALSE;

    pDeleteState = (PSRV_DELETE_STATE_SMB_V1)pCtxSmb1->hState;

    if (pDeleteState)
    {
        InterlockedIncrement(&pDeleteState->refCount);
    }
    else
    {
        PBYTE pBuffer          = pSmbRequest->pBuffer + pSmbRequest->usHeaderSize;
        ULONG ulOffset         = pSmbRequest->usHeaderSize;
        ULONG ulBytesAvailable = pSmbRequest->ulMessageSize - pSmbRequest->usHeaderSize;
        PSMB_DELETE_REQUEST_HEADER  pRequestHeader    = NULL; // Do not free
        PWSTR                       pwszSearchPattern = NULL; // Do not free
        BOOLEAN                     bUseLongFilenames = FALSE;

        ntStatus = WireUnmarshallDeleteRequest(
                        pBuffer,
                        ulBytesAvailable,
                        ulOffset,
                        &pRequestHeader,
                        &pwszSearchPattern);
        BAIL_ON_NT_STATUS(ntStatus);

        if (!pwszSearchPattern || !*pwszSearchPattern)
        {
            ntStatus = STATUS_CANNOT_DELETE;
            BAIL_ON_NT_STATUS(ntStatus);
        }

        if (pSmbRequest->pHeader->flags2 & FLAG2_KNOWS_LONG_NAMES)
        {
            bUseLongFilenames = TRUE;
        }

        ntStatus = SrvBuildDeleteState(
                        pRequestHeader,
                        pwszSearchPattern,
                        bUseLongFilenames,
                        &pDeleteState);
        BAIL_ON_NT_STATUS(ntStatus);

        pCtxSmb1->hState = pDeleteState;
        InterlockedIncrement(&pDeleteState->refCount);
        pCtxSmb1->pfnStateRelease = &SrvReleaseDeleteStateHandle;
    }

    LWIO_LOCK_MUTEX(bInLock, &pDeleteState->mutex);

    switch (pDeleteState->stage)
    {
        case SRV_DELETE_STAGE_SMB_V1_INITIAL:

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

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

            ntStatus = SrvSetStatSessionInfo(
                            pExecContext,
                            pDeleteState->pSession);
            BAIL_ON_NT_STATUS(ntStatus);

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

            ntStatus = SrvFinderBuildSearchPath(
                            NULL,
                            pDeleteState->pwszSearchPattern,
                            &pDeleteState->pwszFilesystemPath,
                            &pDeleteState->pwszSearchPattern2,
                            &pDeleteState->bPathHasWildCards);
            BAIL_ON_NT_STATUS(ntStatus);

            // Need to treat as wildcard if either one of hidden or system
            // was not specified.
            if (!(IsSetFlag(pDeleteState->usSearchAttributes, SMB_FILE_ATTRIBUTE_HIDDEN) &&
                  IsSetFlag(pDeleteState->usSearchAttributes, SMB_FILE_ATTRIBUTE_SYSTEM)))
            {
                pDeleteState->bNeedSearchAttributes = TRUE;
            }

            if (pDeleteState->bPathHasWildCards || pDeleteState->bNeedSearchAttributes)
            {
                SMB_FILE_ATTRIBUTES usSearchAttributes = pDeleteState->usSearchAttributes;

                // Only the hidden and system inclusive attributes are
                // consulted for delete -- except that, apparently,
                // SMB_FILE_ATTRIBUTE_DIRECTORY can also be used, but will
                // result in an error.
                usSearchAttributes &= SMB_FILE_ATTRIBUTE_HIDDEN | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_DIRECTORY;

                ntStatus = SrvFinderCreateSearchSpace(
                                pDeleteState->pTree->hFile,
                                pDeleteState->pTree->pShareInfo,
                                pDeleteState->pSession->pIoSecurityContext,
                                pDeleteState->pSession->hFinderRepository,
                                pDeleteState->pwszFilesystemPath,
                                pDeleteState->pwszSearchPattern2,
                                usSearchAttributes,
                                0,
                                0, // ulSearchStorageType
                                SMB_FIND_FILE_BOTH_DIRECTORY_INFO,
                                pDeleteState->bUseLongFilenames,
                                FILE_LIST_DIRECTORY,
                                &pDeleteState->hSearchSpace,
                                &pDeleteState->usSearchId);
                BAIL_ON_NT_STATUS(ntStatus);
            }

            pDeleteState->stage = SRV_DELETE_STAGE_SMB_V1_DELETE_FILES;

            // intentional fall through

        case SRV_DELETE_STAGE_SMB_V1_DELETE_FILES:

            if (pDeleteState->hSearchSpace)
            {
                ntStatus = SrvDeleteFiles(pExecContext);
            }
            else
            {
                ntStatus = SrvDeleteSingleFile(pExecContext);
            }
            BAIL_ON_NT_STATUS(ntStatus);

            pDeleteState->stage = SRV_DELETE_STAGE_SMB_V1_BUILD_RESPONSE;

            // intentional fall through

        case SRV_DELETE_STAGE_SMB_V1_BUILD_RESPONSE:

            ntStatus = SrvBuildDeleteResponse(pExecContext);
            BAIL_ON_NT_STATUS(ntStatus);

            pDeleteState->stage = SRV_DELETE_STAGE_SMB_V1_DONE;

            // intentional fall through

        case SRV_DELETE_STAGE_SMB_V1_DONE:

            break;
    }

cleanup:

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

        SrvReleaseDeleteState(pDeleteState);
    }

    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 (pDeleteState)
            {
                SrvReleaseDeleteStateAsync(pDeleteState);
            }

            break;
    }

    goto cleanup;
}