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
class CMD5 {
protected:
char m_szMD5[33];
+ unsigned char* m_pszMD5;
public:
CMD5();
}
char* MakeHash(const char* szText, uint32 nTextLen);
+ unsigned char* GetHash();
protected:
void md5_starts( md5_context *ctx ) const;
*/
#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;
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() {
if (it->Equals("saslauthd") || it->Equals("auxprop")) {
m_sMethod += *it + " ";
} else {
- CUtils::PrintError("Ignoring invalid SASL pwcheck method: " + *it);
- sMessage = "Ignored invalid SASL pwcheck method";
+ 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";
+ }
}
}
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;
bSuccess = true;
DEBUG("saslauth: Found [" + sUsername + "] in cache");
} else if (sasl_server_new("znc", NULL, NULL, NULL, NULL, m_cbs, 0, &sasl_conn) == SASL_OK &&
- sasl_checkpass(sasl_conn, sUsername.c_str(), sUsername.size(), sPassword.c_str(), sPassword.size()) == SASL_OK) {
+ sasl_checkpass(sasl_conn, sUsername.AsLower().c_str(), sUsername.AsLower().size(), sPassword.c_str(), sPassword.size()) == SASL_OK) {
m_Cache.AddItem(sCacheKey);
DEBUG("saslauth: Successful SASL authentication [" + sUsername + "]");
if (bSuccess) {
if (!pUser) {
CString sErr;
- pUser = new CUser(sUsername);
+ pUser = new CUser(sUsername.AsLower());
if (ShouldCloneUser()) {
CUser *pBaseUser = CZNC::Get().FindUser(CloneUser());
}
}
+ 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, "::");
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) {
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;
}
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) {
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")
MODCONSTRUCTOR(CMissingMotd) {}
virtual void OnClientLogin() override {
- PutUser(":irc.znc.in 422 :MOTD File is missing");
+ PutUser(":znc.afternet.org 422 :MOTD File is missing");
}
};
if (!GetNetwork()->GetIRCSock()) {
// if we are not connected to any IRC server, send
// an empty or module-nick filled response.
- PutUser(":irc.znc.in 303 " + GetClient()->GetNick() + " :" + sBNCNicks);
+ PutUser(":znc.afternet.org 303 " + GetClient()->GetNick() + " :" + sBNCNicks);
} else {
// We let the server handle this request and then act on
// the 303 response from the IRC server.
if (sAction == "topic") {
pChannel = FindChannel(sKey);
if (pChannel && !(it->second).empty()) {
- PutChan(pChannel->GetNicks(), ":irc.znc.in TOPIC " + pChannel->GetName() + " :" + it->second);
+ PutChan(pChannel->GetNicks(), ":znc.afternet.org TOPIC " + pChannel->GetName() + " :" + it->second);
pChannel->SetTopic(it->second);
}
}
pChannel->SetTopic(sTopic);
SaveTopic(pChannel);
} else {
- pUser->PutUser(":irc.znc.in 482 " + pClient->GetNick() + " " + sChannel + " :You're not channel operator");
+ pUser->PutUser(":znc.afternet.org 482 " + pClient->GetNick() + " " + sChannel + " :You're not channel operator");
}
} else {
sTopic = pChannel->GetTopic();
if (sTopic.empty()) {
- pUser->PutUser(":irc.znc.in 331 " + pClient->GetNick() + " " + sChannel + " :No topic is set.");
+ pUser->PutUser(":znc.afternet.org 331 " + pClient->GetNick() + " " + sChannel + " :No topic is set.");
} else {
- pUser->PutUser(":irc.znc.in 332 " + pClient->GetNick() + " " + sChannel + " :" + sTopic);
+ pUser->PutUser(":znc.afternet.org 332 " + pClient->GetNick() + " " + sChannel + " :" + sTopic);
}
}
} else {
- pUser->PutUser(":irc.znc.in 442 " + pClient->GetNick() + " " + sChannel + " :You're not on that channel");
+ pUser->PutUser(":znc.afternet.org 442 " + pClient->GetNick() + " " + sChannel + " :You're not on that channel");
}
return HALT;
}
const CString GetIRCServer(CIRCNetwork *pNetwork) {
if (!pNetwork) {
- return "irc.znc.in";
+ return "znc.afternet.org";
}
const CString& sServer = pNetwork->GetIRCServer();
if (!sServer.empty())
return sServer;
- return "irc.znc.in";
+ return "znc.afternet.org";
}
bool PutChan(const CString& sChan, const CString& sLine, bool bIncludeCurUser = true, bool bIncludeClient = true, CUser* pUser = NULL, CClient* pClient = NULL) {
#include <znc/IRCNetwork.h>
#include <znc/IRCSock.h>
+#include <znc/User.h>
static const struct {
const char *szName;
}
void Set(const CString& sLine) {
- SetNV("username", sLine.Token(1));
- SetNV("password", sLine.Token(2));
+ 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") + "]");
+ 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) {
- CString sMechanisms = sLine.Token(1, true).AsUpper();
+ if (!SaslImpersonation()) {
+ CString sMechanisms = sLine.Token(1, true).AsUpper();
- if (!sMechanisms.empty()) {
- VCString vsMechanisms;
- sMechanisms.Split(" ", vsMechanisms);
+ if (!sMechanisms.empty()) {
+ VCString vsMechanisms;
+ sMechanisms.Split(" ", vsMechanisms);
- for (VCString::const_iterator it = vsMechanisms.begin(); it != vsMechanisms.end(); ++it) {
- if (!SupportsMechanism(*it)) {
- PutModule("Unsupported mechanism: " + *it);
- return;
- }
- }
+ for (VCString::const_iterator it = vsMechanisms.begin(); it != vsMechanisms.end(); ++it) {
+ if (!SupportsMechanism(*it)) {
+ PutModule("Unsupported mechanism: " + *it);
+ return;
+ }
+ }
- SetNV(NV_MECHANISMS, sMechanisms);
- }
+ SetNV(NV_MECHANISMS, sMechanisms);
+ }
- PutModule("Current mechanisms set: " + GetMechanismsString());
+ PutModule("Current mechanisms set: " + GetMechanismsString());
+ }
}
void RequireAuthCommand(const CString& sLine) {
- if (!sLine.Token(1).empty()) {
- SetNV(NV_REQUIRE_AUTH, sLine.Token(1));
- }
-
- if (GetNV(NV_REQUIRE_AUTH).ToBool()) {
- PutModule("We require SASL negotiation to connect");
- } else {
- PutModule("We will connect even if SASL fails");
+ if (!SaslImpersonation()) {
+ if (!sLine.Token(1).empty()) {
+ SetNV(NV_REQUIRE_AUTH, sLine.Token(1));
+ }
+
+ if (GetNV(NV_REQUIRE_AUTH).ToBool()) {
+ PutModule("We require SASL negotiation to connect");
+ } else {
+ PutModule("We will connect even if SASL fails");
+ }
}
}
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 {
return NetworkPage(WebSock, Tmpl, pNetwork->GetUser(), pNetwork);
} else if (sPageName == "delnetwork") {
+ if (!spSession->IsAdmin()) {
+ return false;
+ }
CString sUser = WebSock.GetParam("user");
if (sUser.empty() && !WebSock.IsPost()) {
sUser = WebSock.GetParam("user", false);
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);
breadNet["Text"] = "Edit Network [" + pNetwork->GetName() + "]";
- 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();
+ 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();
VCString vsArgs;
- pNetwork->DelServers();
- WebSock.GetRawParam("servers").Split("\n", vsArgs);
- for (unsigned int a = 0; a < vsArgs.size(); a++) {
- pNetwork->AddServer(vsArgs[a].Trim_n());
+ if (spSession->IsAdmin()) {
+ WebSock.GetRawParam("servers").Split("\n", vsArgs);
+ if (vsArgs.size()) {
+ pNetwork->DelServers();
+ for (unsigned int a = 0; a < vsArgs.size(); a++) {
+ pNetwork->AddServer(vsArgs[a].Trim_n());
+ }
+ }
}
WebSock.GetRawParam("fingerprints").Split("\n", vsArgs);
}
}
+ 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();
}
void CClient::SendRequiredPasswordNotice() {
- PutClient(":irc.znc.in 464 " + GetNick() + " :Password required");
- PutClient(":irc.znc.in NOTICE AUTH :*** "
+ PutClient(":znc.afternet.org 464 " + GetNick() + " :Password required");
+ PutClient(":znc.afternet.org NOTICE AUTH :*** "
"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.");
+ PutClient(":znc.afternet.org NOTICE AUTH :*** "
+ "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) {
// All PONGs are generated by ZNC. We will still forward this to
// the ircd, but all PONGs from irc will be blocked.
if (sLine.length() >= 5)
- PutClient(":irc.znc.in PONG irc.znc.in " + sLine.substr(5));
+ PutClient(":znc.afternet.org PONG znc.afternet.org " + sLine.substr(5));
else
- PutClient(":irc.znc.in PONG irc.znc.in");
+ PutClient(":znc.afternet.org PONG znc.afternet.org");
} else if (sCommand.Equals("PONG")) {
// Block PONGs, we already responded to the pings
return;
void CClient::RefuseLogin(const CString& sReason) {
PutStatus("Bad username and/or password.");
- PutClient(":irc.znc.in 464 " + GetNick() + " :" + sReason);
+ PutClient(":znc.afternet.org 464 " + GetNick() + " :" + sReason);
Close(Csock::CLT_AFTERWRITE);
}
CString sHost = m_pNetwork ? m_pNetwork->GetBindHost() : m_pUser->GetBindHost();
if (sHost.empty()) {
- sHost = "irc.znc.in";
+ sHost = "znc.afternet.org";
}
return GetNick() + "!" + (m_pNetwork ? m_pNetwork->GetIdent() : m_pUser->GetIdent()) + "@" + sHost;
void CClient::RespondCap(const CString& sResponse)
{
- PutClient(":irc.znc.in CAP " + GetNick() + " " + sResponse);
+ PutClient(":znc.afternet.org CAP " + GetNick() + " " + sResponse);
}
void CClient::HandleCap(const CString& sLine)
}
RespondCap("ACK :" + sList.TrimSuffix_n(" "));
} else {
- PutClient(":irc.znc.in 410 " + GetNick() + " " + sSubCmd + " :Invalid CAP subcommand");
+ PutClient(":znc.afternet.org 410 " + GetNick() + " " + sSubCmd + " :Invalid CAP subcommand");
}
}
void CClient::ParsePass(const CString& sAuthLine) {
- // [user[@identifier][/network]:]password
+ // [network[/user[@identifier]/]]password
- const size_t uColon = sAuthLine.find(":");
- if (uColon != CString::npos) {
- m_sPass = sAuthLine.substr(uColon + 1);
-
- ParseUser(sAuthLine.substr(0, uColon));
+ const size_t uSlash = sAuthLine.find("/");
+ if (uSlash != CString::npos) {
+ 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;
+ }
} else {
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);
-
- ParseIdentifier(sAuthLine.substr(0, uSlash));
- } else {
+ // user[@identifier]
ParseIdentifier(sAuthLine);
- }
}
void CClient::ParseIdentifier(const CString& sAuthLine) {
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()) {
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) {
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;
}
CString sModRet;
+ CModule* pModule;
switch (eType) {
case CModInfo::GlobalModule:
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:
}
CString sModRet;
+ CModule* pModule;
switch (eType) {
case CModInfo::GlobalModule:
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:
if (!m_pUser->IsAdmin()) {
AddCommandHelp(Table, "ListClients", "", "List all clients connected to your ZNC user", sFilter);
}
- 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, "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);
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, "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);
pClient->SetPlaybackActive(true);
if (m_RawBuffer.IsEmpty()) {
- pClient->PutClient(":irc.znc.in 001 " + pClient->GetNick() + " :- Welcome to ZNC -");
+ pClient->PutClient(":znc.afternet.org 001 " + pClient->GetNick() + " :- Welcome to ZNC -");
} else {
const CString& sClientNick = pClient->GetNick(false);
MCString msParams;
if (m_bIRCAway) {
// If they want to know their away reason they'll have to whois
// themselves. At least we can tell them their away status...
- pClient->PutClient(":irc.znc.in 306 " + GetIRCNick().GetNick() + " :You have been marked as being away");
+ pClient->PutClient(":znc.afternet.org 306 " + GetIRCNick().GetNick() + " :You have been marked as being away");
}
const vector<CChan*>& vChans = GetChans();
switch (uRaw) {
case 1: { // :irc.server.com 001 nick :Welcome to the Internet Relay Network nick
- if (m_bAuthed && sServer == "irc.znc.in") {
+ if (m_bAuthed && sServer == "znc.afternet.org") {
// m_bAuthed == true => we already received another 001 => we might be in a traffic loop
m_pNetwork->PutStatus("ZNC seems to be connected to itself, disconnecting...");
Quit();
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());
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();
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);
if (CZNC::Get().AllowConnectionFrom(sHost)) {
GLOBALMODULECALL(OnClientConnect(pClient, sHost, uPort), NOTHING);
} else {
- pClient->Write(":irc.znc.in 464 unknown-nick :Too many anonymous connections from your IP\r\n");
+ pClient->Write(":znc.afternet.org 464 unknown-nick :Too many anonymous connections from your IP\r\n");
pClient->Close(Csock::CLT_AFTERWRITE);
GLOBALMODULECALL(OnFailedLogin("", sHost), NOTHING);
}
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) ] ) \
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;
}
BounceAllClients();
}
- pClient->PutClient(":irc.znc.in 001 " + pClient->GetNick() + " :- Welcome to ZNC -");
+ pClient->PutClient(":znc.afternet.org 001 " + pClient->GetNick() + " :- Welcome to ZNC -");
m_vClients.push_back(pClient);
}