+ return CMD_FAILURE;
+ }
+};
+
+class CommandSASL : public Command
+{
+ public:
+ SimpleExtItem<SaslAuthenticator>& authExt;
+ CommandSASL(Module* Creator, SimpleExtItem<SaslAuthenticator>& ext) : Command(Creator, "SASL", 2), authExt(ext)
+ {
+ this->flags_needed = FLAG_SERVERONLY; // should not be called by users
+ }
+
+ CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
+ {
+ User* target = ServerInstance->FindUUID(parameters[1]);
+ if (!target)
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "User not found in sasl ENCAP event: %s", parameters[1].c_str());
+ return CMD_FAILURE;
+ }
+
+ SaslAuthenticator *sasl = authExt.get(target);
+ if (!sasl)
+ return CMD_FAILURE;
+
+ SaslState state = sasl->ProcessInboundMessage(parameters);
+ if (state == SASL_DONE)
+ {
+ sasl->AnnounceState();
+ authExt.unset(target);
+ }
+ return CMD_SUCCESS;
+ }
+
+ RouteDescriptor GetRouting(User* user, const Params& parameters) CXX11_OVERRIDE
+ {
+ return ROUTE_BROADCAST;
+ }
+};
+
+class ModuleSASL : public Module
+{
+ SimpleExtItem<SaslAuthenticator> authExt;
+ ServerTracker servertracker;
+ SASLCap cap;
+ CommandAuthenticate auth;
+ CommandSASL sasl;
+ Events::ModuleEventProvider sasleventprov;
+
+ public:
+ ModuleSASL()
+ : authExt("sasl_auth", ExtensionItem::EXT_USER, this)
+ , servertracker(this)
+ , cap(this, servertracker)
+ , auth(this, authExt, cap)
+ , sasl(this, authExt)
+ , sasleventprov(this, "event/sasl")
+ {
+ saslevprov = &sasleventprov;
+ }
+
+ void init() CXX11_OVERRIDE
+ {
+ if (!ServerInstance->Modules->Find("m_services_account.so") || !ServerInstance->Modules->Find("m_cap.so"))
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "WARNING: m_services_account and m_cap are not loaded! m_sasl will NOT function correctly until these two modules are loaded!");
+ }
+
+ void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
+ {
+ std::string target = ServerInstance->Config->ConfValue("sasl")->getString("target");
+ if (target.empty())
+ throw ModuleException("<sasl:target> must be set to the name of your services server!");
+
+ sasl_target = target;
+ servertracker.Reset();
+ }
+
+ void OnDecodeMetaData(Extensible* target, const std::string& extname, const std::string& extdata) CXX11_OVERRIDE
+ {
+ if ((target == NULL) && (extname == "saslmechlist"))
+ cap.SetMechlist(extdata);
+ }
+
+ Version GetVersion() CXX11_OVERRIDE
+ {
+ return Version("Provides support for IRC Authentication Layer (aka: SASL) via AUTHENTICATE.", VF_VENDOR);