summaryrefslogtreecommitdiff
path: root/src/modules/extra/m_ssl_openssl.cpp
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2007-01-28 16:12:33 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2007-01-28 16:12:33 +0000
commit9da5c6610fffc9677646ef1d55c0e41fca8778a9 (patch)
tree840c46ac37daa9424535454a359d41053bc70432 /src/modules/extra/m_ssl_openssl.cpp
parent642218aed7c59304811227cde33816cf36f73b45 (diff)
Fix broken openssl outbound connects.
A record needs to be kept of if this session was initially outbound or inbound, so we know if we need to re-call SSL_connect or SSL_accept on handshake failure, we also need to have two SSL_CTX's, one initialized as a client context and one as a server context (this is EW, but i guess its just how openssl does stuff) git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6449 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src/modules/extra/m_ssl_openssl.cpp')
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp88
1 files changed, 76 insertions, 12 deletions
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index 957f1ba3c..e8f62eb1c 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -67,9 +67,11 @@ public:
char* inbuf; // Buffer OpenSSL reads into.
std::string outbuf; // Buffer for outgoing data that OpenSSL will not take.
int fd;
+ bool outbound;
issl_session()
{
+ outbound = false;
rstat = ISSL_READ;
wstat = ISSL_WRITE;
}
@@ -102,6 +104,7 @@ class ModuleSSLOpenSSL : public Module
issl_session sessions[MAX_DESCRIPTORS];
SSL_CTX* ctx;
+ SSL_CTX* clictx;
char* dummy;
@@ -129,8 +132,10 @@ class ModuleSSLOpenSSL : public Module
/* Build our SSL context*/
ctx = SSL_CTX_new( SSLv23_server_method() );
+ clictx = SSL_CTX_new( SSLv23_client_method() );
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
+ SSL_CTX_set_verify(clictx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
// Needs the flag as it ignores a plain /rehash
OnRehash(NULL,"ssl");
@@ -216,18 +221,18 @@ class ModuleSSLOpenSSL : public Module
dhfile = confdir + dhfile;
/* Load our keys and certificates*/
- if (!SSL_CTX_use_certificate_chain_file(ctx, certfile.c_str()))
+ if ((!SSL_CTX_use_certificate_chain_file(ctx, certfile.c_str())) || (!SSL_CTX_use_certificate_chain_file(clictx, certfile.c_str())))
{
ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Can't read certificate file %s", certfile.c_str());
}
- if (!SSL_CTX_use_PrivateKey_file(ctx, keyfile.c_str(), SSL_FILETYPE_PEM))
+ if ((!SSL_CTX_use_PrivateKey_file(ctx, keyfile.c_str(), SSL_FILETYPE_PEM)) || (!SSL_CTX_use_PrivateKey_file(clictx, keyfile.c_str(), SSL_FILETYPE_PEM)))
{
ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Can't read key file %s", keyfile.c_str());
}
/* Load the CAs we trust*/
- if (!SSL_CTX_load_verify_locations(ctx, cafile.c_str(), 0))
+ if ((!SSL_CTX_load_verify_locations(ctx, cafile.c_str(), 0)) || (!SSL_CTX_load_verify_locations(clictx, cafile.c_str(), 0)))
{
ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Can't read CA list from ", cafile.c_str());
}
@@ -244,7 +249,7 @@ class ModuleSSLOpenSSL : public Module
{
ret = PEM_read_DHparams(dhpfile, NULL, NULL, NULL);
- if(SSL_CTX_set_tmp_dh(ctx, ret) < 0)
+ if ((SSL_CTX_set_tmp_dh(ctx, ret) < 0) || (SSL_CTX_set_tmp_dh(clictx, ret) < 0))
{
ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters");
}
@@ -258,6 +263,7 @@ class ModuleSSLOpenSSL : public Module
virtual ~ModuleSSLOpenSSL()
{
SSL_CTX_free(ctx);
+ SSL_CTX_free(clictx);
delete culllist;
}
@@ -364,31 +370,42 @@ class ModuleSSLOpenSSL : public Module
session->inbufoffset = 0;
session->sess = SSL_new(ctx);
session->status = ISSL_NONE;
+ session->outbound = false;
if (session->sess == NULL)
return;
if (SSL_set_fd(session->sess, fd) == 0)
+ {
+ ServerInstance->Log(DEBUG,"BUG: Can't set fd with SSL_set_fd: %d", fd);
return;
+ }
Handshake(session);
}
virtual void OnRawSocketConnect(int fd)
{
+ ServerInstance->Log(DEBUG,"ON RAW SOCKET CONNECT WITH FD %d", fd);
issl_session* session = &sessions[fd];
session->fd = fd;
session->inbuf = new char[inbufsize];
session->inbufoffset = 0;
- session->sess = SSL_new(ctx);
+ session->sess = SSL_new(clictx);
session->status = ISSL_NONE;
+ session->outbound = true;
+
+ ServerInstance->Log(DEBUG,"Session: %08x", session->sess);
if (session->sess == NULL)
return;
if (SSL_set_fd(session->sess, fd) == 0)
+ {
+ ServerInstance->Log(DEBUG,"BUG: Can't set fd with SSL_set_fd: %d", fd);
return;
+ }
Handshake(session);
}
@@ -397,6 +414,8 @@ class ModuleSSLOpenSSL : public Module
{
CloseSession(&sessions[fd]);
+ ServerInstance->Log(DEBUG,"SSL session close: %d", fd);
+
EventHandler* user = ServerInstance->SE->GetRef(fd);
if ((user) && (user->GetExt("ssl_cert", dummy)))
@@ -485,16 +504,19 @@ class ModuleSSLOpenSSL : public Module
}
virtual int OnRawSocketWrite(int fd, const char* buffer, int count)
- {
+ {
issl_session* session = &sessions[fd];
if (!session->sess)
{
+ ServerInstance->Log(DEBUG,"BUG: file descriptor %d doesn't have an SSL session attached!", fd);
CloseSession(session);
- return 1;
+ return -1;
}
session->outbuf.append(buffer, count);
+
+ ServerInstance->Log(DEBUG,"Buffer now: %s", session->outbuf.c_str());
if (session->status == ISSL_HANDSHAKING)
{
@@ -505,6 +527,7 @@ class ModuleSSLOpenSSL : public Module
if (session->status == ISSL_OPEN)
{
+ ServerInstance->Log(DEBUG,"Session is open, writing to it");
if (session->rstat == ISSL_WRITE)
DoRead(session);
@@ -517,6 +540,7 @@ class ModuleSSLOpenSSL : public Module
int DoWrite(issl_session* session)
{
+ ServerInstance->Log(DEBUG,"DoWrite called");
if (!session->outbuf.size())
return -1;
@@ -524,6 +548,7 @@ class ModuleSSLOpenSSL : public Module
if (ret == 0)
{
+ ServerInstance->Log(DEBUG,"SSL_write returned 0");
CloseSession(session);
return 0;
}
@@ -543,6 +568,21 @@ class ModuleSSLOpenSSL : public Module
}
else
{
+ char errbuf[1024];
+ ERR_print_errors_fp(stdout);
+ if (err == SSL_ERROR_WANT_CONNECT)
+ ServerInstance->Log(DEBUG,"Closing in DoWrite() due to error: SSL_ERROR_WANT_CONNECT");
+ if (err == SSL_ERROR_WANT_ACCEPT)
+ ServerInstance->Log(DEBUG,"Closing in DoWrite() due to error: SSL_ERROR_WANT_ACCEPT");
+ if (err == SSL_ERROR_ZERO_RETURN)
+ ServerInstance->Log(DEBUG,"Closing in DoWrite() due to error: SSL_ERROR_ZERO_RETURN");
+ if (err == SSL_ERROR_WANT_X509_LOOKUP)
+ ServerInstance->Log(DEBUG,"Closing in DoWrite() due to error: SSL_ERROR_WANT_X509_LOOKUP");
+ if (err == SSL_ERROR_SSL)
+ ServerInstance->Log(DEBUG,"Closing in DoWrite() due to error: SSL_ERROR_SSL: %s", ERR_error_string(err, errbuf));
+ if (err == SSL_ERROR_SYSCALL)
+ ServerInstance->Log(DEBUG,"Closing in DoWrite() due to error: SSL_ERROR_SYSCALL: %d %s", errno, strerror(errno));
+
CloseSession(session);
return 0;
}
@@ -639,30 +679,42 @@ class ModuleSSLOpenSSL : public Module
}
bool Handshake(issl_session* session)
- {
- int ret = SSL_accept(session->sess);
+ {
+ ServerInstance->Log(DEBUG,"Handshake()");
+ int ret;
+
+ if (session->outbound)
+ ret = SSL_connect(session->sess);
+ else
+ ret = SSL_accept(session->sess);
if (ret < 0)
{
+ ServerInstance->Log(DEBUG,"Handshake ret < 0");
int err = SSL_get_error(session->sess, ret);
if (err == SSL_ERROR_WANT_READ)
{
+ ServerInstance->Log(DEBUG,"Handshake want read");
session->rstat = ISSL_READ;
session->status = ISSL_HANDSHAKING;
}
else if (err == SSL_ERROR_WANT_WRITE)
{
+ ServerInstance->Log(DEBUG,"Handshake want write");
session->wstat = ISSL_WRITE;
session->status = ISSL_HANDSHAKING;
MakePollWrite(session);
}
else
+ {
+ ServerInstance->Log(DEBUG,"Handshake other error");
CloseSession(session);
+ }
return false;
}
- else
+ else if (ret > 0)
{
// Handshake complete.
// This will do for setting the ssl flag...it could be done earlier if it's needed. But this seems neater.
@@ -674,13 +726,25 @@ class ModuleSSLOpenSSL : public Module
}
session->status = ISSL_OPEN;
+
+ ServerInstance->Log(DEBUG,"Handshake complete, returned %d", ret);
MakePollWrite(session);
-
+
+ return true;
+ }
+ else if (ret == 0)
+ {
+ int err = SSL_get_error(session->sess, ret);
+ ServerInstance->Log(DEBUG,"Handshake generic failure: %d", err);
+ ERR_print_errors_fp(stdout);
+ CloseSession(session);
return true;
}
+
+ return true;
}
-
+
virtual void OnPostConnect(userrec* user)
{
// This occurs AFTER OnUserConnect so we can be sure the