*/
#include "inspircd.h"
-
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
-
-#include "inspircd_config.h"
-#include "configreader.h"
-#include "users.h"
-#include "channels.h"
-#include "modules.h"
-#include "socket.h"
-#include "hashcomp.h"
#include "transport.h"
#include "m_cap.h"
class issl_session : public classbase
{
public:
+ issl_session()
+ {
+ sess = NULL;
+ }
+
gnutls_session_t sess;
issl_status status;
std::string outbuf;
}
else
{
- if (!user->io)
+ if (!user->GetIOHook())
{
user->WriteNumeric(670, "%s :STARTTLS successful, go ahead with TLS handshake", user->nick.c_str());
- user->io = Caller;
+ user->AddIOHook(Caller);
Caller->OnRawSocketAccept(user->GetFd(), user->GetIPString(), user->GetPort());
}
else
int dh_bits;
int clientactive;
+ bool cred_alloc;
CommandStartTLS* starttls;
gnutls_global_init(); // This must be called once in the program
- if(gnutls_certificate_allocate_credentials(&x509_cred) != 0)
- ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to allocate certificate credentials");
-
- // Guessing return meaning
- if(gnutls_dh_params_init(&dh_params) < 0)
- ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters");
-
+ cred_alloc = false;
// Needs the flag as it ignores a plain /rehash
OnRehash(NULL,"ssl");
keyfile = confdir + keyfile;
int ret;
-
+
+ if (cred_alloc)
+ {
+ // Deallocate the old credentials
+ gnutls_dh_params_deinit(dh_params);
+ gnutls_certificate_free_credentials(x509_cred);
+ }
+ else
+ 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));
+
+ 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));
+
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));
if((ret = gnutls_certificate_set_x509_key_file (x509_cred, certfile.c_str(), keyfile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
{
// If this fails, no SSL port will work. At all. So, do the smart thing - throw a ModuleException
- throw ModuleException("Unable to load GnuTLS server certificate: " + std::string(gnutls_strerror(ret)));
+ throw ModuleException("Unable to load GnuTLS server certificate (" + std::string(certfile) + ", key: " + keyfile + "): " + std::string(gnutls_strerror(ret)));
}
// This may be on a large (once a day or week) timer eventually.
{
User* user = (User*)item;
- if(user->io)
+ if (user->GetIOHook() == this)
{
// User is using SSL, they're a local user, and they're using one of *our* SSL ports.
// Potentially there could be multiple SSL modules loaded at once on different ports.
ServerInstance->Users->QuitUser(user, "SSL module unloading");
+ user->DelIOHook();
}
if (user->GetExt("ssl_cert", dummy))
{
delete tofree;
user->Shrink("ssl_cert");
}
-
- user->io = NULL;
}
}
virtual Version GetVersion()
{
- return Version(1, 2, 0, 0, VF_VENDOR, API_VERSION);
+ return Version("$Id$", VF_VENDOR, API_VERSION);
}
virtual void OnHookUserIO(User* user, const std::string &targetip)
{
- if (!user->io && isin(targetip,user->GetPort(),listenports))
+ if (!user->GetIOHook() && isin(targetip,user->GetPort(),listenports))
{
/* Hook the user with our module */
- user->io = this;
+ user->AddIOHook(this);
}
}
const char* ret = "OK";
try
{
- ret = ServerInstance->Config->AddIOHook((Module*)this, (BufferedSocket*)ISR->Sock) ? "OK" : NULL;
+ ret = ISR->Sock->AddIOHook((Module*)this) ? "OK" : NULL;
}
catch (ModuleException &e)
{
}
else if (strcmp("IS_UNHOOK", request->GetId()) == 0)
{
- return ServerInstance->Config->DelIOHook((BufferedSocket*)ISR->Sock) ? "OK" : NULL;
+ return ISR->Sock->DelIOHook() ? "OK" : NULL;
}
else if (strcmp("IS_HSDONE", request->GetId()) == 0)
{
}
else
{
+ ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT,
+ "m_ssl_gnutls.so: Error while reading on fd %d: %s",
+ session->fd, gnutls_strerror(ret));
readresult = 0;
CloseSession(session);
}
if(count <= length)
{
- memmove(buffer, session->inbuf, count);
+ memcpy(buffer, session->inbuf, count);
// Move the stuff left in inbuf to the beginning of it
memmove(session->inbuf, session->inbuf + count, (length - count));
// Now we need to set session->inbufoffset to the amount of data still waiting to be handed to insp.
else
{
// There's not as much in the inbuf as there is space in the buffer, so just copy the whole thing.
- memmove(buffer, session->inbuf, length);
+ memcpy(buffer, session->inbuf, length);
// Zero the offset, as there's nothing there..
session->inbufoffset = 0;
// As above
{
if(ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED)
{
+ ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT,
+ "m_ssl_gnutls.so: Error while writing to fd %d: %s",
+ session->fd, gnutls_strerror(ret));
CloseSession(session);
}
else
return;
// Bugfix, only send this numeric for *our* SSL users
- if (dest->GetExt("ssl", dummy) || ((IS_LOCAL(dest) && (dest->io == this))))
+ if (dest->GetExt("ssl", dummy) || ((IS_LOCAL(dest) && (dest->GetIOHook() == this))))
{
ServerInstance->SendWhoisLine(source, dest, 320, "%s %s :is using a secure connection", source->nick.c_str(), dest->nick.c_str());
}
else
{
// Handshake failed.
+ ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT,
+ "m_ssl_gnutls.so: Handshake failed on fd %d: %s",
+ session->fd, gnutls_strerror(ret));
CloseSession(session);
session->status = ISSL_CLOSING;
}
/* Beware here we do not check for errors.
*/
- if ((gnutls_x509_crt_get_expiration_time(cert) < time(0)) || (gnutls_x509_crt_get_activation_time(cert) > time(0)))
+ if ((gnutls_x509_crt_get_expiration_time(cert) < ServerInstance->Time()) || (gnutls_x509_crt_get_activation_time(cert) > ServerInstance->Time()))
{
certinfo->data.insert(std::make_pair("error","Not activated, or expired certificate"));
}