]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_ssl_openssl.cpp
Update copyright headers.
[user/henk/code/inspircd.git] / src / modules / extra / m_ssl_openssl.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2020 Matt Schatz <genius3000@g3k.solutions>
5  *   Copyright (C) 2019 linuxdaemon <linuxdaemon.irc@gmail.com>
6  *   Copyright (C) 2017 Wade Cline <wadecline@hotmail.com>
7  *   Copyright (C) 2014, 2016 Adam <Adam@anope.org>
8  *   Copyright (C) 2014 Julien Vehent <julien@linuxwall.info>
9  *   Copyright (C) 2013-2014, 2016-2021 Sadie Powell <sadie@witchery.services>
10  *   Copyright (C) 2012-2017 Attila Molnar <attilamolnar@hush.com>
11  *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
12  *   Copyright (C) 2012 ChrisTX <xpipe@hotmail.de>
13  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
14  *   Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
15  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
16  *   Copyright (C) 2006-2008, 2010 Craig Edwards <brain@inspircd.org>
17  *   Copyright (C) 2006 Oliver Lupton <om@inspircd.org>
18  *
19  * This file is part of InspIRCd.  InspIRCd is free software: you can
20  * redistribute it and/or modify it under the terms of the GNU General Public
21  * License as published by the Free Software Foundation, version 2.
22  *
23  * This program is distributed in the hope that it will be useful, but WITHOUT
24  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
25  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
26  * details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
30  */
31
32 /// $CompilerFlags: find_compiler_flags("openssl" "")
33 /// $LinkerFlags: find_linker_flags("openssl" "-lssl -lcrypto")
34
35 /// $PackageInfo: require_system("arch") openssl pkgconf
36 /// $PackageInfo: require_system("centos") openssl-devel pkgconfig
37 /// $PackageInfo: require_system("darwin") openssl pkg-config
38 /// $PackageInfo: require_system("debian") libssl-dev openssl pkg-config
39 /// $PackageInfo: require_system("ubuntu") libssl-dev openssl pkg-config
40
41
42 #include "inspircd.h"
43 #include "iohook.h"
44 #include "modules/ssl.h"
45
46 #ifdef __GNUC__
47 # pragma GCC diagnostic push
48 #endif
49
50 // Ignore OpenSSL deprecation warnings on OS X Lion and newer.
51 #if defined __APPLE__
52 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
53 #endif
54
55 // LibreSSL lies about the version of OpenSSL it is compatible with and is a general pain
56 // to support. Support for it was removed in the master branch at the same time that
57 // support for OpenSSL pre-1.1 was.
58 #if defined __GNUC__ && defined LIBRESSL_VERSION_NUMBER
59 # warning LibreSSL support will be discontinued in the future. Consider using the ssl_gnutls or ssl_mbedtls modules instead.
60 #endif
61
62 // Fix warnings about the use of `long long` on C++03.
63 #if defined __clang__
64 # pragma clang diagnostic ignored "-Wc++11-long-long"
65 #elif defined __GNUC__
66 # pragma GCC diagnostic ignored "-Wlong-long"
67 #endif
68
69 #include <openssl/ssl.h>
70 #include <openssl/err.h>
71 #include <openssl/dh.h>
72
73 #ifdef __GNUC__
74 # pragma GCC diagnostic pop
75 #endif
76
77 #ifdef _WIN32
78 # pragma comment(lib, "ssleay32.lib")
79 # pragma comment(lib, "libeay32.lib")
80 #endif
81
82 // Compatibility layer to allow OpenSSL 1.0 to use the 1.1 API.
83 #if ((defined LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L))
84
85 // BIO is opaque in OpenSSL 1.1 but the access API does not exist in 1.0.
86 # define BIO_get_data(BIO) BIO->ptr
87 # define BIO_set_data(BIO, VALUE) BIO->ptr = VALUE;
88 # define BIO_set_init(BIO, VALUE) BIO->init = VALUE;
89
90 // These functions have been renamed in OpenSSL 1.1.
91 # define OpenSSL_version SSLeay_version
92 # define X509_getm_notAfter X509_get_notAfter
93 # define X509_getm_notBefore X509_get_notBefore
94 # define OPENSSL_init_ssl(OPTIONS, SETTINGS) \
95         SSL_library_init(); \
96         SSL_load_error_strings();
97
98 // These macros have been renamed in OpenSSL 1.1.
99 # define OPENSSL_VERSION SSLEAY_VERSION
100
101 #else
102 # define INSPIRCD_OPENSSL_OPAQUE_BIO
103 #endif
104
105 enum issl_status { ISSL_NONE, ISSL_HANDSHAKING, ISSL_OPEN };
106
107 static bool SelfSigned = false;
108 static int exdataindex;
109
110 char* get_error()
111 {
112         return ERR_error_string(ERR_get_error(), NULL);
113 }
114
115 static int OnVerify(int preverify_ok, X509_STORE_CTX* ctx);
116 static void StaticSSLInfoCallback(const SSL* ssl, int where, int rc);
117
118 namespace OpenSSL
119 {
120         class Exception : public ModuleException
121         {
122          public:
123                 Exception(const std::string& reason)
124                         : ModuleException(reason) { }
125         };
126
127         class DHParams
128         {
129                 DH* dh;
130
131          public:
132                 DHParams(const std::string& filename)
133                 {
134                         BIO* dhpfile = BIO_new_file(filename.c_str(), "r");
135                         if (dhpfile == NULL)
136                                 throw Exception("Couldn't open DH file " + filename);
137
138                         dh = PEM_read_bio_DHparams(dhpfile, NULL, NULL, NULL);
139                         BIO_free(dhpfile);
140
141                         if (!dh)
142                                 throw Exception("Couldn't read DH params from file " + filename);
143                 }
144
145                 ~DHParams()
146                 {
147                         DH_free(dh);
148                 }
149
150                 DH* get()
151                 {
152                         return dh;
153                 }
154         };
155
156         class Context
157         {
158                 SSL_CTX* const ctx;
159                 long ctx_options;
160
161          public:
162                 Context(SSL_CTX* context)
163                         : ctx(context)
164                 {
165                         // Sane default options for OpenSSL see https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
166                         // and when choosing a cipher, use the server's preferences instead of the client preferences.
167                         long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE;
168                         // Only turn options on if they exist
169 #ifdef SSL_OP_SINGLE_ECDH_USE
170                         opts |= SSL_OP_SINGLE_ECDH_USE;
171 #endif
172 #ifdef SSL_OP_NO_TICKET
173                         opts |= SSL_OP_NO_TICKET;
174 #endif
175
176                         ctx_options = SSL_CTX_set_options(ctx, opts);
177
178                         long mode = SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
179 #ifdef SSL_MODE_RELEASE_BUFFERS
180                         mode |= SSL_MODE_RELEASE_BUFFERS;
181 #endif
182                         SSL_CTX_set_mode(ctx, mode);
183                         SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
184                         SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
185                         SSL_CTX_set_info_callback(ctx, StaticSSLInfoCallback);
186                 }
187
188                 ~Context()
189                 {
190                         SSL_CTX_free(ctx);
191                 }
192
193                 bool SetDH(DHParams& dh)
194                 {
195                         ERR_clear_error();
196                         return (SSL_CTX_set_tmp_dh(ctx, dh.get()) >= 0);
197                 }
198
199 #ifndef OPENSSL_NO_ECDH
200                 void SetECDH(const std::string& curvename)
201                 {
202                         int nid = OBJ_sn2nid(curvename.c_str());
203                         if (nid == 0)
204                                 throw Exception("Unknown curve: " + curvename);
205
206                         EC_KEY* eckey = EC_KEY_new_by_curve_name(nid);
207                         if (!eckey)
208                                 throw Exception("Unable to create EC key object");
209
210                         ERR_clear_error();
211                         bool ret = (SSL_CTX_set_tmp_ecdh(ctx, eckey) >= 0);
212                         EC_KEY_free(eckey);
213                         if (!ret)
214                                 throw Exception("Couldn't set ECDH parameters");
215                 }
216 #endif
217
218                 bool SetCiphers(const std::string& ciphers)
219                 {
220                         ERR_clear_error();
221                         return SSL_CTX_set_cipher_list(ctx, ciphers.c_str());
222                 }
223
224                 bool SetCerts(const std::string& filename)
225                 {
226                         ERR_clear_error();
227                         return SSL_CTX_use_certificate_chain_file(ctx, filename.c_str());
228                 }
229
230                 bool SetPrivateKey(const std::string& filename)
231                 {
232                         ERR_clear_error();
233                         return SSL_CTX_use_PrivateKey_file(ctx, filename.c_str(), SSL_FILETYPE_PEM);
234                 }
235
236                 bool SetCA(const std::string& filename)
237                 {
238                         ERR_clear_error();
239                         return SSL_CTX_load_verify_locations(ctx, filename.c_str(), 0);
240                 }
241
242                 void SetCRL(const std::string& crlfile, const std::string& crlpath, const std::string& crlmode)
243                 {
244                         if (crlfile.empty() && crlpath.empty())
245                                 return;
246
247                         /* Set CRL mode */
248                         unsigned long crlflags = X509_V_FLAG_CRL_CHECK;
249                         if (stdalgo::string::equalsci(crlmode, "chain"))
250                         {
251                                 crlflags |= X509_V_FLAG_CRL_CHECK_ALL;
252                         }
253                         else if (!stdalgo::string::equalsci(crlmode, "leaf"))
254                         {
255                                 throw ModuleException("Unknown mode '" + crlmode + "'; expected either 'chain' (default) or 'leaf'");
256                         }
257
258                         /* Load CRL files */
259                         X509_STORE* store = SSL_CTX_get_cert_store(ctx);
260                         if (!store)
261                         {
262                                 throw ModuleException("Unable to get X509_STORE from TLS (SSL) context; this should never happen");
263                         }
264                         ERR_clear_error();
265                         if (!X509_STORE_load_locations(store,
266                                 crlfile.empty() ? NULL : crlfile.c_str(),
267                                 crlpath.empty() ? NULL : crlpath.c_str()))
268                         {
269                                 int err = ERR_get_error();
270                                 throw ModuleException("Unable to load CRL file '" + crlfile + "' or CRL path '" + crlpath + "': '" + (err ? ERR_error_string(err, NULL) : "unknown") + "'");
271                         }
272
273                         /* Set CRL mode */
274                         if (X509_STORE_set_flags(store, crlflags) != 1)
275                         {
276                                 throw ModuleException("Unable to set X509 CRL flags");
277                         }
278                 }
279
280
281                 long GetDefaultContextOptions() const
282                 {
283                         return ctx_options;
284                 }
285
286                 long SetRawContextOptions(long setoptions, long clearoptions)
287                 {
288                         // Clear everything
289                         SSL_CTX_clear_options(ctx, SSL_CTX_get_options(ctx));
290
291                         // Set the default options and what is in the conf
292                         SSL_CTX_set_options(ctx, ctx_options | setoptions);
293                         return SSL_CTX_clear_options(ctx, clearoptions);
294                 }
295
296                 void SetVerifyCert()
297                 {
298                         SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
299                 }
300
301                 SSL* CreateServerSession()
302                 {
303                         SSL* sess = SSL_new(ctx);
304                         SSL_set_accept_state(sess); // Act as server
305                         return sess;
306                 }
307
308                 SSL* CreateClientSession()
309                 {
310                         SSL* sess = SSL_new(ctx);
311                         SSL_set_connect_state(sess); // Act as client
312                         return sess;
313                 }
314         };
315
316         class Profile
317         {
318                 /** Name of this profile
319                  */
320                 const std::string name;
321
322                 /** DH parameters in use
323                  */
324                 DHParams dh;
325
326                 /** OpenSSL makes us have two contexts, one for servers and one for clients
327                  */
328                 Context ctx;
329                 Context clictx;
330
331                 /** Digest to use when generating fingerprints
332                  */
333                 const EVP_MD* digest;
334
335                 /** Last error, set by error_callback()
336                  */
337                 std::string lasterr;
338
339                 /** True if renegotiations are allowed, false if not
340                  */
341                 const bool allowrenego;
342
343                 /** Rough max size of records to send
344                  */
345                 const unsigned int outrecsize;
346
347                 static int error_callback(const char* str, size_t len, void* u)
348                 {
349                         Profile* profile = reinterpret_cast<Profile*>(u);
350                         profile->lasterr = std::string(str, len - 1);
351                         return 0;
352                 }
353
354                 /** Set raw OpenSSL context (SSL_CTX) options from a config tag
355                  * @param ctxname Name of the context, client or server
356                  * @param tag Config tag defining this profile
357                  * @param context Context object to manipulate
358                  */
359                 void SetContextOptions(const std::string& ctxname, ConfigTag* tag, Context& context)
360                 {
361                         long setoptions = tag->getInt(ctxname + "setoptions", 0);
362                         long clearoptions = tag->getInt(ctxname + "clearoptions", 0);
363
364 #ifdef SSL_OP_NO_COMPRESSION
365                         // Disable compression by default
366                         if (!tag->getBool("compression", false))
367                                 setoptions |= SSL_OP_NO_COMPRESSION;
368 #endif
369
370                         // Disable TLSv1.0 by default.
371                         if (!tag->getBool("tlsv1", false))
372                                 setoptions |= SSL_OP_NO_TLSv1;
373
374 #ifdef SSL_OP_NO_TLSv1_1
375                         // Enable TLSv1.1 by default.
376                         if (!tag->getBool("tlsv11", true))
377                                 setoptions |= SSL_OP_NO_TLSv1_1;
378 #endif
379
380 #ifdef SSL_OP_NO_TLSv1_2
381                         // Enable TLSv1.2 by default.
382                         if (!tag->getBool("tlsv12", true))
383                                 setoptions |= SSL_OP_NO_TLSv1_2;
384 #endif
385
386                         if (!setoptions && !clearoptions)
387                                 return; // Nothing to do
388
389                         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Setting %s %s context options, default: %ld set: %ld clear: %ld", name.c_str(), ctxname.c_str(), ctx.GetDefaultContextOptions(), setoptions, clearoptions);
390                         long final = context.SetRawContextOptions(setoptions, clearoptions);
391                         ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "%s %s context options: %ld", name.c_str(), ctxname.c_str(), final);
392                 }
393
394          public:
395                 Profile(const std::string& profilename, ConfigTag* tag)
396                         : name(profilename)
397                         , dh(ServerInstance->Config->Paths.PrependConfig(tag->getString("dhfile", "dhparams.pem", 1)))
398                         , ctx(SSL_CTX_new(SSLv23_server_method()))
399                         , clictx(SSL_CTX_new(SSLv23_client_method()))
400                         , allowrenego(tag->getBool("renegotiation")) // Disallow by default
401                         , outrecsize(tag->getUInt("outrecsize", 2048, 512, 16384))
402                 {
403                         if ((!ctx.SetDH(dh)) || (!clictx.SetDH(dh)))
404                                 throw Exception("Couldn't set DH parameters");
405
406                         const std::string hash = tag->getString("hash", "md5", 1);
407                         digest = EVP_get_digestbyname(hash.c_str());
408                         if (digest == NULL)
409                                 throw Exception("Unknown hash type " + hash);
410
411                         std::string ciphers = tag->getString("ciphers");
412                         if (!ciphers.empty())
413                         {
414                                 if ((!ctx.SetCiphers(ciphers)) || (!clictx.SetCiphers(ciphers)))
415                                 {
416                                         ERR_print_errors_cb(error_callback, this);
417                                         throw Exception("Can't set cipher list to \"" + ciphers + "\" " + lasterr);
418                                 }
419                         }
420
421 #ifndef OPENSSL_NO_ECDH
422                         const std::string curvename = tag->getString("ecdhcurve", "prime256v1", 1);
423                         if (!curvename.empty())
424                                 ctx.SetECDH(curvename);
425 #endif
426
427                         SetContextOptions("server", tag, ctx);
428                         SetContextOptions("client", tag, clictx);
429
430                         /* Load our keys and certificates
431                          * NOTE: OpenSSL's error logging API sucks, don't blame us for this clusterfuck.
432                          */
433                         std::string filename = ServerInstance->Config->Paths.PrependConfig(tag->getString("certfile", "cert.pem", 1));
434                         if ((!ctx.SetCerts(filename)) || (!clictx.SetCerts(filename)))
435                         {
436                                 ERR_print_errors_cb(error_callback, this);
437                                 throw Exception("Can't read certificate file: " + lasterr);
438                         }
439
440                         filename = ServerInstance->Config->Paths.PrependConfig(tag->getString("keyfile", "key.pem", 1));
441                         if ((!ctx.SetPrivateKey(filename)) || (!clictx.SetPrivateKey(filename)))
442                         {
443                                 ERR_print_errors_cb(error_callback, this);
444                                 throw Exception("Can't read key file: " + lasterr);
445                         }
446
447                         // Load the CAs we trust
448                         filename = ServerInstance->Config->Paths.PrependConfig(tag->getString("cafile", "ca.pem", 1));
449                         if ((!ctx.SetCA(filename)) || (!clictx.SetCA(filename)))
450                         {
451                                 ERR_print_errors_cb(error_callback, this);
452                                 ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Can't read CA list from %s. This is only a problem if you want to verify client certificates, otherwise it's safe to ignore this message. Error: %s", filename.c_str(), lasterr.c_str());
453                         }
454
455                         // Load the CRLs.
456                         const std::string crlfile = tag->getString("crlfile");
457                         const std::string crlpath = tag->getString("crlpath");
458                         const std::string crlmode = tag->getString("crlmode", "chain", 1);
459                         ctx.SetCRL(crlfile, crlpath, crlmode);
460
461                         clictx.SetVerifyCert();
462                         if (tag->getBool("requestclientcert", true))
463                                 ctx.SetVerifyCert();
464                 }
465
466                 const std::string& GetName() const { return name; }
467                 SSL* CreateServerSession() { return ctx.CreateServerSession(); }
468                 SSL* CreateClientSession() { return clictx.CreateClientSession(); }
469                 const EVP_MD* GetDigest() { return digest; }
470                 bool AllowRenegotiation() const { return allowrenego; }
471                 unsigned int GetOutgoingRecordSize() const { return outrecsize; }
472         };
473
474         namespace BIOMethod
475         {
476                 static int create(BIO* bio)
477                 {
478                         BIO_set_init(bio, 1);
479                         return 1;
480                 }
481
482                 static int destroy(BIO* bio)
483                 {
484                         // XXX: Dummy function to avoid a memory leak in OpenSSL.
485                         // The memory leak happens in BIO_free() (bio_lib.c) when the destroy func of the BIO is NULL.
486                         // This is fixed in OpenSSL but some distros still ship the unpatched version hence we provide this workaround.
487                         return 1;
488                 }
489
490                 static long ctrl(BIO* bio, int cmd, long num, void* ptr)
491                 {
492                         if (cmd == BIO_CTRL_FLUSH)
493                                 return 1;
494                         return 0;
495                 }
496
497                 static int read(BIO* bio, char* buf, int len);
498                 static int write(BIO* bio, const char* buf, int len);
499
500 #ifdef INSPIRCD_OPENSSL_OPAQUE_BIO
501                 static BIO_METHOD* alloc()
502                 {
503                         BIO_METHOD* meth = BIO_meth_new(100 | BIO_TYPE_SOURCE_SINK, "inspircd");
504                         BIO_meth_set_write(meth, OpenSSL::BIOMethod::write);
505                         BIO_meth_set_read(meth, OpenSSL::BIOMethod::read);
506                         BIO_meth_set_ctrl(meth, OpenSSL::BIOMethod::ctrl);
507                         BIO_meth_set_create(meth, OpenSSL::BIOMethod::create);
508                         BIO_meth_set_destroy(meth, OpenSSL::BIOMethod::destroy);
509                         return meth;
510                 }
511 #endif
512         }
513 }
514
515 // BIO_METHOD is opaque in OpenSSL 1.1 so we can't do this.
516 // See OpenSSL::BIOMethod::alloc for the new method.
517 #ifndef INSPIRCD_OPENSSL_OPAQUE_BIO
518 static BIO_METHOD biomethods =
519 {
520         (100 | BIO_TYPE_SOURCE_SINK),
521         "inspircd",
522         OpenSSL::BIOMethod::write,
523         OpenSSL::BIOMethod::read,
524         NULL, // puts
525         NULL, // gets
526         OpenSSL::BIOMethod::ctrl,
527         OpenSSL::BIOMethod::create,
528         OpenSSL::BIOMethod::destroy, // destroy, does nothing, see function body for more info
529         NULL // callback_ctrl
530 };
531 #else
532 static BIO_METHOD* biomethods;
533 #endif
534
535 static int OnVerify(int preverify_ok, X509_STORE_CTX *ctx)
536 {
537         /* XXX: This will allow self signed certificates.
538          * In the future if we want an option to not allow this,
539          * we can just return preverify_ok here, and openssl
540          * will boot off self-signed and invalid peer certs.
541          */
542         int ve = X509_STORE_CTX_get_error(ctx);
543
544         SelfSigned = (ve == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
545
546         return 1;
547 }
548
549 class OpenSSLIOHook : public SSLIOHook
550 {
551  private:
552         SSL* sess;
553         issl_status status;
554         bool data_to_write;
555
556         // Returns 1 if handshake succeeded, 0 if it is still in progress, -1 if it failed
557         int Handshake(StreamSocket* user)
558         {
559                 ERR_clear_error();
560                 int ret = SSL_do_handshake(sess);
561                 if (ret < 0)
562                 {
563                         int err = SSL_get_error(sess, ret);
564
565                         if (err == SSL_ERROR_WANT_READ)
566                         {
567                                 SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
568                                 this->status = ISSL_HANDSHAKING;
569                                 return 0;
570                         }
571                         else if (err == SSL_ERROR_WANT_WRITE)
572                         {
573                                 SocketEngine::ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
574                                 this->status = ISSL_HANDSHAKING;
575                                 return 0;
576                         }
577                         else
578                         {
579                                 CloseSession();
580                                 return -1;
581                         }
582                 }
583                 else if (ret > 0)
584                 {
585                         // Handshake complete.
586                         VerifyCertificate();
587
588                         status = ISSL_OPEN;
589
590                         SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE);
591
592                         return 1;
593                 }
594                 else if (ret == 0)
595                 {
596                         CloseSession();
597                 }
598                 return -1;
599         }
600
601         void CloseSession()
602         {
603                 if (sess)
604                 {
605                         SSL_shutdown(sess);
606                         SSL_free(sess);
607                 }
608                 sess = NULL;
609                 certificate = NULL;
610                 status = ISSL_NONE;
611         }
612
613         void VerifyCertificate()
614         {
615                 X509* cert;
616                 ssl_cert* certinfo = new ssl_cert;
617                 this->certificate = certinfo;
618                 unsigned int n;
619                 unsigned char md[EVP_MAX_MD_SIZE];
620
621                 cert = SSL_get_peer_certificate(sess);
622
623                 if (!cert)
624                 {
625                         certinfo->error = "Could not get peer certificate: "+std::string(get_error());
626                         return;
627                 }
628
629                 certinfo->invalid = (SSL_get_verify_result(sess) != X509_V_OK);
630
631                 if (!SelfSigned)
632                 {
633                         certinfo->unknownsigner = false;
634                         certinfo->trusted = true;
635                 }
636                 else
637                 {
638                         certinfo->unknownsigner = true;
639                         certinfo->trusted = false;
640                 }
641
642                 char buf[512];
643                 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
644                 certinfo->dn = buf;
645                 // Make sure there are no chars in the string that we consider invalid
646                 if (certinfo->dn.find_first_of("\r\n") != std::string::npos)
647                         certinfo->dn.clear();
648
649                 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
650                 certinfo->issuer = buf;
651                 if (certinfo->issuer.find_first_of("\r\n") != std::string::npos)
652                         certinfo->issuer.clear();
653
654                 if (!X509_digest(cert, GetProfile().GetDigest(), md, &n))
655                 {
656                         certinfo->error = "Out of memory generating fingerprint";
657                 }
658                 else
659                 {
660                         certinfo->fingerprint = BinToHex(md, n);
661                 }
662
663                 if ((ASN1_UTCTIME_cmp_time_t(X509_getm_notAfter(cert), ServerInstance->Time()) == -1) || (ASN1_UTCTIME_cmp_time_t(X509_getm_notBefore(cert), ServerInstance->Time()) == 0))
664                 {
665                         certinfo->error = "Not activated, or expired certificate";
666                 }
667
668                 X509_free(cert);
669         }
670
671         void SSLInfoCallback(int where, int rc)
672         {
673                 if ((where & SSL_CB_HANDSHAKE_START) && (status == ISSL_OPEN))
674                 {
675                         if (GetProfile().AllowRenegotiation())
676                                 return;
677
678                         // The other side is trying to renegotiate, kill the connection and change status
679                         // to ISSL_NONE so CheckRenego() closes the session
680                         status = ISSL_NONE;
681                         BIO* bio = SSL_get_rbio(sess);
682                         EventHandler* eh = static_cast<StreamSocket*>(BIO_get_data(bio));
683                         SocketEngine::Shutdown(eh, 2);
684                 }
685         }
686
687         bool CheckRenego(StreamSocket* sock)
688         {
689                 if (status != ISSL_NONE)
690                         return true;
691
692                 ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Session %p killed, attempted to renegotiate", (void*)sess);
693                 CloseSession();
694                 sock->SetError("Renegotiation is not allowed");
695                 return false;
696         }
697
698         // Returns 1 if application I/O should proceed, 0 if it must wait for the underlying protocol to progress, -1 on fatal error
699         int PrepareIO(StreamSocket* sock)
700         {
701                 if (status == ISSL_OPEN)
702                         return 1;
703                 else if (status == ISSL_HANDSHAKING)
704                 {
705                         // The handshake isn't finished, try to finish it
706                         return Handshake(sock);
707                 }
708
709                 CloseSession();
710                 return -1;
711         }
712
713         // Calls our private SSLInfoCallback()
714         friend void StaticSSLInfoCallback(const SSL* ssl, int where, int rc);
715
716  public:
717         OpenSSLIOHook(IOHookProvider* hookprov, StreamSocket* sock, SSL* session)
718                 : SSLIOHook(hookprov)
719                 , sess(session)
720                 , status(ISSL_NONE)
721                 , data_to_write(false)
722         {
723                 // Create BIO instance and store a pointer to the socket in it which will be used by the read and write functions
724 #ifdef INSPIRCD_OPENSSL_OPAQUE_BIO
725                 BIO* bio = BIO_new(biomethods);
726 #else
727                 BIO* bio = BIO_new(&biomethods);
728 #endif
729                 BIO_set_data(bio, sock);
730                 SSL_set_bio(sess, bio, bio);
731
732                 SSL_set_ex_data(sess, exdataindex, this);
733                 sock->AddIOHook(this);
734                 Handshake(sock);
735         }
736
737         void OnStreamSocketClose(StreamSocket* user) CXX11_OVERRIDE
738         {
739                 CloseSession();
740         }
741
742         int OnStreamSocketRead(StreamSocket* user, std::string& recvq) CXX11_OVERRIDE
743         {
744                 // Finish handshake if needed
745                 int prepret = PrepareIO(user);
746                 if (prepret <= 0)
747                         return prepret;
748
749                 // If we resumed the handshake then this->status will be ISSL_OPEN
750                 {
751                         ERR_clear_error();
752                         char* buffer = ServerInstance->GetReadBuffer();
753                         size_t bufsiz = ServerInstance->Config->NetBufferSize;
754                         int ret = SSL_read(sess, buffer, bufsiz);
755
756                         if (!CheckRenego(user))
757                                 return -1;
758
759                         if (ret > 0)
760                         {
761                                 recvq.append(buffer, ret);
762                                 int mask = 0;
763                                 // Schedule a read if there is still data in the OpenSSL buffer
764                                 if (SSL_pending(sess) > 0)
765                                         mask |= FD_ADD_TRIAL_READ;
766                                 if (data_to_write)
767                                         mask |= FD_WANT_POLL_READ | FD_WANT_SINGLE_WRITE;
768                                 if (mask != 0)
769                                         SocketEngine::ChangeEventMask(user, mask);
770                                 return 1;
771                         }
772                         else if (ret == 0)
773                         {
774                                 // Client closed connection.
775                                 CloseSession();
776                                 user->SetError("Connection closed");
777                                 return -1;
778                         }
779                         else // if (ret < 0)
780                         {
781                                 int err = SSL_get_error(sess, ret);
782
783                                 if (err == SSL_ERROR_WANT_READ)
784                                 {
785                                         SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ);
786                                         return 0;
787                                 }
788                                 else if (err == SSL_ERROR_WANT_WRITE)
789                                 {
790                                         SocketEngine::ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE);
791                                         return 0;
792                                 }
793                                 else
794                                 {
795                                         CloseSession();
796                                         return -1;
797                                 }
798                         }
799                 }
800         }
801
802         int OnStreamSocketWrite(StreamSocket* user, StreamSocket::SendQueue& sendq) CXX11_OVERRIDE
803         {
804                 // Finish handshake if needed
805                 int prepret = PrepareIO(user);
806                 if (prepret <= 0)
807                         return prepret;
808
809                 data_to_write = true;
810
811                 // Session is ready for transferring application data
812                 while (!sendq.empty())
813                 {
814                         ERR_clear_error();
815                         FlattenSendQueue(sendq, GetProfile().GetOutgoingRecordSize());
816                         const StreamSocket::SendQueue::Element& buffer = sendq.front();
817                         int ret = SSL_write(sess, buffer.data(), buffer.size());
818
819                         if (!CheckRenego(user))
820                                 return -1;
821
822                         if (ret == (int)buffer.length())
823                         {
824                                 // Wrote entire record, continue sending
825                                 sendq.pop_front();
826                         }
827                         else if (ret > 0)
828                         {
829                                 sendq.erase_front(ret);
830                                 SocketEngine::ChangeEventMask(user, FD_WANT_SINGLE_WRITE);
831                                 return 0;
832                         }
833                         else if (ret == 0)
834                         {
835                                 CloseSession();
836                                 return -1;
837                         }
838                         else // if (ret < 0)
839                         {
840                                 int err = SSL_get_error(sess, ret);
841
842                                 if (err == SSL_ERROR_WANT_WRITE)
843                                 {
844                                         SocketEngine::ChangeEventMask(user, FD_WANT_SINGLE_WRITE);
845                                         return 0;
846                                 }
847                                 else if (err == SSL_ERROR_WANT_READ)
848                                 {
849                                         SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ);
850                                         return 0;
851                                 }
852                                 else
853                                 {
854                                         CloseSession();
855                                         return -1;
856                                 }
857                         }
858                 }
859
860                 data_to_write = false;
861                 SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
862                 return 1;
863         }
864
865         void GetCiphersuite(std::string& out) const CXX11_OVERRIDE
866         {
867                 if (!IsHandshakeDone())
868                         return;
869                 out.append(SSL_get_version(sess)).push_back('-');
870                 out.append(SSL_get_cipher(sess));
871         }
872
873         bool GetServerName(std::string& out) const CXX11_OVERRIDE
874         {
875                 const char* name = SSL_get_servername(sess, TLSEXT_NAMETYPE_host_name);
876                 if (!name)
877                         return false;
878
879                 out.append(name);
880                 return true;
881         }
882
883         bool IsHandshakeDone() const { return (status == ISSL_OPEN); }
884         OpenSSL::Profile& GetProfile();
885 };
886
887 static void StaticSSLInfoCallback(const SSL* ssl, int where, int rc)
888 {
889         OpenSSLIOHook* hook = static_cast<OpenSSLIOHook*>(SSL_get_ex_data(ssl, exdataindex));
890         hook->SSLInfoCallback(where, rc);
891 }
892
893 static int OpenSSL::BIOMethod::write(BIO* bio, const char* buffer, int size)
894 {
895         BIO_clear_retry_flags(bio);
896
897         StreamSocket* sock = static_cast<StreamSocket*>(BIO_get_data(bio));
898         if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK)
899         {
900                 // Writes blocked earlier, don't retry syscall
901                 BIO_set_retry_write(bio);
902                 return -1;
903         }
904
905         int ret = SocketEngine::Send(sock, buffer, size, 0);
906         if ((ret < size) && ((ret > 0) || (SocketEngine::IgnoreError())))
907         {
908                 // Blocked, set retry flag for OpenSSL
909                 SocketEngine::ChangeEventMask(sock, FD_WRITE_WILL_BLOCK);
910                 BIO_set_retry_write(bio);
911         }
912
913         return ret;
914 }
915
916 static int OpenSSL::BIOMethod::read(BIO* bio, char* buffer, int size)
917 {
918         BIO_clear_retry_flags(bio);
919
920         StreamSocket* sock = static_cast<StreamSocket*>(BIO_get_data(bio));
921         if (sock->GetEventMask() & FD_READ_WILL_BLOCK)
922         {
923                 // Reads blocked earlier, don't retry syscall
924                 BIO_set_retry_read(bio);
925                 return -1;
926         }
927
928         int ret = SocketEngine::Recv(sock, buffer, size, 0);
929         if ((ret < size) && ((ret > 0) || (SocketEngine::IgnoreError())))
930         {
931                 // Blocked, set retry flag for OpenSSL
932                 SocketEngine::ChangeEventMask(sock, FD_READ_WILL_BLOCK);
933                 BIO_set_retry_read(bio);
934         }
935
936         return ret;
937 }
938
939 class OpenSSLIOHookProvider : public IOHookProvider
940 {
941         OpenSSL::Profile profile;
942
943  public:
944         OpenSSLIOHookProvider(Module* mod, const std::string& profilename, ConfigTag* tag)
945                 : IOHookProvider(mod, "ssl/" + profilename, IOHookProvider::IOH_SSL)
946                 , profile(profilename, tag)
947         {
948                 ServerInstance->Modules->AddService(*this);
949         }
950
951         ~OpenSSLIOHookProvider()
952         {
953                 ServerInstance->Modules->DelService(*this);
954         }
955
956         void OnAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE
957         {
958                 new OpenSSLIOHook(this, sock, profile.CreateServerSession());
959         }
960
961         void OnConnect(StreamSocket* sock) CXX11_OVERRIDE
962         {
963                 new OpenSSLIOHook(this, sock, profile.CreateClientSession());
964         }
965
966         OpenSSL::Profile& GetProfile() { return profile; }
967 };
968
969 OpenSSL::Profile& OpenSSLIOHook::GetProfile()
970 {
971         IOHookProvider* hookprov = prov;
972         return static_cast<OpenSSLIOHookProvider*>(hookprov)->GetProfile();
973 }
974
975 class ModuleSSLOpenSSL : public Module
976 {
977         typedef std::vector<reference<OpenSSLIOHookProvider> > ProfileList;
978
979         ProfileList profiles;
980
981         void ReadProfiles()
982         {
983                 ProfileList newprofiles;
984                 ConfigTagList tags = ServerInstance->Config->ConfTags("sslprofile");
985                 if (tags.first == tags.second)
986                 {
987                         // Create a default profile named "openssl"
988                         const std::string defname = "openssl";
989                         ConfigTag* tag = ServerInstance->Config->ConfValue(defname);
990                         ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "No <sslprofile> tags found, using settings from the deprecated <openssl> tag");
991
992                         try
993                         {
994                                 newprofiles.push_back(new OpenSSLIOHookProvider(this, defname, tag));
995                         }
996                         catch (OpenSSL::Exception& ex)
997                         {
998                                 throw ModuleException("Error while initializing the default TLS (SSL) profile - " + ex.GetReason());
999                         }
1000                 }
1001                 else
1002                 {
1003                         ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "You have defined an <sslprofile> tag; you should use this in place of \"openssl\" when configuring TLS (SSL) connections in <bind:ssl> or <link:ssl>");
1004                         for (ConfigIter i = tags.first; i != tags.second; ++i)
1005                         {
1006                                 ConfigTag* tag = i->second;
1007                                 if (!stdalgo::string::equalsci(tag->getString("provider"), "openssl"))
1008                                 {
1009                                         ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Ignoring non-OpenSSL <sslprofile> tag at " + tag->getTagLocation());
1010                                         continue;
1011                                 }
1012
1013                                 std::string name = tag->getString("name");
1014                                 if (name.empty())
1015                                 {
1016                                         ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Ignoring <sslprofile> tag without name at " + tag->getTagLocation());
1017                                         continue;
1018                                 }
1019
1020                                 reference<OpenSSLIOHookProvider> prov;
1021                                 try
1022                                 {
1023                                         prov = new OpenSSLIOHookProvider(this, name, tag);
1024                                 }
1025                                 catch (CoreException& ex)
1026                                 {
1027                                         throw ModuleException("Error while initializing TLS (SSL) profile \"" + name + "\" at " + tag->getTagLocation() + " - " + ex.GetReason());
1028                                 }
1029
1030                                 newprofiles.push_back(prov);
1031                         }
1032                 }
1033
1034                 for (ProfileList::iterator i = profiles.begin(); i != profiles.end(); ++i)
1035                 {
1036                         OpenSSLIOHookProvider& prov = **i;
1037                         ServerInstance->Modules.DelService(prov);
1038                 }
1039
1040                 profiles.swap(newprofiles);
1041         }
1042
1043  public:
1044         ModuleSSLOpenSSL()
1045         {
1046                 // Initialize OpenSSL
1047                 OPENSSL_init_ssl(0, NULL);
1048 #ifdef INSPIRCD_OPENSSL_OPAQUE_BIO
1049                 biomethods = OpenSSL::BIOMethod::alloc();
1050         }
1051
1052         ~ModuleSSLOpenSSL()
1053         {
1054                 BIO_meth_free(biomethods);
1055 #endif
1056         }
1057
1058         void init() CXX11_OVERRIDE
1059         {
1060                 ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "OpenSSL lib version \"%s\" module was compiled for \"" OPENSSL_VERSION_TEXT "\"", OpenSSL_version(OPENSSL_VERSION));
1061
1062                 // Register application specific data
1063                 char exdatastr[] = "inspircd";
1064                 exdataindex = SSL_get_ex_new_index(0, exdatastr, NULL, NULL, NULL);
1065                 if (exdataindex < 0)
1066                         throw ModuleException("Failed to register application specific data");
1067
1068                 ReadProfiles();
1069         }
1070
1071         void OnModuleRehash(User* user, const std::string &param) CXX11_OVERRIDE
1072         {
1073                 if (!irc::equals(param, "tls") && !irc::equals(param, "ssl"))
1074                         return;
1075
1076                 try
1077                 {
1078                         ReadProfiles();
1079                         ServerInstance->SNO->WriteToSnoMask('a', "OpenSSL TLS (SSL) profiles have been reloaded.");
1080                 }
1081                 catch (ModuleException& ex)
1082                 {
1083                         ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, ex.GetReason() + " Not applying settings.");
1084                 }
1085         }
1086
1087         void OnCleanup(ExtensionItem::ExtensibleType type, Extensible* item) CXX11_OVERRIDE
1088         {
1089                 if (type == ExtensionItem::EXT_USER)
1090                 {
1091                         LocalUser* user = IS_LOCAL((User*)item);
1092
1093                         if ((user) && (user->eh.GetModHook(this)))
1094                         {
1095                                 // User is using TLS (SSL), they're a local user, and they're using one of *our* TLS (SSL) ports.
1096                                 // Potentially there could be multiple TLS (SSL) modules loaded at once on different ports.
1097                                 ServerInstance->Users->QuitUser(user, "OpenSSL module unloading");
1098                         }
1099                 }
1100         }
1101
1102         ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
1103         {
1104                 const OpenSSLIOHook* const iohook = static_cast<OpenSSLIOHook*>(user->eh.GetModHook(this));
1105                 if ((iohook) && (!iohook->IsHandshakeDone()))
1106                         return MOD_RES_DENY;
1107                 return MOD_RES_PASSTHRU;
1108         }
1109
1110         Version GetVersion() CXX11_OVERRIDE
1111         {
1112                 return Version("Allows TLS (SSL) encrypted connections using the OpenSSL library.", VF_VENDOR);
1113         }
1114 };
1115
1116 MODULE_INIT(ModuleSSLOpenSSL)