summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Powell <petpow@saberuk.com>2017-10-15 18:42:58 +0100
committerPeter Powell <petpow@saberuk.com>2018-11-04 15:29:06 +0000
commit79892a727e323dcc4bce7e9c0cf3c99c5fe61706 (patch)
tree63b3169ae6d1207efaea3ecd264e6d4a071598c3
parentefdb51bc9d46283e55d95cd47398cf463b401d96 (diff)
Implement support for WEBIRC attributes.
-rw-r--r--include/modules/webirc.h42
-rw-r--r--src/modules/m_cgiirc.cpp100
-rw-r--r--src/modules/m_sslinfo.cpp46
3 files changed, 183 insertions, 5 deletions
diff --git a/include/modules/webirc.h b/include/modules/webirc.h
new file mode 100644
index 000000000..4ca3b0730
--- /dev/null
+++ b/include/modules/webirc.h
@@ -0,0 +1,42 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2016-2017 Peter Powell <petpow@saberuk.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#pragma once
+
+#include "event.h"
+
+namespace WebIRC
+{
+ class EventListener;
+
+ typedef insp::flat_map<std::string, std::string, irc::insensitive_swo> FlagMap;
+}
+
+class WebIRC::EventListener
+ : public Events::ModuleEventListener
+{
+ protected:
+ EventListener(Module* mod)
+ : ModuleEventListener(mod, "event/webirc")
+ {
+ }
+
+ public:
+ virtual void OnWebIRCAuth(LocalUser* user, const FlagMap* flags) = 0;
+};
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index 8d911a5b4..d67b09c39 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -25,6 +25,7 @@
#include "inspircd.h"
#include "modules/ssl.h"
+#include "modules/webirc.h"
#include "modules/whois.h"
enum
@@ -141,16 +142,18 @@ class CommandWebIRC : public SplitCommand
StringExtItem gateway;
StringExtItem realhost;
StringExtItem realip;
+ Events::ModuleEventProvider webircevprov;
CommandWebIRC(Module* Creator)
: SplitCommand(Creator, "WEBIRC", 4)
, gateway("cgiirc_gateway", ExtensionItem::EXT_USER, Creator)
, realhost("cgiirc_realhost", ExtensionItem::EXT_USER, Creator)
, realip("cgiirc_realip", ExtensionItem::EXT_USER, Creator)
+ , webircevprov(Creator, "event/webirc")
{
allow_empty_last_param = false;
works_before_reg = true;
- this->syntax = "password gateway hostname ip";
+ this->syntax = "<password> <gateway> <hostname> <ip> [flags]";
}
CmdResult HandleLocal(LocalUser* user, const Params& parameters) CXX11_OVERRIDE
@@ -181,6 +184,33 @@ class CommandWebIRC : public SplitCommand
WriteLog("Connecting user %s is using a WebIRC gateway; changing their IP from %s to %s.",
user->uuid.c_str(), user->GetIPString().c_str(), parameters[3].c_str());
+ // If we have custom flags then deal with them.
+ WebIRC::FlagMap flags;
+ const bool hasflags = (parameters.size() > 4);
+ if (hasflags)
+ {
+ // Parse the flags.
+ irc::spacesepstream flagstream(parameters[4]);
+ for (std::string flag; flagstream.GetToken(flag); )
+ {
+ // Does this flag have a value?
+ const size_t separator = flag.find('=');
+ if (separator == std::string::npos)
+ {
+ flags[flag];
+ continue;
+ }
+
+ // The flag has a value!
+ const std::string key = flag.substr(0, separator);
+ const std::string value = flag.substr(separator + 1);
+ flags[key] = value;
+ }
+ }
+
+ // Inform modules about the WebIRC attempt.
+ FOREACH_MOD_CUSTOM(webircevprov, WebIRC::EventListener, OnWebIRCAuth, (user, (hasflags ? &flags : NULL)));
+
// Set the IP address sent via WEBIRC. We ignore the hostname and lookup
// instead do our own DNS lookups because of unreliable gateways.
ChangeIP(user, ipaddr);
@@ -207,7 +237,10 @@ class CommandWebIRC : public SplitCommand
}
};
-class ModuleCgiIRC : public Module, public Whois::EventListener
+class ModuleCgiIRC
+ : public Module
+ , public WebIRC::EventListener
+ , public Whois::EventListener
{
private:
CommandWebIRC cmd;
@@ -251,7 +284,8 @@ class ModuleCgiIRC : public Module, public Whois::EventListener
public:
ModuleCgiIRC()
- : Whois::EventListener(this)
+ : WebIRC::EventListener(this)
+ , Whois::EventListener(this)
, cmd(this)
{
}
@@ -361,6 +395,66 @@ class ModuleCgiIRC : public Module, public Whois::EventListener
return MOD_RES_PASSTHRU;
}
+ void OnWebIRCAuth(LocalUser* user, const WebIRC::FlagMap* flags) CXX11_OVERRIDE
+ {
+ // We are only interested in connection flags. If none have been
+ // given then we have nothing to do.
+ if (!flags)
+ return;
+
+ WebIRC::FlagMap::const_iterator cport = flags->find("remote-port");
+ if (cport == flags->end())
+ {
+ // If we can't parse the port then just give up.
+ uint16_t port = ConvToNum<uint16_t>(cport->second);
+ if (port)
+ {
+ switch (user->client_sa.family())
+ {
+ case AF_INET:
+ user->client_sa.in4.sin_port = htons(port);
+ break;
+
+ case AF_INET6:
+ user->client_sa.in6.sin6_port = htons(port);
+ break;
+
+ default:
+ // If we have reached this point then we have encountered a bug.
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "BUG: OnWebIRCAuth(%s): socket type %d is unknown!",
+ user->uuid.c_str(), user->client_sa.family());
+ return;
+ }
+ }
+ }
+
+ WebIRC::FlagMap::const_iterator sport = flags->find("local-port");
+ if (sport == flags->end())
+ {
+ // If we can't parse the port then just give up.
+ uint16_t port = ConvToNum<uint16_t>(sport->second);
+ if (port)
+ {
+ switch (user->server_sa.family())
+ {
+ case AF_INET:
+ user->server_sa.in4.sin_port = htons(port);
+ break;
+
+ case AF_INET6:
+ user->server_sa.in6.sin6_port = htons(port);
+ break;
+
+ default:
+ // If we have reached this point then we have encountered a bug.
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "BUG: OnWebIRCAuth(%s): socket type %d is unknown!",
+ user->uuid.c_str(), user->server_sa.family());
+ return;
+ }
+ }
+ }
+ }
+
void OnWhois(Whois::Context& whois) CXX11_OVERRIDE
{
if (!whois.IsSelfWhois() && !whois.GetSource()->HasPrivPermission("users/auspex"))
diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp
index 25415095c..a258c35a5 100644
--- a/src/modules/m_sslinfo.cpp
+++ b/src/modules/m_sslinfo.cpp
@@ -19,6 +19,7 @@
#include "inspircd.h"
#include "modules/ssl.h"
+#include "modules/webirc.h"
#include "modules/whois.h"
enum
@@ -49,6 +50,12 @@ class SSLCertExt : public ExtensionItem {
delete old;
}
+ void unset(Extensible* container)
+ {
+ void* old = unset_raw(container);
+ delete static_cast<std::string*>(old);
+ }
+
std::string serialize(SerializeFormat format, const Extensible* container, void* item) const CXX11_OVERRIDE
{
return static_cast<ssl_cert*>(item)->GetMetaLine();
@@ -154,14 +161,18 @@ class UserCertificateAPIImpl : public UserCertificateAPIBase
}
};
-class ModuleSSLInfo : public Module, public Whois::EventListener
+class ModuleSSLInfo
+ : public Module
+ , public WebIRC::EventListener
+ , public Whois::EventListener
{
CommandSSLInfo cmd;
UserCertificateAPIImpl APIImpl;
public:
ModuleSSLInfo()
- : Whois::EventListener(this)
+ : WebIRC::EventListener(this)
+ , Whois::EventListener(this)
, cmd(this)
, APIImpl(this, cmd.CertExt)
{
@@ -277,6 +288,37 @@ class ModuleSSLInfo : public Module, public Whois::EventListener
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
+
+ void OnWebIRCAuth(LocalUser* user, const WebIRC::FlagMap* flags) CXX11_OVERRIDE
+ {
+ // We are only interested in connection flags. If none have been
+ // given then we have nothing to do.
+ if (!flags)
+ return;
+
+ // We only care about the tls connection flag if the connection
+ // between the gateway and the server is secure.
+ if (!cmd.CertExt.get(user))
+ return;
+
+ WebIRC::FlagMap::const_iterator iter = flags->find("secure");
+ if (iter == flags->end())
+ {
+ // If this is not set then the connection between the client and
+ // the gateway is not secure.
+ cmd.CertExt.unset(user);
+ return;
+ }
+
+ // Create a fake ssl_cert for the user.
+ ssl_cert* cert = new ssl_cert;
+ cert->error = "WebIRC users can not specify valid certs yet";
+ cert->invalid = true;
+ cert->revoked = true;
+ cert->trusted = false;
+ cert->unknownsigner = true;
+ cmd.CertExt.set(user, cert);
+ }
};
MODULE_INIT(ModuleSSLInfo)