diff options
| author | 2021-02-01 18:50:31 +0000 | |
|---|---|---|
| committer | 2021-02-01 18:57:52 +0000 | |
| commit | 9ef90acced21732c31d8cf09b9105d729ac89fb9 (patch) | |
| tree | da4cbf801c0271dcfdccdfa2e9fdddf1e79ad8b9 /src/modules/m_sslinfo.cpp | |
| parent | Make MyClass private and move everything to GetClass. (diff) | |
| parent | Duplicate the stdout file handle when used for logging. (diff) | |
Merge branch 'insp3' into master.
Diffstat (limited to 'src/modules/m_sslinfo.cpp')
| -rw-r--r-- | src/modules/m_sslinfo.cpp | 113 |
1 files changed, 87 insertions, 26 deletions
diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp index cf580b081..b542fb580 100644 --- a/src/modules/m_sslinfo.cpp +++ b/src/modules/m_sslinfo.cpp @@ -144,54 +144,110 @@ class UserCertificateAPIImpl : public UserCertificateAPIBase } }; -class CommandSSLInfo : public Command +class CommandSSLInfo : public SplitCommand { - public: - UserCertificateAPIImpl sslapi; + private: + ChanModeReference sslonlymode; - CommandSSLInfo(Module* Creator) - : Command(Creator, "SSLINFO", 1) - , sslapi(Creator) + void HandleUserInternal(LocalUser* source, User* target, bool verbose) { - syntax = { "<nick>" }; + ssl_cert* cert = sslapi.GetCertificate(target); + if (!cert) + { + source->WriteNotice(InspIRCd::Format("*** %s is not connected using TLS (SSL).", target->nick.c_str())); + } + else if (cert->GetError().length()) + { + source->WriteNotice(InspIRCd::Format("*** %s is connected using TLS (SSL) but has not specified a valid client certificate (%s).", + target->nick.c_str(), cert->GetError().c_str())); + } + else if (!verbose) + { + source->WriteNotice(InspIRCd::Format("*** %s is connected using TLS (SSL) with a valid client certificate (%s).", + target->nick.c_str(), cert->GetFingerprint().c_str())); + } + else + { + source->WriteNotice("*** Distinguished Name: " + cert->GetDN()); + source->WriteNotice("*** Issuer: " + cert->GetIssuer()); + source->WriteNotice("*** Key Fingerprint: " + cert->GetFingerprint()); + } } - CmdResult Handle(User* user, const Params& parameters) override + CmdResult HandleUser(LocalUser* source, const std::string& nick) { - User* target = ServerInstance->Users.FindNick(parameters[0]); + User* target = ServerInstance->Users.FindNick(nick); + if (!target || target->registered != REG_ALL) + { + source->WriteNumeric(Numerics::NoSuchNick(nick)); + return CmdResult::FAILURE; + } - if ((!target) || (target->registered != REG_ALL)) + if (operonlyfp && !source->IsOper() && source != target) { - user->WriteNumeric(Numerics::NoSuchNick(parameters[0])); + source->WriteNumeric(ERR_NOPRIVILEGES, "You must be a server operator to view TLS (SSL) client certificate information for other users."); return CmdResult::FAILURE; } - bool operonlyfp = ServerInstance->Config->ConfValue("sslinfo")->getBool("operonly"); - if (operonlyfp && !user->IsOper() && target != user) + HandleUserInternal(source, target, true); + return CmdResult::SUCCESS; + } + + CmdResult HandleChannel(LocalUser* source, const std::string& channel) + { + Channel* chan = ServerInstance->FindChan(channel); + if (!chan) { - user->WriteNotice("*** You cannot view TLS (SSL) client certificate information for other users"); + source->WriteNumeric(Numerics::NoSuchChannel(channel)); return CmdResult::FAILURE; } - ssl_cert* cert = sslapi.GetCertificate(target); - if (!cert) + if (operonlyfp && !source->IsOper()) { - user->WriteNotice(InspIRCd::Format("*** %s is not connected using TLS (SSL).", target->nick.c_str())); + source->WriteNumeric(ERR_NOPRIVILEGES, "You must be a server operator to view TLS (SSL) client certificate information for channels."); + return CmdResult::FAILURE; } - else if (cert->GetError().length()) + + if (!source->IsOper() && chan->GetPrefixValue(source) < OP_VALUE) { - user->WriteNotice(InspIRCd::Format("*** %s is connected using TLS (SSL) but has not specified a valid client certificate (%s).", - target->nick.c_str(), cert->GetError().c_str())); + source->WriteNumeric(ERR_CHANOPRIVSNEEDED, chan->name, "You must be a channel operator."); + return CmdResult::FAILURE; } - else + + if (sslonlymode) { - user->WriteNotice("*** Distinguished Name: " + cert->GetDN()); - user->WriteNotice("*** Issuer: " + cert->GetIssuer()); - user->WriteNotice("*** Key Fingerprint: " + cert->GetFingerprint()); + source->WriteNotice(InspIRCd::Format("*** %s %s have channel mode +%c (%s) set.", + chan->name.c_str(), chan->IsModeSet(sslonlymode) ? "does" : "does not", + sslonlymode->GetModeChar(), sslonlymode->name.c_str())); } + const Channel::MemberMap& userlist = chan->GetUsers(); + for (Channel::MemberMap::const_iterator i = userlist.begin(); i != userlist.end(); ++i) + HandleUserInternal(source, i->first, false); + return CmdResult::SUCCESS; } + + public: + UserCertificateAPIImpl sslapi; + bool operonlyfp; + + CommandSSLInfo(Module* Creator) + : SplitCommand(Creator, "SSLINFO", 1) + , sslonlymode(Creator, "sslonly") + , sslapi(Creator) + { + allow_empty_last_param = false; + syntax = { "<channel|nick>" }; + } + + CmdResult HandleLocal(LocalUser* user, const Params& parameters) override + { + if (ServerInstance->IsChannel(parameters[0])) + return HandleChannel(user, parameters[0]); + else + return HandleUser(user, parameters[0]); + } }; class ModuleSSLInfo @@ -218,14 +274,19 @@ class ModuleSSLInfo { } + void ReadConfig(ConfigStatus& status) override + { + auto tag = ServerInstance->Config->ConfValue("sslinfo"); + cmd.operonlyfp = tag->getBool("operonly"); + } + void OnWhois(Whois::Context& whois) override { ssl_cert* cert = cmd.sslapi.GetCertificate(whois.GetTarget()); if (cert) { whois.SendLine(RPL_WHOISSECURE, "is using a secure connection"); - bool operonlyfp = ServerInstance->Config->ConfValue("sslinfo")->getBool("operonly"); - if ((!operonlyfp || whois.IsSelfWhois() || whois.GetSource()->IsOper()) && !cert->fingerprint.empty()) + if ((!cmd.operonlyfp || whois.IsSelfWhois() || whois.GetSource()->IsOper()) && !cert->fingerprint.empty()) whois.SendLine(RPL_WHOISCERTFP, InspIRCd::Format("has TLS (SSL) client certificate fingerprint %s", cert->fingerprint.c_str())); } } |
