/* * InspIRCd -- Internet Relay Chat Daemon * * Copyright (C) 2019-2024 Sadie Powell * Copyright (C) 2019 linuxdaemon * Copyright (C) 2014 Googolplexed * Copyright (C) 2012 Robby * Copyright (C) 2012 Attila Molnar * Copyright (C) 2010 Daniel De Graaf * * This file is part of InspIRCd. InspIRCd is free software: you can * redistribute it and/or modify it under the terms of the GNU General Public * License as published by the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "inspircd.h" #include "modules/account.h" #include "stringutils.h" class ModulePassForward final : public Module { private: Account::API accountapi; std::string nickrequired, forwardmsg, forwardcmd; public: ModulePassForward() : Module(VF_VENDOR, "Allows an account password to be forwarded to a services pseudoclient such as NickServ.") , accountapi(this) { } void ReadConfig(ConfigStatus& status) override { const auto& tag = ServerInstance->Config->ConfValue("passforward"); nickrequired = tag->getString("nick", "NickServ"); forwardmsg = tag->getString("forwardmsg", "NOTICE %nick% :*** Forwarding password to %nickrequired%"); forwardcmd = tag->getString("cmd", "SQUERY %nickrequired% :IDENTIFY %nick% %pass%", 1); } std::string FormatStr(const LocalUser* user, const std::string& format, const std::string& pass) { return Template::Replace(format, { { "nick", user->nick, }, { "nickrequired", nickrequired, }, { "pass", pass, }, { "user", user->GetRealUser(), }, }); } void OnPostConnect(User* ruser) override { LocalUser* user = IS_LOCAL(ruser); if (!user || user->password.empty()) return; // If the connect class requires a password, don't forward it if (!user->GetClass()->password.empty()) return; if (accountapi && accountapi->GetAccountName(user)) { // User is logged in already (probably via SASL) don't forward the password return; } ForwardPass(user, user->password); } void OnPostCommand(Command* command, const CommandBase::Params& parameters, LocalUser* user, CmdResult result, bool loop) override { if (command->name == "NICK" && parameters.size() > 1) ForwardPass(user, parameters[1]); } void ForwardPass(LocalUser* user, const std::string& pass) { if (!nickrequired.empty()) { /* Check if nick exists and is on a services server. */ auto* u = ServerInstance->Users.Find(nickrequired); if (!u || !u->server->IsService()) return; } if (!forwardmsg.empty()) ServerInstance->Parser.ProcessBuffer(user, FormatStr(user, forwardmsg, pass)); ServerInstance->Parser.ProcessBuffer(user, FormatStr(user, forwardcmd, pass)); } }; MODULE_INIT(ModulePassForward)