From ec1e85cb3dbe7c733faa7dbd850459a41b7e5144 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 15 Jan 2014 23:31:28 -0500 Subject: [PATCH] Add m_starttls and remove it from m_ssl_gnutls, which allows it to work with both openssl and gnutls --- docs/conf/modules.conf.example | 6 ++ src/configreader.cpp | 1 + src/modules/extra/m_ssl_gnutls.cpp | 66 +--------------- src/modules/m_starttls.cpp | 122 +++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 65 deletions(-) create mode 100644 src/modules/m_starttls.cpp diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index ff7210001..2ab1adebf 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -1806,6 +1806,12 @@ # # # +#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# +# StartTLS module: Implements STARTTLS, which allows clients # +# connected to non SSL enabled ports to enable SSL, if a proper SSL # +# module is loaded (either m_ssl_gnutls or m_ssl_openssl). # +# + #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # SVSHold module: Implements SVSHOLD. Like Q:Lines, but can only be # # added/removed by Services. # diff --git a/src/configreader.cpp b/src/configreader.cpp index 2320a44b1..0f6d414dd 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -335,6 +335,7 @@ struct DeprecatedConfig static const DeprecatedConfig ChangedConfig[] = { { "bind", "transport", "", "has been moved to as of 2.0" }, { "die", "value", "", "you need to reread your config" }, + { "gnutls", "starttls", "", "has been replaced with m_starttls as of 2.2" }, { "link", "autoconnect", "", "2.0+ does not use this attribute - define tags instead" }, { "link", "transport", "", "has been moved to as of 2.0" }, { "module", "name", "m_chanprotect.so", "has been replaced with m_customprefix as of 2.2" }, diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index f894043b7..0e0dc64b4 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -548,57 +548,6 @@ info_done_dealloc: } }; -class CommandStartTLS : public SplitCommand -{ - IOHook& hook; - - public: - bool enabled; - CommandStartTLS(Module* mod, IOHook& Hook) - : SplitCommand(mod, "STARTTLS") - , hook(Hook) - { - enabled = true; - works_before_reg = true; - } - - CmdResult HandleLocal(const std::vector ¶meters, LocalUser *user) - { - if (!enabled) - { - user->WriteNumeric(691, ":STARTTLS is not enabled"); - return CMD_FAILURE; - } - - if (user->registered == REG_ALL) - { - user->WriteNumeric(691, ":STARTTLS is not permitted after client registration is complete"); - } - else - { - if (!user->eh.GetIOHook()) - { - user->WriteNumeric(670, ":STARTTLS successful, go ahead with TLS handshake"); - /* We need to flush the write buffer prior to adding the IOHook, - * otherwise we'll be sending this line inside the SSL session - which - * won't start its handshake until the client gets this line. Currently, - * we assume the write will not block here; this is usually safe, as - * STARTTLS is sent very early on in the registration phase, where the - * user hasn't built up much sendq. Handling a blocked write here would - * be very annoying. - */ - user->eh.DoWrite(); - user->eh.AddIOHook(&hook); - hook.OnStreamSocketAccept(&user->eh, NULL, NULL); - } - else - user->WriteNumeric(691, ":STARTTLS failure"); - } - - return CMD_FAILURE; - } -}; - class ModuleSSLGnuTLS : public Module { GnuTLSIOHook iohook; @@ -611,13 +560,9 @@ class ModuleSSLGnuTLS : public Module bool dh_alloc; RandGen randhandler; - CommandStartTLS starttls; - - GenericCap capHandler; public: - ModuleSSLGnuTLS() - : iohook(this), starttls(this, iohook), capHandler(this, "tls") + ModuleSSLGnuTLS() : iohook(this) { #ifndef GNUTLS_HAS_RND gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); @@ -651,7 +596,6 @@ class ModuleSSLGnuTLS : public Module sslports.clear(); ConfigTag* Conf = ServerInstance->Config->ConfValue("gnutls"); - starttls.enabled = Conf->getBool("starttls", true); if (Conf->getBool("showports", true)) { @@ -919,8 +863,6 @@ class ModuleSSLGnuTLS : public Module { if (!sslports.empty()) tokens["SSL"] = sslports; - if (starttls.enabled) - tokens["STARTTLS"]; } void OnHookIO(StreamSocket* user, ListenSocket* lsb) CXX11_OVERRIDE @@ -937,12 +879,6 @@ class ModuleSSLGnuTLS : public Module if (user->eh.GetIOHook() == &iohook) iohook.TellCiphersAndFingerprint(user); } - - void OnEvent(Event& ev) CXX11_OVERRIDE - { - if (starttls.enabled) - capHandler.HandleEvent(ev); - } }; MODULE_INIT(ModuleSSLGnuTLS) diff --git a/src/modules/m_starttls.cpp b/src/modules/m_starttls.cpp new file mode 100644 index 000000000..09c9b4f0f --- /dev/null +++ b/src/modules/m_starttls.cpp @@ -0,0 +1,122 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2014 Adam + * + * 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/ssl.h" +#include "modules/cap.h" + +// From IRCv3 tls-3.1 +enum +{ + RPL_STARTTLS = 670, + ERR_STARTTLS = 691 +}; + +class CommandStartTLS : public SplitCommand +{ + dynamic_reference_nocheck& ssl; + + public: + CommandStartTLS(Module* mod, dynamic_reference_nocheck& s) + : SplitCommand(mod, "STARTTLS") + , ssl(s) + { + works_before_reg = true; + } + + CmdResult HandleLocal(const std::vector& parameters, LocalUser* user) + { + if (!ssl) + { + user->WriteNumeric(ERR_STARTTLS, ":STARTTLS is not enabled"); + return CMD_FAILURE; + } + + if (user->registered == REG_ALL) + { + user->WriteNumeric(ERR_STARTTLS, ":STARTTLS is not permitted after client registration is complete"); + return CMD_FAILURE; + } + + if (user->eh.GetIOHook()) + { + user->WriteNumeric(ERR_STARTTLS, ":STARTTLS failure"); + return CMD_FAILURE; + } + + user->WriteNumeric(RPL_STARTTLS, ":STARTTLS successful, go ahead with TLS handshake"); + /* We need to flush the write buffer prior to adding the IOHook, + * otherwise we'll be sending this line inside the SSL session - which + * won't start its handshake until the client gets this line. Currently, + * we assume the write will not block here; this is usually safe, as + * STARTTLS is sent very early on in the registration phase, where the + * user hasn't built up much sendq. Handling a blocked write here would + * be very annoying. + */ + user->eh.DoWrite(); + + user->eh.AddIOHook(*ssl); + ssl->OnStreamSocketAccept(&user->eh, NULL, NULL); + + return CMD_SUCCESS; + } +}; + +class ModuleStartTLS : public Module +{ + CommandStartTLS starttls; + GenericCap tls; + dynamic_reference_nocheck ssl; + + public: + ModuleStartTLS() + : starttls(this, ssl) + , tls(this, "tls") + , ssl(this, "ssl") + { + } + + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* conf = ServerInstance->Config->ConfValue("starttls"); + + std::string newprovider = conf->getString("provider"); + if (newprovider.empty()) + ssl.SetProvider("ssl"); + else + ssl.SetProvider("ssl/" + newprovider); + } + + void OnEvent(Event& ev) CXX11_OVERRIDE + { + tls.HandleEvent(ev); + } + + void On005Numeric(std::map& tokens) CXX11_OVERRIDE + { + tokens["STARTTLS"]; + } + + Version GetVersion() CXX11_OVERRIDE + { + return Version("Provides support for the STARTTLS command", VF_VENDOR); + } +}; + +MODULE_INIT(ModuleStartTLS) -- 2.39.5