X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ssl_gnutls.cpp;h=59397e000613b49860d68ff41619eb3d225b1bba;hb=4e6997fddf8eba872584830e0d56c8de83b76aab;hp=4b9d0fc4e8777e8d9232b59b84dea10d22072d09;hpb=1b4925f99fb39d59e88c98db7fae8512e7f54c7b;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 4b9d0fc4e..59397e000 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -12,17 +12,8 @@ */ #include "inspircd.h" - #include #include - -#include "inspircd_config.h" -#include "configreader.h" -#include "users.h" -#include "channels.h" -#include "modules.h" -#include "socket.h" -#include "hashcomp.h" #include "transport.h" #include "m_cap.h" @@ -55,6 +46,11 @@ bool isin(const std::string &host, int port, const std::vector &por class issl_session : public classbase { public: + issl_session() + { + sess = NULL; + } + gnutls_session_t sess; issl_status status; std::string outbuf; @@ -75,8 +71,25 @@ class CommandStartTLS : public Command CmdResult Handle (const std::vector ¶meters, User *user) { - user->io = Caller; - Caller->OnRawSocketAccept(user->GetFd(), user->GetIPString(), user->GetPort()); + /* changed from == REG_ALL to catch clients sending STARTTLS + * after NICK and USER but before OnUserConnect completes and + * give a proper error message (see bug #645) - dz + */ + if (user->registered != REG_NONE) + { + ServerInstance->Users->QuitUser(user, "STARTTLS is not permitted after client registration has started"); + } + else + { + if (!user->GetIOHook()) + { + user->WriteNumeric(670, "%s :STARTTLS successful, go ahead with TLS handshake", user->nick.c_str()); + user->AddIOHook(Caller); + Caller->OnRawSocketAccept(user->GetFd(), user->GetIPString(), user->GetPort()); + } + else + user->WriteNumeric(691, "%s :STARTTLS failure", user->nick.c_str()); + } return CMD_FAILURE; } @@ -105,6 +118,7 @@ class ModuleSSLGnuTLS : public Module int dh_bits; int clientactive; + bool cred_alloc; CommandStartTLS* starttls; @@ -122,13 +136,7 @@ class ModuleSSLGnuTLS : public Module gnutls_global_init(); // This must be called once in the program - if(gnutls_certificate_allocate_credentials(&x509_cred) != 0) - ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to allocate certificate credentials"); - - // Guessing return meaning - if(gnutls_dh_params_init(&dh_params) < 0) - ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters"); - + cred_alloc = false; // Needs the flag as it ignores a plain /rehash OnRehash(NULL,"ssl"); @@ -220,20 +228,35 @@ class ModuleSSLGnuTLS : public Module dh_bits = 1024; // Prepend relative paths with the path to the config directory. - if(cafile[0] != '/') + if ((cafile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(cafile))) cafile = confdir + cafile; - if(crlfile[0] != '/') + if ((crlfile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(crlfile))) crlfile = confdir + crlfile; - if(certfile[0] != '/') + if ((certfile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(certfile))) certfile = confdir + certfile; - if(keyfile[0] != '/') + if ((keyfile[0] != '/') && (!ServerInstance->Config->StartsWithWindowsDriveLetter(keyfile))) keyfile = confdir + keyfile; int ret; - + + if (cred_alloc) + { + // Deallocate the old credentials + gnutls_dh_params_deinit(dh_params); + gnutls_certificate_free_credentials(x509_cred); + } + else + cred_alloc = true; + + if((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) + ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to allocate certificate credentials: %s", gnutls_strerror(ret)); + + if((ret = gnutls_dh_params_init(&dh_params)) < 0) + ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters: %s", gnutls_strerror(ret)); + if((ret =gnutls_certificate_set_x509_trust_file(x509_cred, cafile.c_str(), GNUTLS_X509_FMT_PEM)) < 0) ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to set X.509 trust file '%s': %s", cafile.c_str(), gnutls_strerror(ret)); @@ -243,7 +266,7 @@ class ModuleSSLGnuTLS : public Module if((ret = gnutls_certificate_set_x509_key_file (x509_cred, certfile.c_str(), keyfile.c_str(), GNUTLS_X509_FMT_PEM)) < 0) { // If this fails, no SSL port will work. At all. So, do the smart thing - throw a ModuleException - throw ModuleException("Unable to load GnuTLS server certificate: " + std::string(gnutls_strerror(ret))); + throw ModuleException("Unable to load GnuTLS server certificate (" + std::string(certfile) + ", key: " + keyfile + "): " + std::string(gnutls_strerror(ret))); } // This may be on a large (once a day or week) timer eventually. @@ -280,11 +303,12 @@ class ModuleSSLGnuTLS : public Module { User* user = (User*)item; - if(user->io) + if (user->GetIOHook() == 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. ServerInstance->Users->QuitUser(user, "SSL module unloading"); + user->DelIOHook(); } if (user->GetExt("ssl_cert", dummy)) { @@ -293,8 +317,6 @@ class ModuleSSLGnuTLS : public Module delete tofree; user->Shrink("ssl_cert"); } - - user->io = NULL; } } @@ -313,7 +335,7 @@ class ModuleSSLGnuTLS : public Module virtual Version GetVersion() { - return Version(1, 2, 0, 0, VF_VENDOR, API_VERSION); + return Version("$Id$", VF_VENDOR, API_VERSION); } @@ -324,10 +346,10 @@ class ModuleSSLGnuTLS : public Module virtual void OnHookUserIO(User* user, const std::string &targetip) { - if (!user->io && isin(targetip,user->GetPort(),listenports)) + if (!user->GetIOHook() && isin(targetip,user->GetPort(),listenports)) { /* Hook the user with our module */ - user->io = this; + user->AddIOHook(this); } } @@ -343,7 +365,7 @@ class ModuleSSLGnuTLS : public Module const char* ret = "OK"; try { - ret = ServerInstance->Config->AddIOHook((Module*)this, (BufferedSocket*)ISR->Sock) ? "OK" : NULL; + ret = ISR->Sock->AddIOHook((Module*)this) ? "OK" : NULL; } catch (ModuleException &e) { @@ -353,7 +375,7 @@ class ModuleSSLGnuTLS : public Module } else if (strcmp("IS_UNHOOK", request->GetId()) == 0) { - return ServerInstance->Config->DelIOHook((BufferedSocket*)ISR->Sock) ? "OK" : NULL; + return ISR->Sock->DelIOHook() ? "OK" : NULL; } else if (strcmp("IS_HSDONE", request->GetId()) == 0) { @@ -390,6 +412,10 @@ class ModuleSSLGnuTLS : public Module issl_session* session = &sessions[fd]; + /* For STARTTLS: Don't try and init a session on a socket that already has a session */ + if (session->sess) + return; + session->fd = fd; session->inbuf = new char[inbufsize]; session->inbufoffset = 0; @@ -512,6 +538,9 @@ class ModuleSSLGnuTLS : public Module } else { + ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, + "m_ssl_gnutls.so: Error while reading on fd %d: %s", + session->fd, gnutls_strerror(ret)); readresult = 0; CloseSession(session); } @@ -528,7 +557,7 @@ class ModuleSSLGnuTLS : public Module { memcpy(buffer, session->inbuf, count); // Move the stuff left in inbuf to the beginning of it - memcpy(session->inbuf, session->inbuf + count, (length - count)); + memmove(session->inbuf, session->inbuf + count, (length - count)); // Now we need to set session->inbufoffset to the amount of data still waiting to be handed to insp. session->inbufoffset = length - count; // Insp uses readresult as the count of how much data there is in buffer, so: @@ -592,6 +621,9 @@ class ModuleSSLGnuTLS : public Module { if(ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) { + ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, + "m_ssl_gnutls.so: Error while writing to fd %d: %s", + session->fd, gnutls_strerror(ret)); CloseSession(session); } else @@ -620,9 +652,9 @@ class ModuleSSLGnuTLS : public Module return; // Bugfix, only send this numeric for *our* SSL users - if (dest->GetExt("ssl", dummy) || ((IS_LOCAL(dest) && (dest->io == this)))) + if (dest->GetExt("ssl", dummy) || ((IS_LOCAL(dest) && (dest->GetIOHook() == this)))) { - ServerInstance->SendWhoisLine(source, dest, 320, "%s %s :is using a secure connection", source->nick, dest->nick); + ServerInstance->SendWhoisLine(source, dest, 320, "%s %s :is using a secure connection", source->nick.c_str(), dest->nick.c_str()); } } @@ -680,6 +712,9 @@ class ModuleSSLGnuTLS : public Module else { // Handshake failed. + ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, + "m_ssl_gnutls.so: Handshake failed on fd %d: %s", + session->fd, gnutls_strerror(ret)); CloseSession(session); session->status = ISSL_CLOSING; } @@ -722,7 +757,7 @@ class ModuleSSLGnuTLS : public Module std::string cipher = gnutls_kx_get_name(gnutls_kx_get(sessions[user->GetFd()].sess)); cipher.append("-").append(gnutls_cipher_get_name(gnutls_cipher_get(sessions[user->GetFd()].sess))).append("-"); cipher.append(gnutls_mac_get_name(gnutls_mac_get(sessions[user->GetFd()].sess))); - user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick, cipher.c_str()); + user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), cipher.c_str()); } } } @@ -881,7 +916,7 @@ class ModuleSSLGnuTLS : public Module /* Beware here we do not check for errors. */ - if ((gnutls_x509_crt_get_expiration_time(cert) < time(0)) || (gnutls_x509_crt_get_activation_time(cert) > time(0))) + if ((gnutls_x509_crt_get_expiration_time(cert) < ServerInstance->Time()) || (gnutls_x509_crt_get_activation_time(cert) > ServerInstance->Time())) { certinfo->data.insert(std::make_pair("error","Not activated, or expired certificate")); } @@ -896,7 +931,7 @@ class ModuleSSLGnuTLS : public Module GenericCapHandler(ev, "tls", "tls"); } - void Prioritize() + void Prioritize() { Module* server = ServerInstance->Modules->Find("m_spanningtree.so"); ServerInstance->Modules->SetPriority(this, I_OnPostConnect, PRIO_AFTER, &server);