summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-05-01 04:00:13 -0500
committerattilamolnar <attilamolnar@hush.com>2013-05-02 23:43:33 +0200
commit52386bed51b481f9779ef3525f7c09a10a7e49cf (patch)
tree865088edb78f3f85aa9af51c70f1a8777d885b89 /src
parentd5991ed65206a4a493d2e263b46484a4b270ca2e (diff)
Fix gnutls (again) on Windows by using gnutls_transport_set_errno()
Diffstat (limited to 'src')
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp98
1 files changed, 56 insertions, 42 deletions
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index b3c7bca3e..e3f9cd566 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -77,46 +77,6 @@ static int cert_callback (gnutls_session_t session, const gnutls_datum_t * req_c
return 0;
}
-static ssize_t gnutls_pull_wrapper(gnutls_transport_ptr_t user_wrap, void* buffer, size_t size)
-{
- StreamSocket* user = reinterpret_cast<StreamSocket*>(user_wrap);
- if (user->GetEventMask() & FD_READ_WILL_BLOCK)
- {
- errno = EAGAIN;
- return -1;
- }
- int rv = ServerInstance->SE->Recv(user, reinterpret_cast<char *>(buffer), size, 0);
- if (rv < 0)
- {
- /* On Windows we need to set errno for gnutls */
- if (SocketEngine::IgnoreError())
- errno = EAGAIN;
- }
- if (rv < (int)size)
- ServerInstance->SE->ChangeEventMask(user, FD_READ_WILL_BLOCK);
- return rv;
-}
-
-static ssize_t gnutls_push_wrapper(gnutls_transport_ptr_t user_wrap, const void* buffer, size_t size)
-{
- StreamSocket* user = reinterpret_cast<StreamSocket*>(user_wrap);
- if (user->GetEventMask() & FD_WRITE_WILL_BLOCK)
- {
- errno = EAGAIN;
- return -1;
- }
- int rv = ServerInstance->SE->Send(user, reinterpret_cast<const char *>(buffer), size, 0);
- if (rv < 0)
- {
- /* On Windows we need to set errno for gnutls */
- if (SocketEngine::IgnoreError())
- errno = EAGAIN;
- }
- if (rv < (int)size)
- ServerInstance->SE->ChangeEventMask(user, FD_WRITE_WILL_BLOCK);
- return rv;
-}
-
class RandGen : public HandlerBase2<void, char*, size_t>
{
public:
@@ -132,10 +92,12 @@ class RandGen : public HandlerBase2<void, char*, size_t>
class issl_session
{
public:
+ StreamSocket* socket;
gnutls_session_t sess;
issl_status status;
reference<ssl_cert> cert;
- issl_session() : sess(NULL) {}
+
+ issl_session() : socket(NULL), sess(NULL) {}
};
class CommandStartTLS : public SplitCommand
@@ -213,6 +175,56 @@ class ModuleSSLGnuTLS : public Module
return str ? str : "UNKNOWN";
}
+ static ssize_t gnutls_pull_wrapper(gnutls_transport_ptr_t session_wrap, void* buffer, size_t size)
+ {
+ issl_session* session = reinterpret_cast<issl_session*>(session_wrap);
+ if (session->socket->GetEventMask() & FD_READ_WILL_BLOCK)
+ {
+ gnutls_transport_set_errno(session->sess, EAGAIN);
+ return -1;
+ }
+
+ int rv = ServerInstance->SE->Recv(session->socket, reinterpret_cast<char *>(buffer), size, 0);
+ if (rv < 0)
+ {
+ /* Windows doesn't use errno, but gnutls does, so check SocketEngine::IgnoreError()
+ * and then set errno appropriately.
+ * The gnutls library may also have a different errno variable than us, see
+ * gnutls_transport_set_errno(3).
+ */
+ gnutls_transport_set_errno(session->sess, SocketEngine::IgnoreError() ? EAGAIN : errno);
+ }
+
+ if (rv < (int)size)
+ ServerInstance->SE->ChangeEventMask(session->socket, FD_READ_WILL_BLOCK);
+ return rv;
+ }
+
+ static ssize_t gnutls_push_wrapper(gnutls_transport_ptr_t session_wrap, const void* buffer, size_t size)
+ {
+ issl_session* session = reinterpret_cast<issl_session*>(session_wrap);
+ if (session->socket->GetEventMask() & FD_WRITE_WILL_BLOCK)
+ {
+ gnutls_transport_set_errno(session->sess, EAGAIN);
+ return -1;
+ }
+
+ int rv = ServerInstance->SE->Send(session->socket, reinterpret_cast<const char *>(buffer), size, 0);
+ if (rv < 0)
+ {
+ /* Windows doesn't use errno, but gnutls does, so check SocketEngine::IgnoreError()
+ * and then set errno appropriately.
+ * The gnutls library may also have a different errno variable than us, see
+ * gnutls_transport_set_errno(3).
+ */
+ gnutls_transport_set_errno(session->sess, SocketEngine::IgnoreError() ? EAGAIN : errno);
+ }
+
+ if (rv < (int)size)
+ ServerInstance->SE->ChangeEventMask(session->socket, FD_WRITE_WILL_BLOCK);
+ return rv;
+ }
+
public:
ModuleSSLGnuTLS()
@@ -540,13 +552,14 @@ class ModuleSSLGnuTLS : public Module
issl_session* session = &sessions[user->GetFd()];
gnutls_init(&session->sess, me_server ? GNUTLS_SERVER : GNUTLS_CLIENT);
+ session->socket = user;
#ifdef GNUTLS_NEW_PRIO_API
gnutls_priority_set(session->sess, priority);
#endif
gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
gnutls_dh_set_prime_bits(session->sess, dh_bits);
- gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(user));
+ gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(session));
gnutls_transport_set_push_function(session->sess, gnutls_push_wrapper);
gnutls_transport_set_pull_function(session->sess, gnutls_pull_wrapper);
@@ -762,6 +775,7 @@ class ModuleSSLGnuTLS : public Module
gnutls_bye(session->sess, GNUTLS_SHUT_WR);
gnutls_deinit(session->sess);
}
+ session->socket = NULL;
session->sess = NULL;
session->cert = NULL;
session->status = ISSL_NONE;