X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ssl_openssl.cpp;h=debc179534551991f91cb8e0ce8b85978e6139e8;hb=06eb88c10cb7a57ea800e0204b48277de9cb02ca;hp=a0c30bb9ee604bd10bb2fa75efefa526ad8eb0e6;hpb=b0676698152d88c76020b0fa51942d7297f152f3;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 a0c30bb9e..debc17953 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; } }; @@ -324,8 +333,8 @@ 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; } }; @@ -354,16 +363,11 @@ class OpenSSLIOHook : public SSLIOHook bool data_to_write; reference profile; - bool Handshake(StreamSocket* user) + // 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); @@ -372,20 +376,19 @@ class OpenSSLIOHook : public SSLIOHook { SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); this->status = ISSL_HANDSHAKING; - return true; + return 0; } else if (err == SSL_ERROR_WANT_WRITE) { SocketEngine::ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE); this->status = ISSL_HANDSHAKING; - return true; + return 0; } else { CloseSession(); + return -1; } - - return false; } else if (ret > 0) { @@ -396,13 +399,13 @@ class OpenSSLIOHook : public SSLIOHook SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE); - return true; + return 1; } else if (ret == 0) { CloseSession(); } - return false; + return -1; } void CloseSession() @@ -502,6 +505,21 @@ class OpenSSLIOHook : public SSLIOHook } #endif + // Returns 1 if application I/O should proceed, 0 if it must wait for the underlying protocol to progress, -1 on fatal error + int PrepareIO(StreamSocket* sock) + { + if (status == ISSL_OPEN) + return 1; + else if (status == ISSL_HANDSHAKING) + { + // The handshake isn't finished, try to finish it + return Handshake(sock); + } + + CloseSession(); + return -1; + } + // Calls our private SSLInfoCallback() friend void StaticSSLInfoCallback(const SSL* ssl, int where, int rc); @@ -531,27 +549,12 @@ class OpenSSLIOHook : public SSLIOHook int OnStreamSocketRead(StreamSocket* user, std::string& recvq) CXX11_OVERRIDE { - if (!sess) - { - CloseSession(); - return -1; - } - - if (status == ISSL_HANDSHAKING) - { - // The handshake isn't finished and it wants to read, try to finish it. - if (!Handshake(user)) - { - // Couldn't resume handshake. - if (status == ISSL_NONE) - return -1; - return 0; - } - } + // Finish handshake if needed + int prepret = PrepareIO(user); + if (prepret <= 0) + return prepret; // If we resumed the handshake then this->status will be ISSL_OPEN - - if (status == ISSL_OPEN) { ERR_clear_error(); char* buffer = ServerInstance->GetReadBuffer(); @@ -577,7 +580,7 @@ class OpenSSLIOHook : public SSLIOHook user->SetError("Connection closed"); return -1; } - else if (ret < 0) + else // if (ret < 0) { int err = SSL_get_error(sess, ret); @@ -598,32 +601,18 @@ class OpenSSLIOHook : public SSLIOHook } } } - - return 0; } int OnStreamSocketWrite(StreamSocket* user, std::string& buffer) CXX11_OVERRIDE { - if (!sess) - { - CloseSession(); - return -1; - } + // Finish handshake if needed + int prepret = PrepareIO(user); + if (prepret <= 0) + return prepret; data_to_write = true; - if (status == ISSL_HANDSHAKING) - { - if (!Handshake(user)) - { - // Couldn't resume handshake. - if (status == ISSL_NONE) - return -1; - return 0; - } - } - - if (status == ISSL_OPEN) + // Session is ready for transferring application data { ERR_clear_error(); int ret = SSL_write(sess, buffer.data(), buffer.size()); @@ -641,7 +630,7 @@ class OpenSSLIOHook : public SSLIOHook } else if (ret > 0) { - buffer = buffer.substr(ret); + buffer.erase(0, ret); SocketEngine::ChangeEventMask(user, FD_WANT_SINGLE_WRITE); return 0; } @@ -650,7 +639,7 @@ class OpenSSLIOHook : public SSLIOHook CloseSession(); return -1; } - else if (ret < 0) + else // if (ret < 0) { int err = SSL_get_error(sess, ret); @@ -671,14 +660,15 @@ class OpenSSLIOHook : public SSLIOHook } } } - return 0; } void TellCiphersAndFingerprint(LocalUser* user) { if (sess) { - std::string text = "*** You are connected using SSL cipher '" + std::string(SSL_get_cipher(sess)) + "'"; + std::string text = "*** You are connected using SSL cipher '"; + GetCiphersuite(text); + text += '\''; const std::string& fingerprint = certificate->fingerprint; if (!fingerprint.empty()) text += " and your SSL certificate fingerprint is " + fingerprint; @@ -686,6 +676,12 @@ class OpenSSLIOHook : public SSLIOHook user->WriteNotice(text); } } + + void GetCiphersuite(std::string& out) const + { + out.append(SSL_get_version(sess)).push_back('-'); + out.append(SSL_get_cipher(sess)); + } }; static void StaticSSLInfoCallback(const SSL* ssl, int where, int rc)