📄 xtunnelsauthentication.cpp
字号:
tTraffic.m_ulIncomingTraffic = ulPacketSize; tTraffic.m_ulOutgoingTraffic = 0; pair<unsigned long, TDestinationTraffic> cNewEntry(ulDestinationIP, tTraffic); g_cDestinationIPs.insert(cNewEntry); return false; } bool VerifyDestinationIPAllowedAndLogOutgoingTraffic( unsigned long ulDestinationIP, const char* szHost, unsigned long ulPacketSize ) { // always true if no active database if (!g_pDBConnection) return true; // this is called for every packet, so we'll cache requests //map<unsigned long, unsigned long>::iterator pIter = g_cDestinationIPs.find(ulDestinationIP); map<unsigned long, TDestinationTraffic>::iterator pIter = g_cDestinationIPs.find(ulDestinationIP); if (pIter != g_cDestinationIPs.end()) { pIter->second.m_ulOutgoingTraffic += ulPacketSize; return true; } // ok, we need to find it -- absence of any rules is also true though bool bAllowed = true; for (vector<THostRule>::const_iterator iter = g_cHostDestinationRules.begin(); iter != g_cHostDestinationRules.end(); ++iter) { if (strcmp(iter->m_szHost, szHost)) continue; bAllowed = IsIPInRange(ulDestinationIP, iter->m_ulFromIP, iter->m_ulToIP); if (bAllowed) break; } if (bAllowed) { //pair<unsigned long, unsigned long> cNewEntry(ulDestinationIP, ulPacketSize); TDestinationTraffic tTraffic; tTraffic.m_ulIncomingTraffic = 0; tTraffic.m_ulOutgoingTraffic = ulPacketSize; pair<unsigned long, TDestinationTraffic> cNewEntry(ulDestinationIP, tTraffic); g_cDestinationIPs.insert(cNewEntry); } return bAllowed; }bool VerifyConnectingIPAllowed(const char* szHost) { // assume that g_tConnectedClientsIP was set in an earlier call to VerifyConnectingIPAllowed() return VerifyConnectingIPIsPermitted(g_tConnectedClientsIP, szHost, false); } bool VerifyConnectingIPRejected(const char* szHost) { // assume that g_tConnectedClientsIP was set in an earlier call to VerifyConnectingIPAllowed() return VerifyConnectingIPIsRejected(g_tConnectedClientsIP, szHost); } bool VerifyConnectingIPAllowedAnonymously(const char* szHost) { // assume that g_tConnectedClientsIP was set in an earlier call to VerifyConnectingIPAllowed() return VerifyConnectingIPIsPermitted(g_tConnectedClientsIP, szHost, true); }// this ought to be a redundant check if host OS allows binding listen socket to localhost, but OS X for instance apparently does notbool VerifyConnectingIPIsLocalhost(int inAttemptingSocket) { struct sockaddr_in attempter = { 0 }; if (GetPeerFromSocket(inAttemptingSocket, &attempter, NULL)) return false;#if DEBUG cout << "X-Tunnels: VerifyConnectingIPIsLocalhost asked to verify socket IP " << inet_ntoa(attempter.sin_addr) << " " << endl;#endif //DEBUG return 0 == strcmp(inet_ntoa(attempter.sin_addr), "127.0.0.1"); } int VerifyAccountExistsAndConnectionAvailable(const char* inName, const char* inHost) { // MRU 1000-entry cache of account host/name/hostmax/password enum { EAccountCacheSize = 1000 }; typedef struct { char* m_szHost; char* m_szUserID; int m_iHostMax; // -1 for 'host/id did not exist' char* m_szPassword; time_t m_tLastAccess; } TAccountCache; static TAccountCache s_pAccounts[EAccountCacheSize]; // = { 0 }; bzero(s_pAccounts, EAccountCacheSize * sizeof(TAccountCache)); int iFirstEmpty = 0; for (; iFirstEmpty < EAccountCacheSize; iFirstEmpty++) { if (!s_pAccounts[iFirstEmpty].m_szHost) break; // this is the first empty one if (!strcmp(inName, s_pAccounts[iFirstEmpty].m_szUserID) && !strcmp(inHost, s_pAccounts[iFirstEmpty].m_szHost)) { s_pAccounts[iFirstEmpty].m_tLastAccess = time(NULL); if (s_pAccounts[iFirstEmpty].m_iHostMax > 0) { char* szNewUserID = new char[strlen(inName) + 1]; strcpy(szNewUserID, inName); ChildData()->m_szCachedUserID = szNewUserID; char* szNewHost = new char[strlen(inHost) + 1]; strcpy(szNewHost, inHost); ChildData()->m_szCachedHost = szNewHost; if (s_pAccounts[iFirstEmpty].m_szPassword) { char* szNewPassword = new char[strlen(s_pAccounts[iFirstEmpty].m_szPassword) + 1]; strcpy(szNewPassword, s_pAccounts[iFirstEmpty].m_szPassword); ChildData()->m_szCachedPassword = szNewPassword; } else { delete ChildData()->m_szCachedPassword; ChildData()->m_szCachedPassword = NULL; s_pAccounts[iFirstEmpty].m_szPassword[0] = 0; } return s_pAccounts[iFirstEmpty].m_iHostMax; } else { // an invalid one return -1; } } } // refuse all named logins without database to verify against if (!g_pDBConnection) return -1; int iResult = -1; char szSQLCommand[EMaxMediumBufferSize] = { 0 }; snprintf( szSQLCommand, EMaxMediumBufferSize, "SELECT * FROM AuthenticateUser ('%s', '%s');", inHost, inName ); PGresult* pSQLResult = PQexec(g_pDBConnection, szSQLCommand); ExecStatusType tStatus = PGRES_FATAL_ERROR; if (pSQLResult) {#if DEBUG cout << "XTunnels: VerifyAccountExistsAndConnectionAvailable (" << szSQLCommand << ") message: " << PQresultErrorMessage(pSQLResult) << endl;#endif //DEBUG tStatus = PQresultStatus(pSQLResult); if (tStatus == PGRES_TUPLES_OK) { char* szPasswordResult = PQgetvalue(pSQLResult, 0, 0); if (strlen(inName)) { char* szNewUserID = new char[strlen(inName) + 1]; strcpy(szNewUserID, inName); ChildData()->m_szCachedUserID = szNewUserID; } char* szNewHost = new char[strlen(inHost) + 1]; strcpy(szNewHost, inHost); ChildData()->m_szCachedHost = szNewHost; char* szNewPassword = new char[strlen(inName) + 1]; strcpy(szNewPassword, szPasswordResult); ChildData()->m_szCachedPassword = szNewPassword; char* szAvailableConnectionsResult = PQgetvalue(pSQLResult, 0, 1); iResult = strtol(szAvailableConnectionsResult, NULL, 10); #if DEBUG cout << "XTunnels: VerifyAccountExistsAndConnectionAvailable password (" << szPasswordResult << ") and " << iResult << " available connections" << endl;#endif //DEBUG } else {#if DEBUG cout << "XTunnels: VerifyAccountExistsAndConnectionAvailable (" << szSQLCommand << ") PQresultStatus tStatus was bad!" << endl;#endif //DEBUG } } else {#if DEBUG cout << "XTunnels: VerifyAccountExistsAndConnectionAvailable (" << szSQLCommand << ") errored, returned NULL result!" << endl;#endif //DEBUG } PQclear(pSQLResult); // find LRU entry of s_pAccounts if necessary if (iFirstEmpty >= EAccountCacheSize) { unsigned long ulOldestIndex = 0; time_t ulOldestTime = s_pAccounts[0].m_tLastAccess; for (int iIndex = 1; iIndex < EAccountCacheSize; iIndex++) { if (ulOldestTime > s_pAccounts[iIndex].m_tLastAccess) { ulOldestTime = s_pAccounts[iIndex].m_tLastAccess; ulOldestIndex = iIndex; } } iFirstEmpty = ulOldestIndex; } // add inquiry to cache if possible if (iFirstEmpty < EAccountCacheSize) { delete s_pAccounts[iFirstEmpty].m_szHost; s_pAccounts[iFirstEmpty].m_szHost = new char[strlen(inHost) + 1]; strcpy(s_pAccounts[iFirstEmpty].m_szHost, inHost); delete s_pAccounts[iFirstEmpty].m_szUserID; s_pAccounts[iFirstEmpty].m_szUserID = new char[strlen(inName) + 1]; strcpy(s_pAccounts[iFirstEmpty].m_szUserID, inName); s_pAccounts[iFirstEmpty].m_iHostMax = iResult; delete s_pAccounts[iFirstEmpty].m_szPassword; s_pAccounts[iFirstEmpty].m_szPassword = new char[strlen(ChildData()->Password()) + 1]; strcpy(s_pAccounts[iFirstEmpty].m_szPassword, ChildData()->Password()); s_pAccounts[iFirstEmpty].m_tLastAccess = time(NULL); } return iResult; }void SaveClientSessionTraffic(SChild& tChild, bool bForceSave) { static time_t s_tNextSave = 0; static unsigned long s_ulLoggedIncomingBytes = 0; static unsigned long s_ulLoggedOutgoingBytes = 0; if (!bForceSave) { if (0 == s_tNextSave) { s_tNextSave = time(NULL) + EChildSaveTimeOut; return; } time_t tNow = time(NULL); if (tNow < s_tNextSave) return; } // these would be data errors that should really, really, never happen if (tChild.incomingbytes < s_ulLoggedIncomingBytes) s_ulLoggedIncomingBytes = tChild.incomingbytes; if (tChild.outgoingbytes < s_ulLoggedOutgoingBytes) s_ulLoggedOutgoingBytes = tChild.outgoingbytes; // now calculate new traffic since last save unsigned long ulIncomingTrafficBytes = tChild.incomingbytes - s_ulLoggedIncomingBytes; unsigned long ulOutgoingTrafficBytes = tChild.outgoingbytes - s_ulLoggedOutgoingBytes; unsigned long ulTotalTrafficBytes = ulIncomingTrafficBytes + ulOutgoingTrafficBytes; s_ulLoggedIncomingBytes += ulIncomingTrafficBytes; s_ulLoggedOutgoingBytes += ulIncomingTrafficBytes; unsigned long ulConnectionTime = tChild.connectiontime; if (!ulTotalTrafficBytes || ChildData()->IsAnonymous()) return;#if DEBUG if (!ChildData()->m_szCachedUserID || !ChildData()->m_szCachedHost) cout << "X-Tunnels: child " << getpid() << " thinks empty userid/host isn't anonymous!! " << endl;#endif //DEBUG int iDBErr = OpenDatabaseConnection(); if (iDBErr) {#if DEBUG cout << "X-Tunnels: child " << getpid() << " could not open a database connection to log client traffic!" << endl;#endif //DEBUG return; } char szSQLCommand[EMaxMediumBufferSize] = { 0 }; snprintf( szSQLCommand, EMaxMediumBufferSize, "SELECT InsertUsage ('%s','%s',%lu,%lu,%lu);", ChildData()->Host(), ChildData()->UserID(), ulConnectionTime, ulIncomingTrafficBytes, ulOutgoingTrafficBytes ); PGresult* pSQLResult = PQexec(g_pDBConnection, szSQLCommand);#if DEBUG cout << "XTunnels: SaveClientSessionTraffic (" << szSQLCommand << ") message: " << PQresultErrorMessage(pSQLResult) << endl;#endif //DEBUG PQclear(pSQLResult); CloseDatabaseConnection(); s_tNextSave = 0; }/*bool LoadRulesIfNeeded(const char* szHost) { #error look up in map here to see if rules exist for host return false; }*/ //int GetRulesFromDB(const char* szHost)int GetAllRulesFromDB() { for (vector<THostRule>::const_iterator cDisposeSourceHosts = g_cHostSourceRules.begin(); cDisposeSourceHosts != g_cHostSourceRules.end(); ++cDisposeSourceHosts) delete cDisposeSourceHosts->m_szHost; g_cHostSourceRules.erase(g_cHostSourceRules.begin(), g_cHostSourceRules.end()); for (vector<THostRule>::const_iterator cDisposeDestinationHosts = g_cHostDestinationRules.begin(); cDisposeDestinationHosts != g_cHostDestinationRules.end(); ++cDisposeDestinationHosts) delete cDisposeDestinationHosts->m_szHost; g_cHostDestinationRules.erase(g_cHostDestinationRules.begin(), g_cHostDestinationRules.end()); // assume connection is open -- this is only called by server if (!g_pDBConnection)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -