X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ssl_openssl.cpp;h=e313ca7b5d1e4260a976098ec49ca2c475882bf2;hb=8320bcc9df1ea89a47257c9f9c70aa6d476beaa8;hp=8540ab41f3d87ab8028de00199c9f3840484fc31;hpb=2972f1ec3fbecb70f7ad7f4f605fb5b9264e8816;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 8540ab41f..e313ca7b5 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -196,9 +196,18 @@ namespace OpenSSL return SSL_CTX_clear_options(ctx, clearoptions); } - SSL* CreateSession() + SSL* CreateServerSession() { - return SSL_new(ctx); + SSL* sess = SSL_new(ctx); + SSL_set_accept_state(sess); // Act as server + return sess; + } + + SSL* CreateClientSession() + { + SSL* sess = SSL_new(ctx); + SSL_set_connect_state(sess); // Act as client + return sess; } }; @@ -229,6 +238,10 @@ namespace OpenSSL */ const bool allowrenego; + /** Rough max size of records to send + */ + const unsigned int outrecsize; + static int error_callback(const char* str, size_t len, void* u) { Profile* profile = reinterpret_cast(u); @@ -269,6 +282,7 @@ namespace OpenSSL , ctx(SSL_CTX_new(SSLv23_server_method())) , clictx(SSL_CTX_new(SSLv23_client_method())) , allowrenego(tag->getBool("renegotiation", true)) + , outrecsize(tag->getInt("outrecsize", 2048, 512, 16384)) { if ((!ctx.SetDH(dh)) || (!clictx.SetDH(dh))) throw Exception("Couldn't set DH parameters"); @@ -324,10 +338,11 @@ namespace OpenSSL } const std::string& GetName() const { return name; } - SSL* CreateServerSession() { return ctx.CreateSession(); } - SSL* CreateClientSession() { return clictx.CreateSession(); } + SSL* CreateServerSession() { return ctx.CreateServerSession(); } + SSL* CreateClientSession() { return clictx.CreateClientSession(); } const EVP_MD* GetDigest() { return digest; } bool AllowRenegotiation() const { return allowrenego; } + unsigned int GetOutgoingRecordSize() const { return outrecsize; } }; } @@ -350,21 +365,14 @@ class OpenSSLIOHook : public SSLIOHook private: SSL* sess; issl_status status; - const bool outbound; bool data_to_write; reference profile; // Returns 1 if handshake succeeded, 0 if it is still in progress, -1 if it failed int Handshake(StreamSocket* user) { - int ret; - ERR_clear_error(); - if (outbound) - ret = SSL_connect(sess); - else - ret = SSL_accept(sess); - + int ret = SSL_do_handshake(sess); if (ret < 0) { int err = SSL_get_error(sess, ret); @@ -521,11 +529,10 @@ class OpenSSLIOHook : public SSLIOHook friend void StaticSSLInfoCallback(const SSL* ssl, int where, int rc); public: - OpenSSLIOHook(IOHookProvider* hookprov, StreamSocket* sock, bool is_outbound, SSL* session, const reference& sslprofile) + OpenSSLIOHook(IOHookProvider* hookprov, StreamSocket* sock, SSL* session, const reference& sslprofile) : SSLIOHook(hookprov) , sess(session) , status(ISSL_NONE) - , outbound(is_outbound) , data_to_write(false) , profile(sslprofile) { @@ -600,7 +607,7 @@ class OpenSSLIOHook : public SSLIOHook } } - int OnStreamSocketWrite(StreamSocket* user, std::string& buffer) CXX11_OVERRIDE + int OnStreamSocketWrite(StreamSocket* user) CXX11_OVERRIDE { // Finish handshake if needed int prepret = PrepareIO(user); @@ -610,8 +617,12 @@ class OpenSSLIOHook : public SSLIOHook data_to_write = true; // Session is ready for transferring application data + StreamSocket::SendQueue& sendq = user->GetSendQ(); + while (!sendq.empty()) { ERR_clear_error(); + FlattenSendQueue(sendq, profile->GetOutgoingRecordSize()); + const StreamSocket::SendQueue::Element& buffer = sendq.front(); int ret = SSL_write(sess, buffer.data(), buffer.size()); #ifdef INSPIRCD_OPENSSL_ENABLE_RENEGO_DETECTION @@ -621,13 +632,12 @@ class OpenSSLIOHook : public SSLIOHook if (ret == (int)buffer.length()) { - data_to_write = false; - SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); - return 1; + // Wrote entire record, continue sending + sendq.pop_front(); } else if (ret > 0) { - buffer.erase(0, ret); + sendq.erase_front(ret); SocketEngine::ChangeEventMask(user, FD_WANT_SINGLE_WRITE); return 0; } @@ -657,6 +667,10 @@ class OpenSSLIOHook : public SSLIOHook } } } + + data_to_write = false; + SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); + return 1; } void TellCiphersAndFingerprint(LocalUser* user) @@ -679,6 +693,8 @@ class OpenSSLIOHook : public SSLIOHook out.append(SSL_get_version(sess)).push_back('-'); out.append(SSL_get_cipher(sess)); } + + bool IsHandshakeDone() const { return (status == ISSL_OPEN); } }; static void StaticSSLInfoCallback(const SSL* ssl, int where, int rc) @@ -708,12 +724,12 @@ class OpenSSLIOHookProvider : public refcountbase, public IOHookProvider void OnAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE { - new OpenSSLIOHook(this, sock, false, profile->CreateServerSession(), profile); + new OpenSSLIOHook(this, sock, profile->CreateServerSession(), profile); } void OnConnect(StreamSocket* sock) CXX11_OVERRIDE { - new OpenSSLIOHook(this, sock, true, profile->CreateClientSession(), profile); + new OpenSSLIOHook(this, sock, profile->CreateClientSession(), profile); } }; @@ -784,6 +800,8 @@ class ModuleSSLOpenSSL : public Module void init() CXX11_OVERRIDE { + ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "OpenSSL lib version \"%s\" module was compiled for \"" OPENSSL_VERSION_TEXT "\"", SSLeay_version(SSLEAY_VERSION)); + // Register application specific data char exdatastr[] = "inspircd"; exdataindex = SSL_get_ex_new_index(0, exdatastr, NULL, NULL, NULL); @@ -830,6 +848,18 @@ class ModuleSSLOpenSSL : public Module } } + ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE + { + if ((user->eh.GetIOHook()) && (user->eh.GetIOHook()->prov->creator == this)) + { + OpenSSLIOHook* iohook = static_cast(user->eh.GetIOHook()); + if (!iohook->IsHandshakeDone()) + return MOD_RES_DENY; + } + + return MOD_RES_PASSTHRU; + } + Version GetVersion() CXX11_OVERRIDE { return Version("Provides SSL support for clients", VF_VENDOR);