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());
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() {
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; }
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);
CString m_sRealName;
CString m_sVHost;
CString m_sPass;
+ CString m_sPassSalt;
CString m_sStatusPrefix;
CString m_sDefaultChanModes;
CString m_sChanPrefixes;
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("");
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);
#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;
}
} 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");
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;