X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ssl_gnutls.cpp;h=a42efa1ab121359f6f1587873a4484e280ec7019;hb=bdfde49fb6d9a8787c072b759d4af27584308e1b;hp=716a736f87868f3304adfc7b79a8f697673fe5d2;hpb=2c7c0cd711ff09ec24677ddc118ffc2a8bee190c;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index 716a736f8..a42efa1ab 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -20,6 +20,15 @@ * along with this program. If not, see . */ +/// $CompilerFlags: find_compiler_flags("gnutls") +/// $CompilerFlags: require_version("gnutls" "1.0" "2.12") execute("libgcrypt-config --cflags" "LIBGCRYPT_CXXFLAGS") + +/// $LinkerFlags: find_linker_flags("gnutls" "-lgnutls") +/// $LinkerFlags: require_version("gnutls" "1.0" "2.12") execute("libgcrypt-config --libs" "LIBGCRYPT_LDFLAGS") + +/// $PackageInfo: require_system("darwin") gnutls pkg-config +/// $PackageInfo: require_system("ubuntu" "1.0" "13.10") libgcrypt11-dev +/// $PackageInfo: require_system("ubuntu" "14.04") gnutls-bin libgnutls-dev pkg-config #include "inspircd.h" #include "modules/ssl.h" @@ -29,7 +38,11 @@ #if defined __clang__ # pragma clang diagnostic ignored "-Wc++11-extensions" #elif defined __GNUC__ -# pragma GCC diagnostic ignored "-pedantic" +# if __GNUC__ < 6 +# pragma GCC diagnostic ignored "-pedantic" +# else +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif #endif #include @@ -55,12 +68,9 @@ #endif #ifdef _WIN32 -# pragma comment(lib, "libgnutls-28.lib") +# pragma comment(lib, "libgnutls-30.lib") #endif -/* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") eval("print `libgcrypt-config --cflags | tr -d \r` if `pkg-config --modversion gnutls 2>/dev/null | tr -d \r` lt '2.12'") */ -/* $LinkerFlags: rpath("pkg-config --libs gnutls") pkgconflibs("gnutls","/libgnutls.so","-lgnutls") eval("print `libgcrypt-config --libs | tr -d \r` if `pkg-config --modversion gnutls 2>/dev/null | tr -d \r` lt '2.12'") */ - // These don't exist in older GnuTLS versions #if INSPIRCD_GNUTLS_HAS_VERSION(2, 1, 7) #define GNUTLS_NEW_PRIO_API @@ -97,6 +107,8 @@ typedef gnutls_connection_end_t inspircd_gnutls_session_init_flags_t; #define INSPIRCD_GNUTLS_HAS_CORK #endif +static Module* thismod; + class RandGen : public HandlerBase2 { public: @@ -577,16 +589,21 @@ namespace GnuTLS */ const unsigned int outrecsize; + /** True to request a client certificate as a server + */ + const bool requestclientcert; + Profile(const std::string& profilename, const std::string& certstr, const std::string& keystr, std::auto_ptr& DH, unsigned int mindh, const std::string& hashstr, const std::string& priostr, std::auto_ptr& CA, std::auto_ptr& CRL, - unsigned int recsize) + unsigned int recsize, bool Requestclientcert) : name(profilename) , x509cred(certstr, keystr) , min_dh_bits(mindh) , hash(hashstr) , priority(priostr) , outrecsize(recsize) + , requestclientcert(Requestclientcert) { x509cred.SetDH(DH); x509cred.SetCA(CA, CRL); @@ -657,7 +674,10 @@ namespace GnuTLS #else unsigned int outrecsize = tag->getInt("outrecsize", 2048, 512, 16384); #endif - return new Profile(profilename, certstr, keystr, dh, mindh, hashstr, priostr, ca, crl, outrecsize); + + const bool requestclientcert = tag->getBool("requestclientcert", true); + + return new Profile(profilename, certstr, keystr, dh, mindh, hashstr, priostr, ca, crl, outrecsize, requestclientcert); } /** Set up the given session with the settings in this profile @@ -668,8 +688,9 @@ namespace GnuTLS x509cred.SetupSession(sess); gnutls_dh_set_prime_bits(sess, min_dh_bits); - // Request client certificate if we are a server, no-op if we're a client - gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST); + // Request client certificate if enabled and we are a server, no-op if we're a client + if (requestclientcert) + gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST); } const std::string& GetName() const { return name; } @@ -913,7 +934,7 @@ info_done_dealloc: { StreamSocket* sock = reinterpret_cast(session_wrap); #ifdef _WIN32 - GnuTLSIOHook* session = static_cast(sock->GetIOHook()); + GnuTLSIOHook* session = static_cast(sock->GetModHook(thismod)); #endif if (sock->GetEventMask() & FD_READ_WILL_BLOCK) @@ -950,7 +971,7 @@ info_done_dealloc: { StreamSocket* sock = reinterpret_cast(transportptr); #ifdef _WIN32 - GnuTLSIOHook* session = static_cast(sock->GetIOHook()); + GnuTLSIOHook* session = static_cast(sock->GetModHook(thismod)); #endif if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK) @@ -985,7 +1006,7 @@ info_done_dealloc: { StreamSocket* sock = reinterpret_cast(session_wrap); #ifdef _WIN32 - GnuTLSIOHook* session = static_cast(sock->GetIOHook()); + GnuTLSIOHook* session = static_cast(sock->GetModHook(thismod)); #endif if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK) @@ -1061,6 +1082,9 @@ info_done_dealloc: if (ret > 0) { reader.appendto(recvq); + // Schedule a read if there is still data in the GnuTLS buffer + if (gnutls_record_check_pending(sess) > 0) + SocketEngine::ChangeEventMask(user, FD_ADD_TRIAL_READ); return 1; } else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) @@ -1082,7 +1106,7 @@ info_done_dealloc: } } - int OnStreamSocketWrite(StreamSocket* user) CXX11_OVERRIDE + int OnStreamSocketWrite(StreamSocket* user, StreamSocket::SendQueue& sendq) CXX11_OVERRIDE { // Finish handshake if needed int prepret = PrepareIO(user); @@ -1090,7 +1114,6 @@ info_done_dealloc: return prepret; // Session is ready for transferring application data - StreamSocket::SendQueue& sendq = user->GetSendQ(); #ifdef INSPIRCD_GNUTLS_HAS_CORK while (true) @@ -1146,22 +1169,10 @@ info_done_dealloc: return 1; } - void TellCiphersAndFingerprint(LocalUser* user) - { - if (sess) - { - std::string text = "*** You are connected using SSL cipher '"; - GetCiphersuite(text); - text += '\''; - if (!certificate->fingerprint.empty()) - text += " and your SSL certificate fingerprint is " + certificate->fingerprint; - - user->WriteNotice(text); - } - } - - void GetCiphersuite(std::string& out) const + void GetCiphersuite(std::string& out) const CXX11_OVERRIDE { + if (!IsHandshakeDone()) + return; out.append(UnknownIfNULL(gnutls_protocol_get_name(gnutls_protocol_get_version(sess)))).push_back('-'); out.append(UnknownIfNULL(gnutls_kx_get_name(gnutls_kx_get(sess)))).push_back('-'); out.append(UnknownIfNULL(gnutls_cipher_get_name(gnutls_cipher_get(sess)))).push_back('-'); @@ -1181,7 +1192,7 @@ int GnuTLS::X509Credentials::cert_callback(gnutls_session_t sess, const gnutls_d st->key_type = GNUTLS_PRIVKEY_X509; #endif StreamSocket* sock = reinterpret_cast(gnutls_transport_get_ptr(sess)); - GnuTLS::X509Credentials& cred = static_cast(sock->GetIOHook())->GetProfile()->GetX509Credentials(); + GnuTLS::X509Credentials& cred = static_cast(sock->GetModHook(thismod))->GetProfile()->GetX509Credentials(); st->ncerts = cred.certs.size(); st->cert.x509 = cred.certs.raw(); @@ -1291,6 +1302,7 @@ class ModuleSSLGnuTLS : public Module #ifndef GNUTLS_HAS_RND gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); #endif + thismod = this; } void init() CXX11_OVERRIDE @@ -1326,7 +1338,7 @@ class ModuleSSLGnuTLS : public Module { LocalUser* user = IS_LOCAL(static_cast(item)); - if (user && user->eh.GetIOHook() && user->eh.GetIOHook()->prov->creator == this) + if ((user) && (user->eh.GetModHook(this))) { // User is using SSL, they're a local user, and they're using one of *our* SSL ports. // Potentially there could be multiple SSL modules loaded at once on different ports. @@ -1340,22 +1352,11 @@ class ModuleSSLGnuTLS : public Module return Version("Provides SSL support for clients", VF_VENDOR); } - void OnUserConnect(LocalUser* user) CXX11_OVERRIDE - { - IOHook* hook = user->eh.GetIOHook(); - if (hook && hook->prov->creator == this) - static_cast(hook)->TellCiphersAndFingerprint(user); - } - ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE { - if ((user->eh.GetIOHook()) && (user->eh.GetIOHook()->prov->creator == this)) - { - GnuTLSIOHook* iohook = static_cast(user->eh.GetIOHook()); - if (!iohook->IsHandshakeDone()) - return MOD_RES_DENY; - } - + const GnuTLSIOHook* const iohook = static_cast(user->eh.GetModHook(this)); + if ((iohook) && (!iohook->IsHandshakeDone())) + return MOD_RES_DENY; return MOD_RES_PASSTHRU; } };