diff options
-rw-r--r-- | include/usermanager.h | 15 | ||||
-rw-r--r-- | include/users.h | 1 | ||||
-rw-r--r-- | src/inspircd.cpp | 3 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_gnutls.cpp | 93 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_openssl.cpp | 14 | ||||
-rw-r--r-- | src/modules/m_hostcycle.cpp | 4 | ||||
-rw-r--r-- | src/usermanager.cpp | 26 | ||||
-rw-r--r-- | src/users.cpp | 4 |
8 files changed, 114 insertions, 46 deletions
diff --git a/include/usermanager.h b/include/usermanager.h index eee076802..941569e8c 100644 --- a/include/usermanager.h +++ b/include/usermanager.h @@ -56,6 +56,11 @@ class CoreExport UserManager : public fakederef<UserManager> */ LocalList local_users; + /** Last used already sent id, used when sending messages to neighbors to help determine whether the message has + * been sent to a particular user or not. See User::ForEachNeighbor() for more info. + */ + already_sent_t already_sent_id; + public: /** Constructor, initializes variables */ @@ -83,11 +88,6 @@ class CoreExport UserManager : public fakederef<UserManager> */ unsigned int unregistered_count; - /** - * Reset the already_sent IDs so we don't wrap it around and drop a message - */ - void GarbageCollect(); - /** Perform background user events such as PING checks */ void DoBackgroundUserStuff(); @@ -186,4 +186,9 @@ class CoreExport UserManager : public fakederef<UserManager> * @param ... The format arguments */ void ServerNoticeAll(const char* text, ...) CUSTOM_PRINTF(2, 3); + + /** Retrieves the next already sent id, guaranteed to be not equal to any user's already_sent field + * @return Next already_sent id + */ + already_sent_t NextAlreadySentId(); }; diff --git a/include/users.h b/include/users.h index 03540018b..fa346a329 100644 --- a/include/users.h +++ b/include/users.h @@ -720,7 +720,6 @@ class CoreExport LocalUser : public User, public insp::intrusive_list_node<Local */ unsigned int CommandFloodPenalty; - static already_sent_t already_sent_id; already_sent_t already_sent; /** Check if the user matches a G or K line, and disconnect them if they do. diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 5c4de52bd..69aa2619c 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -659,10 +659,7 @@ void InspIRCd::Run() OLDTIME = TIME.tv_sec; if ((TIME.tv_sec % 3600) == 0) - { - Users->GarbageCollect(); FOREACH_MOD(OnGarbageCollect, ()); - } Timers.TickTimers(TIME.tv_sec); Users->DoBackgroundUserStuff(); diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index 962e80d28..716a736f8 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -209,14 +209,6 @@ namespace GnuTLS return dh; } - /** Generate */ - static std::auto_ptr<DHParams> Generate(unsigned int bits) - { - std::auto_ptr<DHParams> dh(new DHParams); - ThrowOnError(gnutls_dh_params_generate2(dh->dh_params, bits), "Unable to generate DH params"); - return dh; - } - ~DHParams() { gnutls_dh_params_deinit(dh_params); @@ -353,6 +345,40 @@ namespace GnuTLS { gnutls_priority_set(sess, priority); } + + static const char* GetDefault() + { + return "NORMAL:%SERVER_PRECEDENCE:-VERS-SSL3.0"; + } + + static std::string RemoveUnknownTokens(const std::string& prio) + { + std::string ret; + irc::sepstream ss(prio, ':'); + for (std::string token; ss.GetToken(token); ) + { + // Save current position so we can revert later if needed + const std::string::size_type prevpos = ret.length(); + // Append next token + if (!ret.empty()) + ret.push_back(':'); + ret.append(token); + + gnutls_priority_t test; + if (gnutls_priority_init(&test, ret.c_str(), NULL) < 0) + { + // The new token broke the priority string, revert to the previously working one + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Priority string token not recognized: \"%s\"", token.c_str()); + ret.erase(prevpos); + } + else + { + // Worked + gnutls_priority_deinit(test); + } + } + return ret; + } }; #else /** Dummy class, used when gnutls_priority_set() is not available @@ -362,7 +388,7 @@ namespace GnuTLS public: Priority(const std::string& priorities) { - if (priorities != "NORMAL") + if (priorities != GetDefault()) throw Exception("You've set a non-default priority string, but GnuTLS lacks support for it"); } @@ -371,6 +397,17 @@ namespace GnuTLS // Always set the default priorities gnutls_set_default_priority(sess); } + + static const char* GetDefault() + { + return "NORMAL"; + } + + static std::string RemoveUnknownTokens(const std::string& prio) + { + // We don't do anything here because only NORMAL is accepted + return prio; + } }; #endif @@ -564,24 +601,40 @@ namespace GnuTLS return ret; } + static std::string GetPrioStr(const std::string& profilename, ConfigTag* tag) + { + // Use default priority string if this tag does not specify one + std::string priostr = GnuTLS::Priority::GetDefault(); + bool found = tag->readString("priority", priostr); + // If the prio string isn't set in the config don't be strict about the default one because it doesn't work on all versions of GnuTLS + if (!tag->getBool("strictpriority", found)) + { + std::string stripped = GnuTLS::Priority::RemoveUnknownTokens(priostr); + if (stripped.empty()) + { + // Stripping failed, act as if a prio string wasn't set + stripped = GnuTLS::Priority::RemoveUnknownTokens(GnuTLS::Priority::GetDefault()); + ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Priority string for profile \"%s\" contains unknown tokens and stripping it didn't yield a working one either, falling back to \"%s\"", profilename.c_str(), stripped.c_str()); + } + else if ((found) && (stripped != priostr)) + { + // Prio string was set in the config and we ended up with something that works but different + ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Priority string for profile \"%s\" contains unknown tokens, stripped to \"%s\"", profilename.c_str(), stripped.c_str()); + } + priostr.swap(stripped); + } + return priostr; + } + public: static reference<Profile> Create(const std::string& profilename, ConfigTag* tag) { std::string certstr = ReadFile(tag->getString("certfile", "cert.pem")); std::string keystr = ReadFile(tag->getString("keyfile", "key.pem")); - std::auto_ptr<DHParams> dh; - int gendh = tag->getInt("gendh"); - if (gendh) - { - gendh = (gendh < 1024 ? 1024 : gendh); - dh = DHParams::Generate(gendh); - } - else - dh = DHParams::Import(ReadFile(tag->getString("dhfile", "dhparams.pem"))); + std::auto_ptr<DHParams> dh = DHParams::Import(ReadFile(tag->getString("dhfile", "dhparams.pem"))); - // Use default priority string if this tag does not specify one - std::string priostr = tag->getString("priority", "NORMAL"); + std::string priostr = GetPrioStr(profilename, tag); unsigned int mindh = tag->getInt("mindhbits", 1024); std::string hashstr = tag->getString("hash", "md5"); diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 7dd834e13..c9ae14e11 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -269,10 +269,10 @@ namespace OpenSSL long setoptions = tag->getInt(ctxname + "setoptions"); long clearoptions = tag->getInt(ctxname + "clearoptions"); #ifdef SSL_OP_NO_COMPRESSION - if (!tag->getBool("compression", true)) + if (!tag->getBool("compression", false)) // Disable compression by default setoptions |= SSL_OP_NO_COMPRESSION; #endif - if (!tag->getBool("sslv3", true)) + if (!tag->getBool("sslv3", false)) // Disable SSLv3 by default setoptions |= SSL_OP_NO_SSLv3; if (!tag->getBool("tlsv1", true)) setoptions |= SSL_OP_NO_TLSv1; @@ -363,6 +363,14 @@ namespace OpenSSL return 1; } + static int destroy(BIO* bio) + { + // XXX: Dummy function to avoid a memory leak in OpenSSL. + // The memory leak happens in BIO_free() (bio_lib.c) when the destroy func of the BIO is NULL. + // This is fixed in OpenSSL but some distros still ship the unpatched version hence we provide this workaround. + return 1; + } + static long ctrl(BIO* bio, int cmd, long num, void* ptr) { if (cmd == BIO_CTRL_FLUSH) @@ -385,7 +393,7 @@ static BIO_METHOD biomethods = NULL, // gets OpenSSL::BIOMethod::ctrl, OpenSSL::BIOMethod::create, - NULL, // destroy, NULL causes older OpenSSL to leak memory in BIO_free() (bio_lib.c) + OpenSSL::BIOMethod::destroy, // destroy, does nothing, see function body for more info NULL // callback_ctrl }; diff --git a/src/modules/m_hostcycle.cpp b/src/modules/m_hostcycle.cpp index e8a0abbf1..d4def6473 100644 --- a/src/modules/m_hostcycle.cpp +++ b/src/modules/m_hostcycle.cpp @@ -29,8 +29,8 @@ class ModuleHostCycle : public Module // GetFullHost() returns the original data at the time this function is called const std::string quitline = ":" + user->GetFullHost() + " QUIT :" + quitmsg; - already_sent_t silent_id = ++LocalUser::already_sent_id; - already_sent_t seen_id = ++LocalUser::already_sent_id; + already_sent_t silent_id = ServerInstance->Users.NextAlreadySentId(); + already_sent_t seen_id = ServerInstance->Users.NextAlreadySentId(); IncludeChanList include_chans(user->chans.begin(), user->chans.end()); std::map<User*,bool> exceptions; diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 41061f6d1..ba6bbf36b 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -49,7 +49,8 @@ namespace } UserManager::UserManager() - : unregistered_count(0) + : already_sent_id(0) + , unregistered_count(0) { } @@ -278,14 +279,6 @@ void UserManager::ServerNoticeAll(const char* text, ...) } } -void UserManager::GarbageCollect() -{ - // Reset the already_sent IDs so we don't wrap it around and drop a message - LocalUser::already_sent_id = 0; - for (LocalList::const_iterator i = local_users.begin(); i != local_users.end(); ++i) - (**i).already_sent = 0; -} - /* this returns true when all modules are satisfied that the user should be allowed onto the irc server * (until this returns true, a user will block in the waiting state, waiting to connect up to the * registration timeout maximum seconds) @@ -368,3 +361,18 @@ void UserManager::DoBackgroundUserStuff() } } } + +already_sent_t UserManager::NextAlreadySentId() +{ + if (++already_sent_id == 0) + { + // Wrapped around, reset the already_sent ids of all users + already_sent_id = 1; + for (LocalList::iterator i = local_users.begin(); i != local_users.end(); ++i) + { + LocalUser* user = *i; + user->already_sent = 0; + } + } + return already_sent_id; +} diff --git a/src/users.cpp b/src/users.cpp index d503844e7..93fd8d065 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -26,8 +26,6 @@ #include "inspircd.h" #include "xline.h" -already_sent_t LocalUser::already_sent_id = 0; - bool User::IsNoticeMaskSet(unsigned char sm) { if (!isalpha(sm)) @@ -873,7 +871,7 @@ void User::ForEachNeighbor(ForEachNeighborHandler& handler, bool include_self) FOREACH_MOD(OnBuildNeighborList, (this, include_chans, exceptions)); // Get next id, guaranteed to differ from the already_sent field of all users - const already_sent_t newid = ++LocalUser::already_sent_id; + const already_sent_t newid = ServerInstance->Users.NextAlreadySentId(); // Handle exceptions first for (std::map<User*, bool>::const_iterator i = exceptions.begin(); i != exceptions.end(); ++i) |