]> jfr.im git - irc/evilnet/znc.git/commitdiff
Initial commit for evilnet modifications to znc 1.6.2 origin/znc-1.6.2-evilnet
authorMrLenin <redacted>
Fri, 29 Jan 2016 18:59:32 +0000 (13:59 -0500)
committerMrLenin <redacted>
Fri, 29 Jan 2016 18:59:32 +0000 (13:59 -0500)
include/znc/IRCSock.h
include/znc/MD5.h
modules/cyrusauth.cpp
modules/sasl.cpp
modules/webadmin.cpp
src/Client.cpp
src/ClientCommand.cpp
src/IRCSock.cpp
src/MD5.cpp

index d9af1b0187626fafa89c7446ab14ca0f053609be..75f28b510f83f81d986455e8a4293e6bf5bdd1de 100644 (file)
@@ -63,6 +63,8 @@ public:
        virtual void SockError(int iErrno, const CString& sDescription);
        virtual void Timeout();
        virtual void ReachedMaxBuffer();
+       
+       void Register();
 
        void PutIRC(const CString& sLine);
        void PutIRCQuick(const CString& sLine); //!< Should be used for PONG only
index f2cde0eeb0433d34326d19e705c4e4050bc160fc..d9eddc4185dd9fe51ab87de7a5f7da844ba87c4d 100644 (file)
@@ -26,6 +26,7 @@ md5_context;
 class CMD5 {
 protected:
        char m_szMD5[33];
+       unsigned char* m_pszMD5;
 
 public:
        CMD5();
@@ -44,6 +45,7 @@ public:
        }
 
        char* MakeHash(const char* szText, uint32 nTextLen);
+       unsigned char* GetHash();
 
 protected:
        void md5_starts( md5_context *ctx ) const;
index cba01a0b8984cd8c5b2b9c8dcbd86b55f8ae673a..a2b1112508cca0ab1689de73cedff2cfb134d2bd 100644 (file)
  */
 
 #include <znc/znc.h>
+#include <znc/IRCNetwork.h>
 #include <znc/User.h>
+#include <znc/MD5.h>
 
 #include <sasl/sasl.h>
+#include <sstream>
 
 class CSASLAuthMod : public CModule {
 public:
        MODCONSTRUCTOR(CSASLAuthMod) {
                m_Cache.SetTTL(60000/*ms*/);
-
+               m_bWebIrcEnabled = false;
                m_cbs[0].id = SASL_CB_GETOPT;
                m_cbs[0].proc = reinterpret_cast<int(*)()>(CSASLAuthMod::getopt);
                m_cbs[0].context = this;
@@ -44,6 +47,61 @@ public:
                AddCommand("CloneUser",        static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::CloneUserCommand),
                        "[username]");
                AddCommand("DisableCloneUser", static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::DisableCloneUserCommand));
+               AddCommand("SetImpersonateAccount",         static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::SetImpersonateAccount),
+                       "username password", "Set the username and password for the SASL Impersonaton Account");
+               AddCommand("SetWebIrc",        static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::SetWebIrc),
+                       "username password", "Set the username and password for WebIRC");
+               AddCommand("SetWebIrcHost",        static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::SetWebIrcHost),
+                       "hostname", "Set the hostname used for WebIRC");
+               AddCommand("SetUserSalt",      static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::SetUserSalt),
+                       "salt", "Set the salt used when hashing usernames");
+               AddCommand("SetNetworkName",        static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::SetNetworkName),
+                       "network", "Set the network name used for newly created accounts");
+               AddCommand("SetServer",        static_cast<CModCommand::ModCmdFunc>(&CSASLAuthMod::SetServer),
+                       "server port ssl", "Set the server and port used for newly created accounts");
+       }
+       
+       void SetServer(const CString& sLine) {
+               SetNV("server", sLine.Token(1));
+               SetNV("port", sLine.Token(2));
+               SetNV("ssl", sLine.Token(3));
+
+               PutModule("Server and port used for newly created accounts has been set to [" + GetNV("server") + ":" + (GetNV("ssl").ToBool() ? "+" + GetNV("port") : GetNV("port")) + "]");
+       }
+       
+       void SetNetworkName(const CString& sLine) {
+               SetNV("networkname", sLine.Token(1));
+
+               PutModule("Network name used for newly created accounts has been set to [" + GetNV("networkname") + "]");
+       }
+
+       void SetImpersonateAccount(const CString& sLine) {
+               SetNV("impersonationusername", sLine.Token(1));
+               SetNV("impersonationpassword", sLine.Token(2));
+
+               PutModule("SASL Impersonaton Account Username has been set to [" + GetNV("impersonationusername") + "]");
+               PutModule("SASL Impersonaton Account Password has been set to [" + GetNV("impersonationpassword") + "]");
+       }
+
+       void SetWebIrc(const CString& sLine) {
+               SetNV("webircusername", sLine.Token(1));
+               SetNV("webircpassword", sLine.Token(2));
+
+               PutModule("WebIRC Username has been set to [" + GetNV("webircusername") + "]");
+               PutModule("WebIRC Password has been set to [" + GetNV("webircpassword") + "]");
+       }
+       
+       void SetWebIrcHost(const CString& sLine) {
+               SetNV("webirchost", sLine);
+
+               PutModule("WebIRC hostname has been set to [" + GetNV("webirchost") + "]");
+       }
+       
+       void SetUserSalt(const CString& sLine) {
+               SetNV("usersalt", sLine.Token(1));
+
+               PutModule("User salt has been set to [" + GetNV("usersalt") + "]");
+
        }
 
        virtual ~CSASLAuthMod() {
@@ -67,10 +125,16 @@ public:
                        if (it->Equals("saslauthd") || it->Equals("auxprop")) {
                                m_sMethod += *it + " ";
                        } else {
+                               if (it->Equals("webirc")) {
+                                       m_bWebIrcEnabled = true;
+                               } else if (it->Equals("impersonation")) {
+                                       m_bSaslImpersonateEnabled = true;
+                               } else {
                                CUtils::PrintError("Ignoring invalid SASL pwcheck method: " + *it);
                                sMessage = "Ignored invalid SASL pwcheck method";
                        }
                }
+               }
 
                m_sMethod.TrimRight();
 
@@ -90,7 +154,7 @@ public:
        virtual EModRet OnLoginAttempt(std::shared_ptr<CAuthBase> Auth) override {
                const CString& sUsername = Auth->GetUsername();
                const CString& sPassword = Auth->GetPassword();
-               CUser *pUser(CZNC::Get().FindUser(sUsername));
+               CUser *pUser(CZNC::Get().FindUser(sUsername.AsLower()));
                sasl_conn_t *sasl_conn(NULL);
                bool bSuccess = false;
 
@@ -116,7 +180,7 @@ public:
                if (bSuccess) {
                        if (!pUser) {
                                CString sErr;
-                               pUser = new CUser(sUsername);
+                               pUser = new CUser(sUsername.AsLower());
 
                                if (ShouldCloneUser()) {
                                        CUser *pBaseUser = CZNC::Get().FindUser(CloneUser());
@@ -134,6 +198,17 @@ public:
                                        }
                                }
 
+                               pUser->SetNick(sUsername);
+                               pUser->SetAltNick(sUsername + "_");
+                               pUser->SetIdent(sUsername);
+                               pUser->SetRealName(sUsername);
+
+                               CString sAddNetworkError;
+                               CIRCNetwork* pNetwork = pUser->AddNetwork(GetNV("networkname"), sAddNetworkError);
+
+                               if (pNetwork) {
+                                       pNetwork->AddServer(GetNV("server"), GetNV("port").ToUShort(), "", GetNV("ssl").ToBool());
+
                                if (pUser) {
                                        // "::" is an invalid MD5 hash, so user won't be able to login by usual method
                                        pUser->SetPass("::", CUser::HASH_MD5, "::");
@@ -144,6 +219,26 @@ public:
                                        delete pUser;
                                        pUser = NULL;
                                }
+
+                                       if (m_bSaslImpersonateEnabled) {
+                                               CString sModRet;
+
+                                               if (pNetwork->GetModules().LoadModule("sasl", "", CModInfo::NetworkModule, pUser, pNetwork, sModRet))
+                                               {
+                                                       CModule* pModule = pNetwork->GetModules().FindModule("sasl");
+                                                       if (pModule) {
+                                                               pModule->SetNV("saslimpersonation", "yes");
+                                                               pModule->SetNV("impersonationuser", sUsername);
+                                                               pModule->SetNV("username", GetNV("impersonationusername"));
+                                                               pModule->SetNV("password", GetNV("impersonationpassword"));
+                                                               pModule->SetNV("require_auth", "yes");
+                                                               pModule->SetNV("mechanisms", "PLAIN");
+                                                       }
+                                               }
+                                               else DEBUG("saslauth: Failure loading sasl module for created user [" << sUsername << "] ");
+                                       }
+                               }
+                               else DEBUG("saslauth: Failure adding network for created user [" << sUsername << "]: " << sAddNetworkError);
                        }
 
                        if (pUser) {
@@ -151,7 +246,35 @@ public:
                                return HALT;
                        }
                }
+               return CONTINUE;
+       }
 
+       virtual EModRet OnIRCRegistration(CString& sPass, CString& sNick,
+                                                                         CString& sIdent, CString& sRealName)
+       {
+               if (m_bWebIrcEnabled) {
+                       CUser* pUser = CModule::GetUser();
+                       CIRCNetwork* pNetwork = CModule::GetNetwork();
+               
+                       if (pUser != NULL && !(pNetwork->GetName().CaseCmp(GetNV("networkname")))) {
+                               if (!(pUser->GetUserName().StrCmp("MrLenin")))
+                                       return CONTINUE;
+
+                               std::ostringstream sWebIrcMsg;
+                               CString sUsername = pUser->GetUserName();
+                               CMD5 md5(sUsername + GetNV("usersalt"));
+                               uint8* hashBytes = downsample(md5.GetHash());
+                               unsigned int hashInts[3] = { hashBytes[0], hashBytes[1], hashBytes[2] };
+
+                               sWebIrcMsg << "WEBIRC " << GetNV("webircpassword") << " " << GetNV("webircusername") << " " << sUsername <<
+                                       GetNV("webirchost") << " 255." << hashInts[0] << "." << hashInts[1] << "." << hashInts[2];
+
+                               CModule::PutIRC(sWebIrcMsg.str());
+            
+                               delete[] hashBytes;
+                       }
+               }
+               
                return CONTINUE;
        }
 
@@ -207,6 +330,8 @@ protected:
 
        sasl_callback_t m_cbs[2];
        CString m_sMethod;
+       bool m_bWebIrcEnabled;
+       bool m_bSaslImpersonateEnabled;
 
        static int getopt(void *context, const char *plugin_name,
                        const char *option, const char **result, unsigned *len) {
@@ -217,12 +342,27 @@ protected:
 
                return SASL_CONTINUE;
        }
+
+       /** Downsamples a 128bit result to 32bits (md5 -> unsigned int).
+        * @param[in] i 128bit result to downsample.
+        * @return downsampled result.
+
+        */
+       static inline uint8* downsample(unsigned char *i)
+       {
+               uint8* r = new uint8[3];
+               r[0] = i[0] ^ i[1] ^ i[2] ^ i[3] ^ i[4];
+               r[1] = i[5] ^ i[6] ^ i[7] ^ i[8] ^ i[9];
+               r[2] = i[10] ^ i[11] ^ i[12] ^ i[13] ^ i[14] ^ i[15];
+       
+               return r;
+       }
 };
 
 template<> void TModInfo<CSASLAuthMod>(CModInfo& Info) {
        Info.SetWikiPage("cyrusauth");
        Info.SetHasArgs(true);
-       Info.SetArgsHelpText("This global module takes up to two arguments - the methods of authentication - auxprop and saslauthd");
+       Info.SetArgsHelpText("This global module takes up to four arguments - the methods of authentication - auxprop and saslauthd - and optionally, if WebIRC host spoofing and/or SASL Impersonation is to be enabled - webirc and impersonation");
 }
 
 GLOBALMODULEDEFS(CSASLAuthMod, "Allow users to authenticate via SASL password verification method")
index 4f2fc3def3c608114af70dfb6c6fed7d54e67a0a..8d656dea57f8dac0eef52000bcee040ae58138aa 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <znc/IRCNetwork.h>
 #include <znc/IRCSock.h>
+#include <znc/User.h>
 
 static const struct {
        const char *szName;
@@ -97,14 +98,21 @@ public:
        }
 
        void Set(const CString& sLine) {
+               if (!SaslImpersonation()) {
                SetNV("username", sLine.Token(1));
                SetNV("password", sLine.Token(2));
 
                PutModule("Username has been set to [" + GetNV("username") + "]");
                PutModule("Password has been set to [" + GetNV("password") + "]");
        }
-
+       }
+       
+       bool SaslImpersonation() const {
+               return GetNV("saslimpersonation").ToBool();
+       }
+       
        void SetMechanismCommand(const CString& sLine) {
+               if (!SaslImpersonation()) {
                CString sMechanisms = sLine.Token(1, true).AsUpper();
 
                if (!sMechanisms.empty()) {
@@ -123,8 +131,10 @@ public:
 
                PutModule("Current mechanisms set: " + GetMechanismsString());
        }
+       }
 
        void RequireAuthCommand(const CString& sLine) {
+               if (!SaslImpersonation()) {
                if (!sLine.Token(1).empty()) {
                        SetNV(NV_REQUIRE_AUTH, sLine.Token(1));
                }
@@ -135,6 +145,7 @@ public:
                        PutModule("We will connect even if SASL fails");
                }
        }
+       }
 
        bool SupportsMechanism(const CString& sMechanism) const {
                for (size_t i = 0; SupportedMechanisms[i].szName != NULL; i++) {
@@ -179,7 +190,7 @@ public:
 
        void Authenticate(const CString& sLine) {
                if (m_Mechanisms.GetCurrent().Equals("PLAIN") && sLine.Equals("+")) {
-                       CString sAuthLine = GetNV("username") + '\0' + GetNV("username")  + '\0' + GetNV("password");
+                       CString sAuthLine = (SaslImpersonation() ? GetNV("impersonationuser") : GetNV("username")) + '\0' + GetNV("username")  + '\0' + GetNV("password");
                        sAuthLine.Base64Encode();
                        PutIRC("AUTHENTICATE " + sAuthLine);
                } else {
index 639be02101b5359b5e82fcb8c397a75242f0b2cf..398b3f133e31a2787e75b836cec3de464c033788 100644 (file)
@@ -466,6 +466,11 @@ public:
                        return NetworkPage(WebSock, Tmpl, pNetwork->GetUser(), pNetwork);
 
                } else if (sPageName == "delnetwork") {
+               // Admin||Self Check
+                       if (!spSession->IsAdmin()) {
+                               return false;
+                       }
+            
                        CString sUser = WebSock.GetParam("user");
                        if (sUser.empty() && !WebSock.IsPost()) {
                                sUser = WebSock.GetParam("user", false);
@@ -473,11 +478,6 @@ public:
 
                        CUser* pUser = CZNC::Get().FindUser(sUser);
 
-                       // Admin||Self Check
-                       if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pUser)) {
-                               return false;
-                       }
-
                        return DelNetwork(WebSock, pUser, Tmpl);
                } else if (sPageName == "editchan") {
                        CIRCNetwork* pNetwork = SafeGetNetworkFromParam(WebSock);
@@ -860,11 +860,13 @@ public:
 
                                breadNet["Text"] = "Edit Network [" + pNetwork->GetName() + "]";
 
+                               if (spSession->IsAdmin()) {
                                const vector<CServer*>& vServers = pNetwork->GetServers();
                                for (unsigned int a = 0; a < vServers.size(); a++) {
                                        CTemplate& l = Tmpl.AddRow("ServerLoop");
                                        l["Server"] = vServers[a]->GetString();
                                }
+                               }
 
                                const vector<CChan*>& Channels = pNetwork->GetChans();
                                for (unsigned int c = 0; c < Channels.size(); c++) {
@@ -1034,11 +1036,15 @@ public:
 
                VCString vsArgs;
 
+               if (spSession->IsAdmin()) {
+                       WebSock.GetRawParam("servers").Split("\n", vsArgs);
+                       if (vsArgs.size()) {
                pNetwork->DelServers();
-               WebSock.GetRawParam("servers").Split("\n", vsArgs);
                for (unsigned int a = 0; a < vsArgs.size(); a++) {
                        pNetwork->AddServer(vsArgs[a].Trim_n());
                }
+                       }
+               }
 
                WebSock.GetRawParam("fingerprints").Split("\n", vsArgs);
                while (!pNetwork->GetTrustedFingerprints().empty()) {
@@ -1099,9 +1105,27 @@ public:
                        }
                }
 
+               CString sModUnloadError;
+               CModule* pModule;
+               
                for (set<CString>::iterator it2 = ssUnloadMods.begin(); it2 != ssUnloadMods.end(); ++it2) {
+                       if (!it2->CaseCmp("sasl")) {
+                               pModule = pNetwork->GetModules().FindModule("sasl");
+                               
+                               if (pModule) {
+                                       if (pModule->GetNV("saslimpersonation").ToBool()) {
+                                               sModUnloadError = "Unable to unload module [sasl] SaslImpersonation enabled.";
+                                               continue;
+                                       }
+                               }
+                       }
                        pNetwork->GetModules().UnloadModule(*it2);
                }
+               
+               if (!sModUnloadError.empty()) {
+                       DEBUG(sModUnloadError);
+                       WebSock.GetSession()->AddError(sModUnloadError);
+               }
 
                CTemplate TmplMod;
                TmplMod["Username"] = pUser->GetUserName();
index e6e741f5c3ba14462dbda04586f118feaae004ed..6dda7b512a96555b734e2993db7d1cb4f1d1ffc3 100644 (file)
@@ -84,8 +84,8 @@ void CClient::SendRequiredPasswordNotice() {
                          "You need to send your password. "
                          "Configure your client to send a server password.");
        PutClient(":irc.znc.in NOTICE AUTH :*** "
-                         "To connect now, you can use /quote PASS <username>:<password>, "
-                         "or /quote PASS <username>/<network>:<password> to connect to a specific network.");
+                         "To connect now, you can use /quote PASS /<username>/<password>, "
+                         "or /quote PASS <network>/<username>/<password> to connect to a specific network.");
 }
 
 void CClient::ReadLine(const CString& sData) {
@@ -999,29 +999,34 @@ void CClient::HandleCap(const CString& sLine)
 }
 
 void CClient::ParsePass(const CString& sAuthLine) {
-       // [user[@identifier][/network]:]password
 
-       const size_t uColon = sAuthLine.find(":");
-       if (uColon != CString::npos) {
-               m_sPass = sAuthLine.substr(uColon + 1);
+       // [network[/user[@identifier]/]]password
 
-               ParseUser(sAuthLine.substr(0, uColon));
+       if (sAuthLine.find("/") == CString::npos) {
+               m_sPass = sAuthLine;
        } else {
+               VCString vsAuthLine;
+               sAuthLine.Split("/", vsAuthLine, false);
+               switch (vsAuthLine.size()) {
+               case 2:
+                       ParseUser(vsAuthLine[0]);
+                       m_sPass = vsAuthLine[1];
+                       break;
+               case 3:
+                       m_sNetwork = vsAuthLine[0];
+                       ParseUser(vsAuthLine[1]);
+                       m_sPass = vsAuthLine[2];
+                       break;
+               default:
                m_sPass = sAuthLine;
        }
 }
 
 void CClient::ParseUser(const CString& sAuthLine) {
-       // user[@identifier][/network]
-
-       const size_t uSlash = sAuthLine.rfind("/");
-       if (uSlash != CString::npos) {
-               m_sNetwork = sAuthLine.substr(uSlash + 1);
+       // user[@identifier]
 
-               ParseIdentifier(sAuthLine.substr(0, uSlash));
-       } else {
                ParseIdentifier(sAuthLine);
-       }
 }
 
 void CClient::ParseIdentifier(const CString& sAuthLine) {
index b74b0ac6d56136719d0827057cb49c9dee228591..c230e886f3a151df20f7b2092919a92fd3fe44ef 100644 (file)
@@ -533,6 +533,11 @@ void CClient::UserCommand(CString& sLine) {
                        PutStatus(sNetworkAddError);
                }
        } else if (sCommand.Equals("DELNETWORK")) {
+        if (!m_pUser->IsAdmin()) {
+                       PutStatus("Administrative access required to remove a Network. Ask an admin to remove the network for you.");
+                       return;
+               }
+        
                CString sNetwork = sLine.Token(1);
 
                if (sNetwork.empty()) {
@@ -691,6 +696,11 @@ void CClient::UserCommand(CString& sLine) {
                        PutStatus("You don't have a network named " + sNetwork);
                }
        } else if (sCommand.Equals("ADDSERVER")) {
+               if (!m_pUser->IsAdmin()) {
+                       PutStatus("Administrative access required to add a Server. Ask an admin to add the server for you.");
+                       return;
+               }
+        
                CString sServer = sLine.Token(1);
 
                if (!m_pNetwork) {
@@ -710,6 +720,11 @@ void CClient::UserCommand(CString& sLine) {
                        PutStatus("Perhaps the server is already added or openssl is disabled?");
                }
        } else if (sCommand.Equals("REMSERVER") || sCommand.Equals("DELSERVER")) {
+        if (!m_pUser->IsAdmin()) {
+                       PutStatus("Administrative access required to remove a Server. Ask an admin to remove the server for you.");
+                       return;
+               }
+        
                if (!m_pNetwork) {
                        PutStatus("You must be connected with a network to use this command");
                        return;
@@ -1080,6 +1095,7 @@ void CClient::UserCommand(CString& sLine) {
                }
 
                CString sModRet;
+               CModule* pModule;
 
                switch (eType) {
                case CModInfo::GlobalModule:
@@ -1089,6 +1105,16 @@ void CClient::UserCommand(CString& sLine) {
                        m_pUser->GetModules().UnloadModule(sMod, sModRet);
                        break;
                case CModInfo::NetworkModule:
+                       if (!sMod.CaseCmp("sasl")) {
+                               pModule = m_pNetwork->GetModules().FindModule("sasl");
+                               
+                               if (pModule) {
+                                       if (pModule->GetNV("saslimpersonation").ToBool()) {
+                                               PutStatus("Unable to unload module [sasl] SaslImpersonation enabled.");
+                                               return;
+                                       }
+                               }
+                       }
                        m_pNetwork->GetModules().UnloadModule(sMod, sModRet);
                        break;
                default:
@@ -1150,6 +1176,7 @@ void CClient::UserCommand(CString& sLine) {
                }
 
                CString sModRet;
+               CModule* pModule;
 
                switch (eType) {
                case CModInfo::GlobalModule:
@@ -1159,6 +1186,16 @@ void CClient::UserCommand(CString& sLine) {
                        m_pUser->GetModules().ReloadModule(sMod, sArgs, m_pUser, NULL, sModRet);
                        break;
                case CModInfo::NetworkModule:
+                       if (!sMod.CaseCmp("sasl")) {
+                               pModule = m_pNetwork->GetModules().FindModule("sasl");
+                               
+                               if (pModule) {
+                                       if (pModule->GetNV("saslimpersonation").ToBool()) {
+                                               PutStatus("Unable to reload module [sasl] SaslImpersonation enabled.");
+                                               return;
+                                       }
+                               }
+                       }
                        m_pNetwork->GetModules().ReloadModule(sMod, sArgs, m_pUser, m_pNetwork, sModRet);
                        break;
                default:
@@ -1628,19 +1665,19 @@ void CClient::HelpUser(const CString& sFilter) {
        if (!m_pUser->IsAdmin()) {
                AddCommandHelp(Table, "ListClients", "", "List all clients connected to your ZNC user", sFilter);
        }
+
+       if (m_pUser->IsAdmin()) {
        AddCommandHelp(Table, "ListServers", "", "List all servers of current IRC network", sFilter);
 
        AddCommandHelp(Table, "AddNetwork", "<name>", "Add a network to your user", sFilter);
        AddCommandHelp(Table, "DelNetwork", "<name>", "Delete a network from your user", sFilter);
        AddCommandHelp(Table, "ListNetworks", "", "List all networks", sFilter);
-       if (m_pUser->IsAdmin()) {
                AddCommandHelp(Table, "MoveNetwork", "<old user> <old network> <new user> [new network]", "Move an IRC network from one user to another", sFilter);
-       }
        AddCommandHelp(Table, "JumpNetwork", "<network>", "Jump to another network (Alternatively, you can connect to ZNC several times, using `user/network` as username)", sFilter);
 
        AddCommandHelp(Table, "AddServer", "<host> [[+]port] [pass]", "Add a server to the list of alternate/backup servers of current IRC network.", sFilter);
        AddCommandHelp(Table, "DelServer", "<host> [port] [pass]", "Remove a server from the list of alternate/backup servers of current IRC network", sFilter);
-
+       }
        AddCommandHelp(Table, "AddTrustedServerFingerprint", "<fi:ng:er>", "Add a trusted server SSL certificate fingerprint (SHA-256) to current IRC network.", sFilter);
        AddCommandHelp(Table, "DelTrustedServerFingerprint", "<fi:ng:er>", "Delete a trusted server SSL certificate from current IRC network.", sFilter);
        AddCommandHelp(Table, "ListTrustedServerFingerprints", "", "List all trusted server SSL certificates of current IRC network.", sFilter);
index 91730f16aef77a0d109f75e3480c14c685b6d439..931ed18b274b84dfbabefb727d379ffd2def5c25 100644 (file)
@@ -844,6 +844,7 @@ void CIRCSock::SendNextCap() {
                if (m_ssPendingCaps.empty()) {
                        // We already got all needed ACK/NAK replies.
                        PutIRC("CAP END");
+                       Register();
                } else {
                        CString sCap = *m_ssPendingCaps.begin();
                        m_ssPendingCaps.erase(m_ssPendingCaps.begin());
@@ -1091,7 +1092,12 @@ void CIRCSock::SetNick(const CString& sNick) {
 
 void CIRCSock::Connected() {
        DEBUG(GetSockName() << " == Connected()");
+       PutIRC("CAP LS");
+}
 
+void CIRCSock::Register() {
+       DEBUG(GetSockName() << " == Register()");
+       
        CString sPass = m_sPass;
        CString sNick = m_pNetwork->GetNick();
        CString sIdent = m_pNetwork->GetIdent();
@@ -1101,12 +1107,9 @@ void CIRCSock::Connected() {
        IRCSOCKMODULECALL(OnIRCRegistration(sPass, sNick, sIdent, sRealName), &bReturn);
        if (bReturn) return;
 
-       PutIRC("CAP LS");
-
-       if (!sPass.empty()) {
+       if (!sPass.empty())
                PutIRC("PASS " + sPass);
-       }
-
+       
        PutIRC("NICK " + sNick);
        PutIRC("USER " + sIdent + " \"" + sIdent + "\" \"" + sIdent + "\" :" + sRealName);
 
index a3e1c414aa9e9307414d5f8f50c36c2be84111e2..488c17399437a43b62da34e32938ee858b236682 100644 (file)
@@ -35,7 +35,16 @@ CMD5::CMD5(const char* szText, uint32 nTextLen) {
        MakeHash(szText, nTextLen);
 }
 
-CMD5::~CMD5() {}
+CMD5::~CMD5()
+{
+    if (m_pszMD5 != NULL)
+        delete[] m_pszMD5;
+}
+
+unsigned char* CMD5::GetHash()
+{
+    return m_pszMD5;
+}
 
 #define GET_UINT32(n,b,i) {                 \
        (n) = ((uint32) (b)[(i)    ]      )     \
@@ -258,6 +267,12 @@ char* CMD5::MakeHash(const char* szText, uint32 nTextLen) {
                        md5sum[0], md5sum[1], md5sum[2], md5sum[3], md5sum[4], md5sum[5],
                        md5sum[6], md5sum[7], md5sum[8], md5sum[9], md5sum[10], md5sum[11],
                        md5sum[12], md5sum[13], md5sum[14], md5sum[15]);
+            
+    m_pszMD5 = new unsigned char[16];
+    m_pszMD5[0] = md5sum[0]; m_pszMD5[1] = md5sum[1]; m_pszMD5[2] = md5sum[2]; m_pszMD5[3] = md5sum[3]; 
+    m_pszMD5[4] = md5sum[4]; m_pszMD5[5] = md5sum[5]; m_pszMD5[6] = md5sum[6]; m_pszMD5[7] = md5sum[7]; 
+    m_pszMD5[8] = md5sum[8]; m_pszMD5[9] = md5sum[9]; m_pszMD5[10] = md5sum[10]; m_pszMD5[11] = md5sum[11]; 
+    m_pszMD5[12] = md5sum[12]; m_pszMD5[13] = md5sum[13]; m_pszMD5[14] = md5sum[14]; m_pszMD5[15] = md5sum[15]; 
 
        return m_szMD5;
 }