📄 tcptransport.cpp
字号:
goto PacketReadyToSend;
} else {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCP -- reading SMB TCP failed!! closing connection")));
hr = E_FAIL;
goto Done;
}
}
//
// Special case keep alives -- there is no reason to wake up the Cracker
// for these. (keep alive is opeation 0x85)
if(pHeader[0] == 0x85) {
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-TCPRECV: its a keepalive... dont do anything")));
continue;
} else if (pHeader[0] != 0x00) { //who knows what this is... close up shop
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCPRECV: got a unexpected packet header (%d)"), pHeader[0]));
hr = E_FAIL;
goto Done;
}
//
// Prepare to read the real packet
pHeader[0] = 0;
dwHeader = ntohl(dwHeader);
if(dwHeader > sizeof(pNewPacket->InSMB)) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCPRECV: this packet is too large (%d) for our buffers!! -- drop connection"), dwHeader));
hr = E_OUTOFMEMORY;
goto Done;
}
//
// Read one SMB packet (wait up to 'g_uiTCPTimeoutInSeconds' seconds for this)
if(dwHeader != (DWORD)timed_recv(sSock, (char *)(pNewPacket->InSMB), dwHeader, 0, g_uiTCPTimeoutInSeconds, &fTimedOut)) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCP -- reading SMB TCP packet of %d bytes timed out!! -- closing connection"), dwHeader));
hr = E_FAIL;
goto Done;
}
//
// Set packet fields that are specific to 'normal' packets only
IFDBG(pNewPacket->PerfStartTimer());
pNewPacket->uiPacketType = SMB_NORMAL_PACKET;
pNewPacket->pInSMB = (SMB_HEADER *)pNewPacket->InSMB;
pNewPacket->uiInSize = dwHeader;
PacketReadyToSend:
//
// Give the cracker a reference (will be dec'ed by QueueTCPPacketForSend)
IncrementConnectionCounter(pMyConnection);
pNewPacket->pToken = (void *)pMyConnection;
pNewPacket->pOutSMB = NULL;
pNewPacket->uiOutSize = 0;
pNewPacket->pfnQueueFunction = QueueTCPPacketForSend;
pNewPacket->pfnCopyTranportToken = CopyTCPTransportToken;
pNewPacket->pfnDeleteTransportToken = DeleteTCPTransportToken;
//pNewPacket->pfnGetSocketName = TCP_GetSocketName;
pNewPacket->ulConnectionID = ConnectionID;
pNewPacket->dwDelayBeforeSending = 0;
#ifdef DEBUG
pNewPacket->uiPacketNumber = InterlockedIncrement(&SMB_Globals::g_PacketID);
#endif
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-TCPRECV:Got a TCP packet! (%d bytes--id %d)"), dwHeader, pNewPacket->uiPacketNumber));
//hand off the packet to the SMB cracker
if(FAILED(CrackPacket(pNewPacket))) {
//this should *NEVER* happen... Crack should handle its own errors
// and when there is one it should return back an error code to the client
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-TCPRECV: UNEXPECTED ERROR IN CRACK()!")));
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Done;
} else {
pNewPacket = NULL;
}
}
hr = S_OK;
Done:
if(pNewPacket) {
SMB_Globals::g_SMB_Pool.Free(pNewPacket);
pNewPacket = NULL;
}
if(FAILED(hr)) {
closesocket(pMyConnection->sock);
pMyConnection->sock = INVALID_SOCKET;
}
//
// Push a packet into the cracker that kills off anything we might
// have opened
if(TRUE == Cracker::g_fIsRunning) {
//
// Give the cracker a reference (will be dec'ed by QueueTCPPacketForSend)
IncrementConnectionCounter(pMyConnection);
//
// Get some memory out of our free pool
ASSERT(NULL == pNewPacket);
if(NULL == (pNewPacket = SMB_Globals::g_SMB_Pool.Alloc())) {
hr = E_OUTOFMEMORY;
goto Done;
}
if(NULL != pNewPacket) {
memset(pNewPacket, 0, sizeof(SMB_PACKET));
pNewPacket->uiPacketType = SMB_CONNECTION_DROPPED;
pNewPacket->ulConnectionID = ConnectionID;
pNewPacket->pToken = (void *)pMyConnection;
pNewPacket->pfnQueueFunction = QueueTCPPacketForSend;
pNewPacket->pfnCopyTranportToken = CopyTCPTransportToken;
pNewPacket->pfnDeleteTransportToken = DeleteTCPTransportToken;
//pNewPacket->pfnGetSocketName = TCP_GetSocketName;
pNewPacket->dwDelayBeforeSending = 0;
#ifdef DEBUG
pNewPacket->uiPacketNumber = InterlockedIncrement(&SMB_Globals::g_PacketID);
#endif
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-TCPRECV: sending out connection dropped for %d"), ConnectionID));
//
// Hand off the packet to the SMB cracker
if(FAILED(CrackPacket(pNewPacket))) {
//this should *NEVER* happen... Crack should handle its own errors
// and when there is one it should return back an error code to the client
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-NBRECV: UNEXPECTED ERROR IN CRACK()!")));
ASSERT(FALSE);
hr = E_UNEXPECTED;
goto Exit;
} else {
pNewPacket = NULL;
}
}
} else {
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-TCPRECV: cracker thread is dead -- just exiting")));
ASSERT(FALSE);
}
Exit:
if(pNewPacket) {
SMB_Globals::g_SMB_Pool.Free(pNewPacket);
pNewPacket = NULL;
}
//
// Dec our threads ref to the connection
DecrementConnectionCounter(pMyConnection);
//
// Give back our id
if(0xFFFF != sConnectionID) {
if(FAILED(g_ConnectionID.RemoveID(sConnectionID))) {
ASSERT(FALSE);
}
}
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-TCPRECV:Exiting thread!")));
TRACEMSG(ZONE_TCPIP, (L"SMBSRV: Removed TCP Connection -- Total Connections: %d", InterlockedDecrement(&TCP_TRANSPORT::g_lAliveSockets)));
return 0;
}
HRESULT TCP_TerminateSession(ULONG ulConnectionID)
{
CCritSection csLock(&TCP_TRANSPORT::g_csLockTCPTransportGlobals);
ce::list<CONNECTION_HOLDER *, TCP_CONNECTION_HLDR_ALLOC>::iterator itConn;
HRESULT hr = E_FAIL;
csLock.Lock();
for(itConn = g_ConnectionList.begin(); itConn != g_ConnectionList.end(); ++itConn) {
CONNECTION_HOLDER *pConn = (*itConn);
CCritSection csConnLock(&pConn->csSockLock);
csConnLock.Lock();
if(ulConnectionID == pConn->ulConnectionID) {
TRACEMSG(ZONE_TCPIP, (L"SMBSRV: TCPTRANS -- terminating connection %d", ulConnectionID));
closesocket(pConn->sock);
hr = S_OK;
goto Done;
}
}
Done:
return hr;
}
HRESULT TCP_GetSocketName(SMB_PACKET *pPacket, struct sockaddr *pSockAddr, int *pNameLen)
{
CONNECTION_HOLDER *pMyConnection = NULL;
HRESULT hr = E_FAIL;
//
// Make sure they (the cracker) have given us memory!
if(NULL == pPacket || NULL == pPacket->pToken) {
ASSERT(FALSE); //internal error -- this should NEVER happen
return E_UNEXPECTED;
}
pMyConnection = (CONNECTION_HOLDER *)pPacket->pToken;
//
// If the connection has dropped delete memory
if(SMB_CONNECTION_DROPPED == pPacket->uiPacketType) {
TRACEMSG(ZONE_TCPIP, (L"TCPIP: connection dropped packet -- deleting memory"));
hr = S_OK;
goto Done;
}
if(0 != getsockname(pMyConnection->sock, pSockAddr, pNameLen)) {
ASSERT(FALSE);
hr = E_FAIL;
}
Done:
return hr;
}
//
// This function is the transport specific callback for transmitting
// packets -- in the event an unrecoverable error occurs, we will
// just shut down the socket -- this is okay because it will
// cause all other transmissions to that socket to fail (there
// could be more in the cracker queue waiting to be sent) -- eventually
// the refcnt for the connection will reach 0 and will be terminated
HRESULT
TCP_TRANSPORT::QueueTCPPacketForSend(SMB_PACKET *pPacket, BOOL fDestruct)
{
HRESULT hr = S_OK;
DWORD dwSendSize;
//char *pDWPtr = NULL;
CONNECTION_HOLDER *pMyConnection = NULL;
//
// Make sure they (the cracker) have given us memory!
if(NULL == pPacket || NULL == pPacket->pToken) {
ASSERT(FALSE); //internal error -- this should NEVER happen
return E_UNEXPECTED;
}
pMyConnection = (CONNECTION_HOLDER *)pPacket->pToken;
EnterCriticalSection(&pMyConnection->csSockLock); //serialize writes!!
TRACEMSG(ZONE_TCPIP, (TEXT("SMBSRV-TCP -- sending response for packet: %d on socket %d"), pPacket->uiPacketNumber, pMyConnection->sock));
//
// If the packet isnt normal just return (dont send data)
if(SMB_NORMAL_PACKET != pPacket->uiPacketType) {
TRACEMSG(ZONE_TCPIP, (L"TCPIP: connection dropped/timed out packet -- deleting memory"));
hr = S_OK;
goto Done;
}
ASSERT(pPacket->uiOutSize <= SMB_Globals::MAX_PACKET_SIZE);
dwSendSize = htonl(pPacket->uiOutSize);
//pDWPtr = (CHAR *)&dwSendSize;
//pDWPtr[0] = 0;
if(TRUE == g_fStopped) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCP -- we have shut down.. dont send the packet")));
hr = E_FAIL;
goto Done;
}
WSABUF myBufs[2];
myBufs[0].len = sizeof(DWORD);
myBufs[0].buf = (CHAR *)&dwSendSize;
myBufs[1].len = pPacket->uiOutSize;
myBufs[1].buf = (CHAR *)pPacket->pOutSMB;
if(FAILED(writeAll_BlockedOverLapped(pMyConnection->sock, pMyConnection->hOverlappedHandle, myBufs, 2))) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCP -- sending SMB header over TCP failed!! closing connection")));
closesocket(pMyConnection->sock);
pMyConnection->sock = INVALID_SOCKET;
hr = E_FAIL;
goto Done;
}
/*if(FAILED(writeAll(pMyConnection->sock, (CHAR *)&dwSendSize, 4))) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCP -- sending SMB header over TCP failed!! closing connection")));
closesocket(pMyConnection->sock);
pMyConnection->sock = INVALID_SOCKET;
hr = E_FAIL;
goto Done;
}
if(FAILED(writeAll(pMyConnection->sock, (char *)pPacket->pOutSMB, pPacket->uiOutSize))) {
TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV-TCP -- sending SMB over TCP failed!! closing connection")));
closesocket(pMyConnection->sock);
pMyConnection->sock = INVALID_SOCKET;
hr = E_FAIL;
goto Done;
}*/
Done:
#ifdef DEBUG
if(SMB_NORMAL_PACKET == pPacket->uiPacketType && pPacket->pInSMB) {
UCHAR SMB = pPacket->pInSMB->Command;
pPacket->PerfStopTimer(SMB);
DWORD dwProcessing = pPacket->TimeProcessing();
CCritSection csLock(&Cracker::g_csPerfLock);
csLock.Lock();
DOUBLE dwNew = (Cracker::g_dblPerfAvePacketTime[SMB] * Cracker::g_dwPerfPacketsProcessed[SMB]);
Cracker::g_dwPerfPacketsProcessed[SMB] ++;
dwNew += dwProcessing;
dwNew /= Cracker::g_dwPerfPacketsProcessed[SMB];
Cracker::g_dblPerfAvePacketTime[SMB] = dwNew;
csLock.UnLock();
}
#endif
if(TRUE == fDestruct) {
SMB_Globals::g_SMB_Pool.Free(pPacket);
}
LeaveCriticalSection(&pMyConnection->csSockLock);
if(TRUE == fDestruct) {
DecrementConnectionCounter(pMyConnection);
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -