]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge pull request #1103 from rburchell/master-fix-info
authorAttila Molnar <attilamolnar@hush.com>
Sun, 15 Nov 2015 17:49:06 +0000 (18:49 +0100)
committerAttila Molnar <attilamolnar@hush.com>
Sun, 15 Nov 2015 17:49:06 +0000 (18:49 +0100)
Some updates to INFO.

include/usermanager.h
include/users.h
src/inspircd.cpp
src/modules/extra/m_ssl_gnutls.cpp
src/modules/extra/m_ssl_openssl.cpp
src/modules/m_hostcycle.cpp
src/usermanager.cpp
src/users.cpp

index eee076802f866927f11ee1aca287e77140cfdf57..941569e8c02e7af1813ec95468fd7e924a3d36d8 100644 (file)
@@ -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();
 };
index 03540018b85d7816266ef304441427a34e7e2400..fa346a32968f2164a93aed14c447ef9ba25d7e42 100644 (file)
@@ -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.
index 5c4de52bd26848c9d83b086205bb7b386c7b3636..69aa2619ccc6f9a00c600dde581b5f3718fd2807 100644 (file)
@@ -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();
index 962e80d28120797d02878aad80e018fcbb006c6a..716a736f87868f3304adfc7b79a8f697673fe5d2 100644 (file)
@@ -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");
 
index 7dd834e130e3fc6c9fcb404a38ff8d7575a8b9ad..c9ae14e11bad0b31547494d3b19cd9d3a052d199 100644 (file)
@@ -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
 };
 
index e8a0abbf15800d1f6871483a2ad80e55c07a28b4..d4def647347e9e3fa0fbf4366cc85390661afa54 100644 (file)
@@ -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;
index 41061f6d1d82decc109b3eb1fb3b6d4b34378ce3..ba6bbf36bb8e6a96bd1a2a3c6bd82211df21bf9d 100644 (file)
@@ -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;
+}
index d503844e794c76641187828a43ff395f30180a5d..93fd8d06568b169f9e84138f09297a055bc92923 100644 (file)
@@ -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)