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; }
static NTSTATUS SrvMarshallEchoResponse( PSRV_EXEC_CONTEXT pExecContext, PBYTE pEchoBlob, USHORT usEchoBlobLength ) { NTSTATUS ntStatus = 0; 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]; PECHO_RESPONSE_HEADER pResponseHeader = NULL; // Do not free PBYTE pOutBuffer = pSmbResponse->pBuffer; ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable; ULONG ulOffset = 0; USHORT usBytesUsed = 0; ULONG ulTotalBytesUsed = 0; PCSTR pMinEchoBlob = "lwio"; if (!pSmbResponse->ulSerialNum) { ntStatus = SrvMarshalHeader_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_ECHO, STATUS_SUCCESS, TRUE, pExecContext->pConnection->serverProperties.Capabilities, pSmbRequest->pHeader->tid, SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader), pSmbRequest->pHeader->uid, pSmbRequest->pHeader->mid, FALSE, &pSmbResponse->pHeader, &pSmbResponse->pWordCount, &pSmbResponse->pAndXHeader, &pSmbResponse->usHeaderSize); } else { ntStatus = SrvMarshalHeaderAndX_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_ECHO, &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 = 1; if (ulBytesAvailable < sizeof(ECHO_RESPONSE_HEADER)) { ntStatus = STATUS_INVALID_BUFFER_SIZE; BAIL_ON_NT_STATUS(ntStatus); } pResponseHeader = (PECHO_RESPONSE_HEADER)pOutBuffer; pOutBuffer += sizeof(ECHO_RESPONSE_HEADER); ulOffset += sizeof(ECHO_RESPONSE_HEADER); ulBytesAvailable -= sizeof(ECHO_RESPONSE_HEADER); ulTotalBytesUsed += sizeof(ECHO_RESPONSE_HEADER); ntStatus = WireMarshallEchoResponseData( pOutBuffer, ulBytesAvailable, (usEchoBlobLength > 4 ? pEchoBlob : (PBYTE)pMinEchoBlob), (usEchoBlobLength > 4 ? usEchoBlobLength : strlen(pMinEchoBlob)), &usBytesUsed); BAIL_ON_NT_STATUS(ntStatus); pResponseHeader->sequenceNumber = 0; pResponseHeader->byteCount = (USHORT)usBytesUsed; // pOutBuffer += usBytesUsed; // ulOffset += usBytesUsed; // ulBytesAvailable -= usBytesUsed; ulTotalBytesUsed += usBytesUsed; pSmbResponse->ulMessageSize = ulTotalBytesUsed; cleanup: return ntStatus; error: if (ulTotalBytesUsed) { pSmbResponse->pHeader = NULL; pSmbResponse->pAndXHeader = NULL; memset(pSmbResponse->pBuffer, 0, ulTotalBytesUsed); } pSmbResponse->ulMessageSize = 0; goto cleanup; }
NTSTATUS SrvBuildSetInfoResponse( 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]; PBYTE pOutBuffer = pSmbResponse->pBuffer; ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable; ULONG ulOffset = 0; USHORT usBytesUsed = 0; ULONG ulTotalBytesUsed = 0; PUSHORT pSetup = NULL; BYTE setupCount = 0; USHORT usParams = 0; USHORT usDataOffset = 0; USHORT usParameterOffset = 0; if (!pSmbResponse->ulSerialNum) { ntStatus = SrvMarshalHeader_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_TRANSACTION2, STATUS_SUCCESS, TRUE, pConnection->serverProperties.Capabilities, pCtxSmb1->pTree->tid, SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader), pCtxSmb1->pSession->uid, pSmbRequest->pHeader->mid, pConnection->serverProperties.bRequireSecuritySignatures, &pSmbResponse->pHeader, &pSmbResponse->pWordCount, &pSmbResponse->pAndXHeader, &pSmbResponse->usHeaderSize); } else { ntStatus = SrvMarshalHeaderAndX_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_TRANSACTION2, &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 = 10 + setupCount; ntStatus = WireMarshallTransaction2Response( pOutBuffer, ulBytesAvailable, ulOffset, pSetup, setupCount, (PBYTE)&usParams, sizeof(usParams), NULL, 0, &usDataOffset, &usParameterOffset, &usBytesUsed); BAIL_ON_NT_STATUS(ntStatus); // pOutBuffer += usBytesUsed; // ulOffset += usBytesUsed; // ulBytesAvailable -= usBytesUsed; ulTotalBytesUsed += usBytesUsed; pSmbResponse->ulMessageSize = ulTotalBytesUsed; cleanup: return ntStatus; error: if (ulTotalBytesUsed) { pSmbResponse->pHeader = NULL; pSmbResponse->pAndXHeader = NULL; memset(pSmbResponse->pBuffer, 0, ulTotalBytesUsed); } pSmbResponse->ulMessageSize = 0; goto cleanup; }
static NTSTATUS SrvBuildOpenResponse( 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]; POPEN_RESPONSE_HEADER pResponseHeader = NULL; // Do not free PBYTE pOutBuffer = pSmbResponse->pBuffer; ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable; ULONG ulOffset = 0; ULONG ulTotalBytesUsed = 0; PSRV_OPEN_STATE_SMB_V1 pOpenState = NULL; pOpenState = (PSRV_OPEN_STATE_SMB_V1)pCtxSmb1->hState; if (!pSmbResponse->ulSerialNum) { ntStatus = SrvMarshalHeader_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_OPEN_ANDX, STATUS_SUCCESS, TRUE, pConnection->serverProperties.Capabilities, pOpenState->pTree->tid, SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader), pCtxSmb1->pSession->uid, pSmbRequest->pHeader->mid, pConnection->serverProperties.bRequireSecuritySignatures, &pSmbResponse->pHeader, &pSmbResponse->pWordCount, &pSmbResponse->pAndXHeader, &pSmbResponse->usHeaderSize); } else { ntStatus = SrvMarshalHeaderAndX_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_OPEN_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 = 15; if (ulBytesAvailable < sizeof(OPEN_RESPONSE_HEADER)) { ntStatus = STATUS_INVALID_BUFFER_SIZE; BAIL_ON_NT_STATUS(ntStatus); } pResponseHeader = (POPEN_RESPONSE_HEADER)pOutBuffer; // pOutBuffer += sizeof(OPEN_RESPONSE_HEADER); // ulOffset += sizeof(OPEN_RESPONSE_HEADER); // ulBytesAvailable -= sizeof(OPEN_RESPONSE_HEADER); ulTotalBytesUsed += sizeof(OPEN_RESPONSE_HEADER); pResponseHeader->usFid = pOpenState->pFile->fid; pResponseHeader->ulServerFid = pOpenState->pFile->fid; pResponseHeader->usOpenAction = pOpenState->ulCreateAction; switch (pOpenState->ucOplockLevel) { case SMB_OPLOCK_LEVEL_I: // file is opened only by this user at the current time pResponseHeader->usOpenAction |= 0x8000; break; default: pResponseHeader->usOpenAction &= ~0x8000; break; } // TODO: Mirroring this field is close, but probably not exactly correct pResponseHeader->usGrantedAccess = pOpenState->pRequestHeader->usDesiredAccess; pResponseHeader->usFileAttributes = pOpenState->networkOpenInfo.FileAttributes; ntStatus = WireNTTimeToSMBUTime( pOpenState->networkOpenInfo.LastWriteTime, &pResponseHeader->ulLastWriteTime); BAIL_ON_NT_STATUS(ntStatus); pResponseHeader->ulDataSize = SMB_MIN( UINT32_MAX, pOpenState->networkOpenInfo.EndOfFile); if (SrvTreeIsNamedPipe(pOpenState->pTree)) { ntStatus = SrvMarshallPipeInfo( pOpenState->pFilePipeInfo, pOpenState->pFilePipeLocalInfo, &pResponseHeader->usDeviceState); BAIL_ON_NT_STATUS(ntStatus); pResponseHeader->usFileType = (USHORT)pOpenState->filePipeInfo.ReadMode; } else { pResponseHeader->usFileType = 0; pResponseHeader->usDeviceState = 0; } pResponseHeader->usReserved = 0; pResponseHeader->usByteCount = 0; pSmbResponse->ulMessageSize = ulTotalBytesUsed; cleanup: return ntStatus; error: if (ulTotalBytesUsed) { pSmbResponse->pHeader = NULL; pSmbResponse->pAndXHeader = NULL; memset(pSmbResponse->pBuffer, 0, ulTotalBytesUsed); } pSmbResponse->ulMessageSize = 0; goto cleanup; }
static NTSTATUS SrvNotifyBuildExecContext( PSRV_CHANGE_NOTIFY_STATE_SMB_V1 pNotifyState, PSRV_EXEC_CONTEXT* ppExecContext ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = NULL; PSMB_PACKET pSmbRequest = NULL; PBYTE pParams = NULL; ULONG ulParamLength = 0; PBYTE pData = NULL; ULONG ulDataLen = 0; ULONG ulDataOffset = 0; PBYTE pBuffer = NULL; ULONG ulBytesAvailable = 0; ULONG ulOffset = 0; USHORT usBytesUsed = 0; USHORT usTotalBytesUsed = 0; PSMB_HEADER pHeader = NULL; // Do not free PBYTE pWordCount = NULL; // Do not free PANDX_HEADER pAndXHeader = NULL; // Do not free PUSHORT pSetup = NULL; UCHAR ucSetupCount = 0; ULONG ulParameterOffset = 0; ULONG ulNumPackageBytesUsed = 0; SMB_NOTIFY_CHANGE_HEADER notifyRequestHeader = {0}; ntStatus = SMBPacketAllocate( pNotifyState->pConnection->hPacketAllocator, &pSmbRequest); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SMBPacketBufferAllocate( pNotifyState->pConnection->hPacketAllocator, (64 * 1024) + 4096, &pSmbRequest->pRawBuffer, &pSmbRequest->bufferLen); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvInitPacket_SMB_V1(pSmbRequest, TRUE); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvBuildExecContext( pNotifyState->pConnection, pSmbRequest, TRUE, &pExecContext); BAIL_ON_NT_STATUS(ntStatus); pSmbRequest->sequence = pNotifyState->ulRequestSequence; pBuffer = pSmbRequest->pRawBuffer; ulBytesAvailable = pSmbRequest->bufferLen; if (ulBytesAvailable < sizeof(NETBIOS_HEADER)) { ntStatus = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(ntStatus); } pBuffer += sizeof(NETBIOS_HEADER); ulBytesAvailable -= sizeof(NETBIOS_HEADER); ntStatus = SrvMarshalHeader_SMB_V1( pBuffer, ulOffset, ulBytesAvailable, COM_NT_TRANSACT, pNotifyState->ioStatusBlock.Status, FALSE, /* not a response */ pNotifyState->usTid, pNotifyState->ulPid, pNotifyState->usUid, pNotifyState->usMid, pNotifyState->pConnection->serverProperties.bRequireSecuritySignatures, &pHeader, &pWordCount, &pAndXHeader, &usBytesUsed); BAIL_ON_NT_STATUS(ntStatus); pBuffer += usBytesUsed; ulOffset += usBytesUsed; ulBytesAvailable -= usBytesUsed; usTotalBytesUsed += usBytesUsed; notifyRequestHeader.usFid = pNotifyState->usFid; pSetup = (PUSHORT)¬ifyRequestHeader; ucSetupCount = sizeof(notifyRequestHeader)/sizeof(USHORT); *pWordCount = 18 + ucSetupCount; ntStatus = WireMarshallNtTransactionRequest( pBuffer, ulBytesAvailable, ulOffset, SMB_SUB_COMMAND_NT_TRANSACT_NOTIFY_CHANGE, pSetup, ucSetupCount, pParams, ulParamLength, pData, ulDataLen, &ulDataOffset, &ulParameterOffset, &ulNumPackageBytesUsed); BAIL_ON_NT_STATUS(ntStatus); // pBuffer += ulNumPackageBytesUsed; // ulOffset += ulNumPackageBytesUsed; // ulBytesAvailable -= ulNumPackageBytesUsed; usTotalBytesUsed += ulNumPackageBytesUsed; pSmbRequest->bufferUsed += usTotalBytesUsed; ntStatus = SMBPacketMarshallFooter(pSmbRequest); BAIL_ON_NT_STATUS(ntStatus); *ppExecContext = pExecContext; cleanup: if (pSmbRequest) { SMBPacketRelease( pNotifyState->pConnection->hPacketAllocator, pSmbRequest); } return ntStatus; error: *ppExecContext = NULL; if (pExecContext) { SrvReleaseExecContext(pExecContext); } goto cleanup; }
static NTSTATUS SrvBuildRenameResponse( 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]; PSMB_RENAME_RESPONSE_HEADER pResponseHeader = NULL; // Do not free PBYTE pOutBuffer = pSmbResponse->pBuffer; ULONG ulBytesAvailable = pSmbResponse->ulBytesAvailable; ULONG ulOffset = 0; USHORT usBytesUsed = 0; ULONG ulTotalBytesUsed = 0; if (!pSmbResponse->ulSerialNum) { ntStatus = SrvMarshalHeader_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_RENAME, STATUS_SUCCESS, TRUE, pCtxSmb1->pTree->tid, SMB_V1_GET_PROCESS_ID(pSmbRequest->pHeader), pCtxSmb1->pSession->uid, pSmbRequest->pHeader->mid, pConnection->serverProperties.bRequireSecuritySignatures, &pSmbResponse->pHeader, &pSmbResponse->pWordCount, &pSmbResponse->pAndXHeader, &pSmbResponse->usHeaderSize); } else { ntStatus = SrvMarshalHeaderAndX_SMB_V1( pOutBuffer, ulOffset, ulBytesAvailable, COM_RENAME, &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 = 0; ntStatus = WireMarshallRenameResponse( pOutBuffer, ulBytesAvailable, ulOffset, &pResponseHeader, &usBytesUsed); BAIL_ON_NT_STATUS(ntStatus); // pOutBuffer += usBytesUsed; // ulOffset += usBytesUsed; // ulBytesAvailable -= usBytesUsed; ulTotalBytesUsed += usBytesUsed; pResponseHeader->usByteCount = 0; pSmbResponse->ulMessageSize = ulTotalBytesUsed; cleanup: return ntStatus; error: if (ulTotalBytesUsed) { pSmbResponse->pHeader = NULL; pSmbResponse->pAndXHeader = NULL; memset(pSmbResponse->pBuffer, 0, ulTotalBytesUsed); } pSmbResponse->ulMessageSize = 0; goto cleanup; }