+ ProtocolInterface::ServerList servers;
+ ServerInstance->PI->GetServerList(servers);
+ for (ProtocolInterface::ServerList::const_iterator i = servers.begin(); i != servers.end(); ++i)
+ {
+ const ProtocolInterface::ServerInfo& server = *i;
+ if (InspIRCd::Match(server.servername, sasl_target))
+ {
+ online = true;
+ break;
+ }
+ }
+ }
+
+ bool IsOnline() const { return online; }
+};
+
+class SASLCap : public Cap::Capability
+{
+ private:
+ std::string mechlist;
+ const ServerTracker& servertracker;
+ UserCertificateAPI sslapi;
+
+ bool OnRequest(LocalUser* user, bool adding) CXX11_OVERRIDE
+ {
+ if (requiressl && sslapi && !sslapi->GetCertificate(user))
+ return false;
+
+ // Servers MUST NAK any sasl capability request if the authentication layer
+ // is unavailable.
+ return servertracker.IsOnline();
+ }
+
+ bool OnList(LocalUser* user) CXX11_OVERRIDE
+ {
+ if (requiressl && sslapi && !sslapi->GetCertificate(user))
+ return false;
+
+ // Servers MUST NOT advertise the sasl capability if the authentication layer
+ // is unavailable.
+ return servertracker.IsOnline();
+ }
+
+ const std::string* GetValue(LocalUser* user) const CXX11_OVERRIDE
+ {
+ return &mechlist;
+ }
+
+ public:
+ bool requiressl;
+ SASLCap(Module* mod, const ServerTracker& tracker)
+ : Cap::Capability(mod, "sasl")
+ , servertracker(tracker)
+ , sslapi(mod)
+ {
+ }
+
+ void SetMechlist(const std::string& newmechlist)
+ {
+ if (mechlist == newmechlist)
+ return;
+
+ mechlist = newmechlist;
+ NotifyValueChange();
+ }
+};