예제 #1
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;
}
예제 #2
0
static
NTSTATUS
SrvQueryFileOpenInformation(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus = 0;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PSRV_OPEN_STATE_SMB_V1     pOpenState = NULL;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;

    if (!IoRtlEcpListIsAcknowledged(
            pOpenState->pEcpList,
            SRV_ECP_TYPE_NET_OPEN_INFO))
    {
        if (!pOpenState->pNetworkOpenInfo)
        {
            pOpenState->pNetworkOpenInfo = &pOpenState->networkOpenInfo;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = IoQueryInformationFile(
                            pOpenState->pFile->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pOpenState->pNetworkOpenInfo,
                            sizeof(pOpenState->networkOpenInfo),
                            FileNetworkOpenInformation);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
        }
    }
    else
    {
        pOpenState->pNetworkOpenInfo = &pOpenState->networkOpenInfo;
    }

    if (!(pOpenState->pNetworkOpenInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
    {
        SrvFileBlockIdleTimeout(pOpenState->pFile);
    }
    else
    {
        SrvFileUnblockIdleTimeout(pOpenState->pFile);
    }

    if (SrvTreeIsNamedPipe(pOpenState->pTree))
    {
        if (!IoRtlEcpListIsAcknowledged(
                    pOpenState->pEcpList,
                    SRV_ECP_TYPE_PIPE_INFO))
        {
            if (!pOpenState->pFilePipeInfo)
            {
                pOpenState->pFilePipeInfo = &pOpenState->filePipeInfo;

                SrvPrepareOpenStateAsync(pOpenState, pExecContext);

                ntStatus = IoQueryInformationFile(
                                pOpenState->pFile->hFile,
                                pOpenState->pAcb,
                                &pOpenState->ioStatusBlock,
                                pOpenState->pFilePipeInfo,
                                sizeof(pOpenState->filePipeInfo),
                                FilePipeInformation);
                BAIL_ON_NT_STATUS(ntStatus);

                SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
            }
        }
        else
        {
            pOpenState->pFilePipeInfo = &pOpenState->filePipeInfo;
        }

        if (!IoRtlEcpListIsAcknowledged(
                    pOpenState->pEcpList,
                    SRV_ECP_TYPE_PIPE_LOCAL_INFO))
        {
            if (!pOpenState->pFilePipeLocalInfo)
            {
                pOpenState->pFilePipeLocalInfo = &pOpenState->filePipeLocalInfo;

                SrvPrepareOpenStateAsync(pOpenState, pExecContext);

                ntStatus = IoQueryInformationFile(
                                pOpenState->pFile->hFile,
                                pOpenState->pAcb,
                                &pOpenState->ioStatusBlock,
                                pOpenState->pFilePipeLocalInfo,
                                sizeof(pOpenState->filePipeLocalInfo),
                                FilePipeLocalInformation);
                BAIL_ON_NT_STATUS(ntStatus);

                SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
            }
        }
        else
        {
            pOpenState->pFilePipeLocalInfo = &pOpenState->filePipeLocalInfo;
        }
    }

cleanup:

    return ntStatus;

error:

    goto cleanup;
}
예제 #3
0
static
NTSTATUS
SrvQueryFileOpenInformation(
    PSRV_EXEC_CONTEXT pExecContext
    )
{
    NTSTATUS                   ntStatus = 0;
    PSRV_PROTOCOL_EXEC_CONTEXT pCtxProtocol = pExecContext->pProtocolContext;
    PSRV_EXEC_CONTEXT_SMB_V1   pCtxSmb1     = pCtxProtocol->pSmb1Context;
    PSRV_OPEN_STATE_SMB_V1     pOpenState = NULL;

    pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState;

    if (!pOpenState->pFileBasicInfo)
    {
        pOpenState->pFileBasicInfo = &pOpenState->fileBasicInfo;

        SrvPrepareOpenStateAsync(pOpenState, pExecContext);

        ntStatus = IoQueryInformationFile(
                        pOpenState->pFile->hFile,
                        pOpenState->pAcb,
                        &pOpenState->ioStatusBlock,
                        pOpenState->pFileBasicInfo,
                        sizeof(pOpenState->fileBasicInfo),
                        FileBasicInformation);
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
    }

    if (!pOpenState->pFileStdInfo)
    {
        pOpenState->pFileStdInfo = &pOpenState->fileStdInfo;

        SrvPrepareOpenStateAsync(pOpenState, pExecContext);

        ntStatus = IoQueryInformationFile(
                        pOpenState->pFile->hFile,
                        pOpenState->pAcb,
                        &pOpenState->ioStatusBlock,
                        pOpenState->pFileStdInfo,
                        sizeof(pOpenState->fileStdInfo),
                        FileStandardInformation);
        BAIL_ON_NT_STATUS(ntStatus);

        SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
    }

    if (SrvTreeIsNamedPipe(pOpenState->pTree))
    {
        if (!pOpenState->pFilePipeInfo)
        {
            pOpenState->pFilePipeInfo = &pOpenState->filePipeInfo;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = IoQueryInformationFile(
                            pOpenState->pFile->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pOpenState->pFilePipeInfo,
                            sizeof(pOpenState->filePipeInfo),
                            FilePipeInformation);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
        }

        if (!pOpenState->pFilePipeLocalInfo)
        {
            pOpenState->pFilePipeLocalInfo = &pOpenState->filePipeLocalInfo;

            SrvPrepareOpenStateAsync(pOpenState, pExecContext);

            ntStatus = IoQueryInformationFile(
                            pOpenState->pFile->hFile,
                            pOpenState->pAcb,
                            &pOpenState->ioStatusBlock,
                            pOpenState->pFilePipeLocalInfo,
                            sizeof(pOpenState->filePipeLocalInfo),
                            FilePipeLocalInformation);
            BAIL_ON_NT_STATUS(ntStatus);

            SrvReleaseOpenStateAsync(pOpenState); // completed synchronously
        }
    }

cleanup:

    return ntStatus;

error:

    goto cleanup;
}