]> jfr.im git - irc/rizon/znc.git/commitdiff
Add supports for salted hashes to znc.conf
authorpsychon <redacted>
Sun, 13 Jul 2008 15:32:27 +0000 (15:32 +0000)
committerpsychon <redacted>
Sun, 13 Jul 2008 15:32:27 +0000 (15:32 +0000)
These changes the format of the 'Pass' config option. The old format is
still accepted. The new format is:

  Pass = plain#<plain text password>
  Pass = md5#<password hash>
  Pass = md5#<hash of password with salt appended>#<salt>#

This also makes ZNC only write configs in the new format.

znc --makeconf and znc --makepass now always generate salted hashes.

git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1127 726aef4b-f618-498e-8847-2d620e286838

User.cpp
User.h
Utils.cpp
Utils.h
main.cpp
znc.cpp

index a269a035d9d3ace472fd973b3828f88b63d00a23..c3f5d36b3c0203fda5170ac9e42f8eb632acf49a 100644 (file)
--- a/User.cpp
+++ b/User.cpp
@@ -565,7 +565,15 @@ bool CUser::PrintLine(CFile& File, const CString& sName, const CString& sValue)
 bool CUser::WriteConfig(CFile& File) {
        File.Write("<User " + GetUserName() + ">\n");
 
-       PrintLine(File, "Pass", GetPass() + ((IsPassHashed()) ? " -" : ""));
+       if (IsPassHashed()) {
+               if (m_sPassSalt.empty()) {
+                       PrintLine(File, "Pass", "md5#" + GetPass());
+               } else {
+                       PrintLine(File, "Pass", "md5#" + GetPass() + "#" + m_sPassSalt + "#");
+               }
+       } else {
+               PrintLine(File, "Pass", "plain#" + GetPass());
+       }
        PrintLine(File, "Nick", GetNick());
        PrintLine(File, "AltNick", GetAltNick());
        PrintLine(File, "Ident", GetIdent());
@@ -808,7 +816,9 @@ bool CUser::CheckPass(const CString& sPass) {
                return (sPass == m_sPass);
        }
 
-       return (m_sPass.CaseCmp(sPass.MD5()) == 0);
+       CString sSaltedPass = sPass + m_sPassSalt;
+
+       return (m_sPass.CaseCmp(sSaltedPass.MD5()) == 0);
 }
 
 /*CClient* CUser::GetClient() {
@@ -1023,7 +1033,11 @@ void CUser::SetAltNick(const CString& s) { m_sAltNick = s; }
 void CUser::SetIdent(const CString& s) { m_sIdent = s; }
 void CUser::SetRealName(const CString& s) { m_sRealName = s; }
 void CUser::SetVHost(const CString& s) { m_sVHost = s; }
-void CUser::SetPass(const CString& s, bool bHashed) { m_sPass = s; m_bPassHashed = bHashed; }
+void CUser::SetPass(const CString& s, bool bHashed, const CString& sSalt) {
+       m_sPass = s;
+       m_bPassHashed = bHashed;
+       m_sPassSalt = sSalt;
+}
 void CUser::SetMultiClients(bool b) { m_bMultiClients = b; }
 void CUser::SetBounceDCCs(bool b) { m_bBounceDCCs = b; }
 void CUser::SetUseClientIP(bool b) { m_bUseClientIP = b; }
diff --git a/User.h b/User.h
index 02dca00a25554bf82e79b4a9cfcb166bb6546620..ae4d1e6cfaa5fce708d11372941f848656ac1f82 100644 (file)
--- a/User.h
+++ b/User.h
@@ -119,7 +119,7 @@ public:
        void SetIdent(const CString& s);
        void SetRealName(const CString& s);
        void SetVHost(const CString& s);
-       void SetPass(const CString& s, bool bHashed);
+       void SetPass(const CString& s, bool bHashed, const CString& sSalt = "");
        void SetBounceDCCs(bool b);
        void SetMultiClients(bool b);
        void SetUseClientIP(bool b);
@@ -207,6 +207,7 @@ protected:
        CString                 m_sRealName;
        CString                 m_sVHost;
        CString                 m_sPass;
+       CString                 m_sPassSalt;
        CString                 m_sStatusPrefix;
        CString                 m_sDefaultChanModes;
        CString                 m_sChanPrefixes;
index ffbf27c28ba7cb25c77aeead60a2c335cee56c72..8aea3a76afb78f1e006f5d984dab7a0cc00cbe61 100644 (file)
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -189,6 +189,49 @@ CString CUtils::GetHashPass() {
        return "";
 }
 
+CString CUtils::GetSaltedHashPass(CString& sSalt, unsigned int uiSaltLength) {
+       sSalt = CString::RandomString(uiSaltLength);
+       const char *pSalt = sSalt.c_str();
+
+       while (true) {
+               char* pass = CUtils::GetPass("Enter Password");
+               char* pass1 = (char *) malloc(strlen(pass) + 1);
+               // Make a copy of this since it is stored in a static buffer and will be overwritten when we fill pass2 below
+               strcpy(pass1, pass);
+               // null out our pass so it doesn't sit in memory
+               memset(pass, 0, strlen(pass));
+               char* pass2 = CUtils::GetPass("Confirm Password");
+               int iLen = strlen(pass1);
+
+               if (strcmp(pass1, pass2) != 0) {
+                       CUtils::PrintError("The supplied passwords did not match");
+               } else if (!iLen) {
+                       CUtils::PrintError("You can not use an empty password");
+               } else {
+                       // Construct the salted pass
+                       char *salted_pass = (char *) malloc(iLen + uiSaltLength + 1);
+                       strcpy(salted_pass, pass1);
+                       strcpy(salted_pass + iLen, pSalt);
+
+                       CString sRet((const char*) CMD5(salted_pass, iLen + uiSaltLength));
+                       // null out our pass so it doesn't sit in memory
+                       memset(salted_pass, 0, iLen + uiSaltLength);
+                       memset(pass1, 0, iLen);
+                       memset(pass2, 0, strlen(pass2));
+                       free(salted_pass);
+                       free(pass1);
+
+                       return sRet;
+               }
+
+               memset((char*) pass1, 0, iLen); // null out our pass so it doesn't sit in memory
+               memset((char*) pass2, 0, strlen(pass2));        // null out our pass so it doesn't sit in memory
+               free(pass1);
+       }
+
+       return "";
+}
+
 char* CUtils::GetPass(const CString& sPrompt) {
        PrintPrompt(sPrompt);
        return getpass("");
diff --git a/Utils.h b/Utils.h
index 20dcb77dbd44f3c6f6d315c8813253b9b67a8e4b..f1b456f8ba454e00b25f9a1ffa3f2426de1473de 100644 (file)
--- a/Utils.h
+++ b/Utils.h
@@ -52,6 +52,7 @@ public:
        static void PrintAction(const CString& sMessage);
        static void PrintStatus(bool bSuccess, const CString& sMessage = "");
        static CString GetHashPass();
+       static CString GetSaltedHashPass(CString& sSalt, unsigned int uiSaltLength = 20);
        static char* GetPass(const CString& sPrompt);
        static bool GetInput(const CString& sPrompt, CString& sRet, const CString& sDefault = "", const CString& sHint = "");
        static bool GetBoolInput(const CString& sPrompt, bool bDefault);
index 230878e2f160350e80485bfae9bc0c7a1dcb2240..59fa7d98be0ceeb262f89269782b5370fb5e0478 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -193,9 +193,10 @@ int main(int argc, char** argv) {
 
 #endif /* HAVE_LIBSSL */
        if (bMakePass) {
-               CString sHash = CUtils::GetHashPass();
+               CString sSalt;
+               CString sHash = CUtils::GetSaltedHashPass(sSalt);
                CUtils::PrintMessage("Use this in the <User> section of your config:");
-               CUtils::PrintMessage("Pass = " + sHash + " -");
+               CUtils::PrintMessage("Pass = md5#" + sHash + "#" + sSalt + "#");
 
                return 0;
        }
diff --git a/znc.cpp b/znc.cpp
index f8674d5fd18bde4f7c17f4aa1ddc8a29e1d0d54e..d5d52d39365910f18b703e274b7eff18967c39d9 100644 (file)
--- a/znc.cpp
+++ b/znc.cpp
@@ -666,8 +666,9 @@ bool CZNC::WriteNewConfig(const CString& sConfig) {
                } while (!CUser::IsValidUserName(sUser));
 
                vsLines.push_back("<User " + sUser + ">");
-               sAnswer = CUtils::GetHashPass();
-               vsLines.push_back("\tPass       = " + sAnswer + " -");
+               CString sSalt;
+               sAnswer = CUtils::GetSaltedHashPass(sSalt);
+               vsLines.push_back("\tPass       = md5#" + sAnswer + "#" + sSalt + "#");
 
                if (CUtils::GetBoolInput("Would you like this user to be an admin?", bFirstUser)) {
                        vsLines.push_back("\tAdmin      = true");
@@ -1180,12 +1181,29 @@ bool CZNC::DoRehash(CString& sError)
                                                CUtils::PrintMessage("WARNING: AwaySuffix has been depricated, instead try -> LoadModule = awaynick %nick%_" + sValue);
                                                continue;
                                        } else if (sName.CaseCmp("Pass") == 0) {
+                                               // There are different formats for this available:
+                                               // Pass = <plain text>
+                                               // Pass = <md5 hash> -
+                                               // Pass = plain#<plain text>
+                                               // Pass = md5#<md5 hash>
+                                               // Pass = md5#<salted md5 hash>#<salt>#
+                                               // The last one is the md5 hash of 'password' + 'salt'
                                                if (sValue.Right(1) == "-") {
                                                        sValue.RightChomp();
                                                        sValue.Trim();
                                                        pUser->SetPass(sValue, true);
                                                } else {
-                                                       pUser->SetPass(sValue, false);
+                                                       CString sMethod = sValue.Token(0, false, "#");
+                                                       CString sPass = sValue.Token(1, true, "#");
+                                                       if (sMethod == "md5") {
+                                                               CString sSalt = sPass.Token(1, false, "#");
+                                                               sPass = sPass.Token(0, false, "#");
+                                                               pUser->SetPass(sPass, true, sSalt);
+                                                       } else if (sMethod == "plain") {
+                                                               pUser->SetPass(sPass, false);
+                                                       } else {
+                                                               pUser->SetPass(sValue, false);
+                                                       }
                                                }
 
                                                continue;