📄 xtunnelsservermain.cpp
字号:
#endif //DEBUG sQuitReason = kDisconnectReasonMustClose; sQuitMessage = sMessageDataTooLarge; return 1; } // extract packed data unsigned long ulClientSessionKeySize = XT2HOST16(*(unsigned short*)&packet->m_tData.challengereply.challengereplyblob[blobsize]); if (ulClientSessionKeySize > EMaxSmallBufferSize) {#if DEBUG cout << "X-Tunnels: HandleMessageChallengeReply found too big (" << ulClientSessionKeySize << " ) encryption key!!" << endl;#endif //DEBUG sQuitReason = kDisconnectReasonMustClose; sQuitMessage = sMessageDataTooLarge; return 1; } char szClientSessionKey[EMaxSmallBufferSize]; if (ulClientSessionKeySize) {#if DEBUG cout << "X-Tunnels: HandleMessageChallengeReply received encryption session key, current set encryption algorithm is " << sServerPacketEncryption << endl;#endif //DEBUG memcpy(szClientSessionKey, &packet->m_tData.challengereply.challengereplyblob[blobsize + sizeof(unsigned short)], ulClientSessionKeySize); ChildData()->MakeClientDecryptionKey(ulClientSessionKeySize, szClientSessionKey); } else { sServerPacketEncryption = EAlgorithm_None; ChildData()->MakeClientDecryptionKey(0, NULL); } // check that client's authentication is ok if (ChildData()->m_szCachedUserID) { bool isOK = ChildData()->CheckServerChallengeBlob(blobsize, packet->m_tData.challengereply.challengereplyblob);#if DEBUG cout << "X-Tunnels: HandleMessageChallengeReply called CheckClientChallengeBlob with " << blobsize << " bytes and got " << (isOK ? "true" : "false") << endl;#endif //DEBUG if (!isOK) { sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = g_szMessageAuthenticationFailed; return 1; } } // we create a unique encryption key char szServerSessionKey[EMaxSmallBufferSize] = { 0 }; unsigned long ulServerSessionKeySize = 0; uuid_t tUniqueKey; FillWithRandomLongs(&tUniqueKey, sizeof(tUniqueKey)); GetUUIDString((uuid_t*)&tUniqueKey, szServerSessionKey); ulServerSessionKeySize = strlen(szServerSessionKey); ChildData()->MakeServerEncryptionKey(ulServerSessionKeySize, szServerSessionKey); // return answer to client's challenge char clientchallengeblobdata[ChallengeReplyParam::kMaxChallengeReplyBlobSize]; unsigned long clientchallengeblobsize = 0; ChildData()->GetClientChallengeBlob(clientchallengeblobsize, clientchallengeblobdata); packet->m_tHeaderBasic.commandid = HOST2XT32(EMessageChallengeReply); blobsize = sizeof(unsigned long) + clientchallengeblobsize; unsigned long keysize = sizeof(unsigned short) + ulServerSessionKeySize; unsigned long packetsize = blobsize + keysize; packet->m_tHeaderBasic.payloadsize = HOST2XT32(packetsize); packet->m_tData.challengereply.challengereplyblobsize = HOST2XT32(clientchallengeblobsize); memcpy(&packet->m_tData.challengereply.challengereplyblob, clientchallengeblobdata, clientchallengeblobsize); long offset = clientchallengeblobsize; // pack key size and data directly after blob for sending *(unsigned short *)&packet->m_tData.challengereply.challengereplyblob[offset] = HOST2XT16(ulServerSessionKeySize); offset += sizeof(unsigned short); memcpy(&packet->m_tData.challengereply.challengereplyblob[offset], szServerSessionKey, ulServerSessionKeySize); // now that it's packed, send it if (ChildData()->SendPacketToClient(packet, packetsize, false)) return 1;#if DEBUG cout << "X-Tunnels: HandleMessageChallengeReply succeeded, sent " << packet->m_tData.challengereply.challengereplyblobsize << " byte reply " << GetUUIDString((uuid_t*)packet->m_tData.challengereply.challengereplyblob, NULL) << endl;#endif //DEBUG return 0; }int HandleMessageDisconnect(TXTunnelsPacket* packet) { packet->m_tData.disconnect.messagesize = HOST2XT16(packet->m_tData.disconnect.messagesize);#if DEBUG cout << "X-Tunnels: HandleMessageDisconnect got reason " << XT2HOST32(packet->m_tData.disconnect.reason) << endl; int expectedMessageSize = packet->m_tHeaderBasic.payloadsize - 6; if (packet->m_tData.disconnect.messagesize != expectedMessageSize) cout << "X-Tunnels: HandleMessageDisconnect expected string size " << expectedMessageSize << " but got " << packet->m_tData.disconnect.messagesize << endl;#endif //DEBUG // there's no trailing NUL packet->m_tData.disconnect.message[packet->m_tData.disconnect.messagesize] = 0;#if DEBUG cout << "X-Tunnels: HandleMessageDisconnect got string of size " << packet->m_tData.disconnect.messagesize << ": " << packet->m_tData.disconnect.message << endl;#endif //DEBUG // reply politely SendGoodbyePacket(sClientTCPSocket, kDisconnectReasonNormal, sMessagePoliteGoodbye, true);#if DEBUG cout << "X-Tunnels: HandleMessageDisconnect succeeded" << endl;#endif //DEBUG return 0; }int HandleMessageClientHello(TXTunnelsPacket* packet) { packet->m_tData.clienthello.how = XT2HOST32(packet->m_tData.clienthello.how); long namesize = packet->m_tData.clienthello.useridsize = XT2HOST16(packet->m_tData.clienthello.useridsize); if (namesize > (long)EMaxDBUsernameLength) {#if DEBUG cout << "X-Tunnels: HandleMessageClientHello got unacceptable " << namesize << " name size" << endl;#endif //DEBUG sQuitReason = kDisconnectReasonMustClose; sQuitMessage = sMessageDataTooLarge; return 1; } // extract packed host long offset = namesize; unsigned short hostsize = XT2HOST16(*(unsigned short*)&packet->m_tData.clienthello.m_szUserID[offset]); if (hostsize > (unsigned short)EMaxDBHostLength) {#if DEBUG cout << "X-Tunnels: HandleMessageClientHello got unacceptable " << hostsize << " host size" << endl;#endif //DEBUG sQuitReason = kDisconnectReasonMustClose; sQuitMessage = sMessageDataTooLarge; return 1; } offset += sizeof(hostsize); char* szUserHost = &packet->m_tData.clienthello.m_szUserID[offset]; // extract packed post host data offset = hostsize; uuid_t sessionuuid; memcpy(&sessionuuid, &szUserHost[offset], sizeof(sessionuuid)); offset += sizeof(sessionuuid); unsigned long algorithm = XT2HOST32(*(unsigned long*)&szUserHost[offset]); offset += sizeof(unsigned long); unsigned long desiredtimeout = XT2HOST32(*(unsigned long*)&szUserHost[offset]); offset += sizeof(unsigned long); unsigned long challengeblobsize = XT2HOST32(*(unsigned long*)&szUserHost[offset]); offset += sizeof(unsigned long); char *challengeblob = &szUserHost[offset]; // no trailing NULs packet->m_tData.clienthello.m_szUserID[namesize] = 0; szUserHost[hostsize] = 0;#if DEBUG cout << "X-Tunnels: HandleMessageClientHello packet { how = " << packet->m_tData.clienthello.how << ", '" << packet->m_tData.clienthello.m_szUserID << "@" << szUserHost << "', sessionid " << GetUUIDString((uuid_t*)&sessionuuid, NULL) << ", algorithm = " << algorithm << ", timeout = " << desiredtimeout << ", <challengeblob> size = " << challengeblobsize << " }" << endl;#endif //DEBUG // handle the settings we read if (desiredtimeout < g_ulChildDeathwatchTimeout) if (desiredtimeout != EUseDefaultDeathwatchTimeOut) g_ulChildDeathwatchTimeout = desiredtimeout; // HandleMessageClientReady will want to pipe this to parent strncpy(g_tCurrentChildInfo.m_szHost, szUserHost, EMaxDBHostLength); switch (packet->m_tData.clienthello.how) { case ELoginAnonymous: sReopenSession = false; bzero(&sRequestedSession, sizeof(sRequestedSession)); delete ChildData()->m_szCachedUserID; ChildData()->m_szCachedUserID = NULL; delete ChildData()->m_szCachedHost; ChildData()->m_szCachedHost = NULL; if (VerifyConnectingIPRejected(szUserHost)) { sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = g_szMessageIPRejected;#if DEBUG cout << "X-Tunnels: host " << szUserHost << " rules rejected IP of anonymous login" << endl;#endif //DEBUG return 1; } if (!VerifyConnectingIPAllowedAnonymously(szUserHost)) { sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = g_szMessageNoAnonymousLogin;#if DEBUG cout << "X-Tunnels: host " << szUserHost << " rules did not allow IP of anonymous login" << endl;#endif //DEBUG return 1; }#if ENFORCE_ANONYMOUS_HOST_LIMITS g_iHostMax = VerifyAccountExistsAndConnectionAvailable("", szUserHost); // < 1 return means no account exists on that host with that name if (g_iHostMax < 1) { sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = g_szMessageBadAnonymousHost;#if DEBUG cout << "X-Tunnels: host " << szUserHost << " rules rejected attempted anonymous connection" << endl;#endif //DEBUG return 1; }#endif // ENFORCE_ANONYMOUS_HOST_LIMITS break; case ELoginNamePassword: { if (VerifyConnectingIPRejected(szUserHost)) { sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = g_szMessageIPRejected;#if DEBUG cout << "X-Tunnels: host " << szUserHost << " rules rejected IP of non-anonymous login" << endl;#endif //DEBUG return 1; } if (!VerifyConnectingIPAllowed(szUserHost)) { sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = g_szMessageBadAddress;#if DEBUG cout << "X-Tunnels: host " << szUserHost << " rules rejected IP of attempted connection" << endl;#endif //DEBUG return 1; } sReopenSession = false; bzero(&sRequestedSession, sizeof(sRequestedSession)); g_iHostMax = VerifyAccountExistsAndConnectionAvailable(packet->m_tData.clienthello.m_szUserID, szUserHost); // < 1 return means no account exists on that host with that name if (g_iHostMax < 1) { sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = g_szMessageBadUser;#if DEBUG cout << "X-Tunnels: host " << szUserHost << " rules rejected username of attempted connection" << endl;#endif //DEBUG return 1; } } break; case ELoginSessionID: sReopenSession = true; delete ChildData()->m_szCachedUserID; ChildData()->m_szCachedUserID = NULL; delete ChildData()->m_szCachedHost; ChildData()->m_szCachedHost = NULL; memcpy(&sRequestedSession, &sessionuuid, sizeof(sRequestedSession)); break; default:#if DEBUG cout << "X-Tunnels: HandleMessageClientHello got unknown login method " << packet->m_tData.clienthello.how << endl;#endif //DEBUG sQuitReason = kDisconnectReasonWrongVersion | EDisconnectDelayFlag; sQuitMessage = sMessageBadLogin; return 1; } uuid_t serverchallengeblobdata; FillWithRandomLongs(&serverchallengeblobdata, sizeof(serverchallengeblobdata)); unsigned long serverchallengeblobsize = sizeof(serverchallengeblobdata); switch (algorithm) { case EAlgorithm_None: // only allowed for anonymous login if (sReopenSession || ChildData()->m_szCachedUserID) {#if DEBUG cout << "Client attempted named login without encryption" << endl;#endif //DEBUG sQuitReason = kDisconnectReasonAuthenticationFailed | EDisconnectDelayFlag; sQuitMessage = sMessageMustAuthenticate; return 1; } break; case EAlgorithm_MD5: case EAlgorithm_SHA1: // will use password cached in VerifyAccount() above ChildData()->m_ulKeyEncryptionType = algorithm; ChildData()->MakeClientChallengeBlob(challengeblobsize, challengeblob); ChildData()->MakeServerChallengeBlob(serverchallengeblobsize, reinterpret_cast<char*>(&serverchallengeblobdata)); break; case EAlgorithm_Triple_DES: case EAlgorithm_AES_128_Bits: case EAlgorithm_AES_192_Bits: case EAlgorithm_AES_256_Bits: default:#if DEBUG cout << "X-Tunnels: HandleMessageClientHello got unimplemented authentication encryption method " << algorithm << endl;#endif //DEBUG sQuitReason = kDisconnectReasonWrongVersion; sQuitMessage = sMessageBadEncryption; return 1; } // send our version back packet->m_tHeaderBasic.commandid = HOST2XT32(EMessageVersion); long packetsize = sizeof(TVersionParam); packet->m_tHeaderBasic.payloadsize = HOST2XT32(packetsize); packet->m_tData.m_tVersion.m_byProtocolMajor = ECurrentProtocolMajorVersion; packet->m_tData.m_tVersion.m_byProtocolMinor = ECurrentProtocolMinorVersion; packet->m_tData.m_tVersion.m_wVersionID = HOST2XT16(ECurrentServerVersion); if (ChildData()->SendPacketToClient(packet, packetsize, false)) return 1; // send a challenge too packet->m_tHeaderBasic.commandid = HOST2XT32(EMessageServerChallenge); packetsize = sizeof(unsigned long) + sizeof(unsigned long) + serverchallengeblobsize; packet->m_tHeaderBasic.payloadsize = HOST2XT32(packetsize); packet->m_tData.serverchallenge.algorithm = HOST2XT32(algorithm); packet->m_tData.serverchallenge.challengeblobsize = HOST2XT32(serverchallengeblobsize); memcpy(&packet->m_tData.serverchallenge.challengeblob, &serverchallengeblobdata, serverchallengeblobsize); if (ChildData()->SendPacketToClient(packet, packetsize, false)) return 1; #if DEBUG cout << "X-Tunnels: HandleMessageClientHello succeeded, sent version and challenge back " << endl;#endif //DEBUG return 0; }int OpenUDPSocket(int& outNewSocket, u_port_t& outNewPort) // 0 means request refused { long attempts = 0; do { attempts++; // we'll pick port from 5000 - 65000 u_port_t tryPort = rand() % 60000 + 5000; outNewSocket = u_openudp(tryPort); if (outNewSocket != -1) { if (-1 == setnonblock(outNewSocket)) // UDP ports are nonblocking {#if DEBUG cout << "X-Tunnels: OpenUDPSocket couldn't set outNewSocket nonblocking!" << endl;#endif //DEBUG } outNewPort = tryPort; pair<long, long> newMapping(tryPort, outNewSocket); pair<map<long, long>::iterator, bool> p = g_cUDPPorts.insert(newMapping); g_ulActiveSinglePorts++; if (!p.second) {#if DEBUG cout << "X-Tunnels: OpenUDPSocket found new port already listed as active!" << endl;#endif //DEBUG } } } while (!outNewPort && (attempts < 1500)); return 0 != outNewPort; }int HandleMessageClientReady(TXTunnelsPacket* packet) { if (packet->m_tHeaderBasic.payloadsize != 0 /*sizeof(ClientReadyParam)*/) // sizeof(ClientReadyParam) is 1! {#if DEBUG cout << "X-Tunnels: HandleMessageClientReady expects packetsize " << 0 /*sizeof(ClientReadyParam)*/ << " but packet claims " << packet->m_tHeaderBasic.payloadsize << endl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -