]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/extra/m_ssl_gnutls.cpp
Read multiple GnuTLS records in one RawSocketRead operation
[user/henk/code/inspircd.git] / src / modules / extra / m_ssl_gnutls.cpp
index c81be9f7bb16f476f4f9399dac0947ccf5f7252a..f05a73227044d7f08e84389bc2b146408218ce90 100644 (file)
@@ -81,7 +81,7 @@ class CommandStartTLS : public Command
                        {
                                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());
+                               Caller->OnRawSocketAccept(user->GetFd(), NULL, NULL);
                        }
                        else
                                user->WriteNumeric(691, "%s :STARTTLS failure", user->nick.c_str());
@@ -255,16 +255,16 @@ class ModuleSSLGnuTLS : public Module
                        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));
+                       ServerInstance->Logs->Log("m_ssl_gnutls",DEBUG, "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));
+                       ServerInstance->Logs->Log("m_ssl_gnutls",DEBUG, "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));
+                       ServerInstance->Logs->Log("m_ssl_gnutls",DEBUG, "m_ssl_gnutls.so: Failed to set X.509 trust file '%s': %s", cafile.c_str(), gnutls_strerror(ret));
 
                if((ret = gnutls_certificate_set_x509_crl_file (x509_cred, crlfile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
-                       ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to set X.509 CRL file '%s': %s", crlfile.c_str(), gnutls_strerror(ret));
+                       ServerInstance->Logs->Log("m_ssl_gnutls",DEBUG, "m_ssl_gnutls.so: Failed to set X.509 CRL file '%s': %s", crlfile.c_str(), gnutls_strerror(ret));
 
                if((ret = gnutls_certificate_set_x509_key_file (x509_cred, certfile.c_str(), keyfile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
                {
@@ -347,9 +347,9 @@ class ModuleSSLGnuTLS : public Module
                output.append(" STARTTLS");
        }
 
-       virtual void OnHookUserIO(User* user, const std::string &targetip)
+       virtual void OnHookUserIO(User* user)
        {
-               if (!user->GetIOHook() && isin(targetip,user->GetPort(),listenports))
+               if (!user->GetIOHook() && isin(user->GetServerIP(),user->GetServerPort(),listenports))
                {
                        /* Hook the user with our module */
                        user->AddIOHook(this);
@@ -421,7 +421,7 @@ class ModuleSSLGnuTLS : public Module
        }
 
 
-       virtual void OnRawSocketAccept(int fd, const std::string &ip, int localport)
+       virtual void OnRawSocketAccept(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
        {
                /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */
                if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1))
@@ -520,34 +520,43 @@ class ModuleSSLGnuTLS : public Module
 
                if (session->status == ISSL_HANDSHAKEN)
                {
-                       int ret = gnutls_record_recv(session->sess, buffer, count);
-
-                       if (ret > 0)
+                       unsigned int len = 0;
+                       while (len < count)
                        {
-                               readresult = ret;
+                               int ret = gnutls_record_recv(session->sess, buffer + len, count - len);
+                               if (ret > 0)
+                               {
+                                       len += ret;
+                               }
+                               else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
+                               {
+                                       break;
+                               }
+                               else
+                               {
+                                       if (ret != 0)
+                                               ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT,
+                                                       "m_ssl_gnutls.so: Error while reading on fd %d: %s",
+                                                       fd, gnutls_strerror(ret));
+
+                                       // if ret == 0, client closed connection.
+                                       readresult = 0;
+                                       CloseSession(session);
+                                       return 1;
+                               }
                        }
-                       else if (ret == 0)
+                       readresult = len;
+                       if (len)
                        {
-                               // Client closed connection.
-                               readresult = 0;
-                               CloseSession(session);
                                return 1;
                        }
-                       else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
+                       else
                        {
                                errno = EAGAIN;
                                return -1;
                        }
-                       else
-                       {
-                               ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT,
-                                               "m_ssl_gnutls.so: Error while reading on fd %d: %s",
-                                               fd, gnutls_strerror(ret));
-                               readresult = 0;
-                               CloseSession(session);
-                       }
                }
-               else if(session->status == ISSL_CLOSING)
+               else if (session->status == ISSL_CLOSING)
                        readresult = 0;
 
                return 1;
@@ -610,7 +619,8 @@ class ModuleSSLGnuTLS : public Module
                        }
                }
 
-               MakePollWrite(fd);
+               if (!session->outbuf.empty())
+                       MakePollWrite(fd);
 
                /* Who's smart idea was it to return 1 when we havent written anything?
                 * This fucks the buffer up in BufferedSocket :p