* ---------------------------------------------------
*/
-#include <string>
-#include <vector>
+#include "inspircd.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
-#include "inspircd_config.h"
+#ifdef WINDOWS
+#include <openssl/applink.c>
+#endif
+
#include "configreader.h"
#include "users.h"
#include "channels.h"
#include "socket.h"
#include "hashcomp.h"
-#include "inspircd.h"
#include "transport.h"
+#ifdef WINDOWS
+#pragma comment(lib, "libeay32MTd")
+#pragma comment(lib, "ssleay32MTd")
+#undef MAX_DESCRIPTORS
+#define MAX_DESCRIPTORS 10000
+#endif
+
/* $ModDesc: Provides SSL support for clients */
/* $CompileFlags: pkgconfversion("openssl","0.9.7") pkgconfincludes("openssl","/openssl/ssl.h","") */
/* $LinkerFlags: rpath("pkg-config --libs openssl") pkgconflibs("openssl","/libssl.so","-lssl -lcrypto -ldl") */
SSL_CTX* clictx;
char* dummy;
+ char cipher[MAXBUF];
std::string keyfile;
std::string certfile;
std::string cafile;
// std::string crlfile;
std::string dhfile;
+ std::string sslports;
int clientactive;
InspIRCd* PublicInstance;
ModuleSSLOpenSSL(InspIRCd* Me)
- : Module::Module(Me), PublicInstance(Me)
+ : Module(Me), PublicInstance(Me)
{
ServerInstance->PublishInterface("InspSocketHook", this);
listenports.clear();
clientactive = 0;
+ sslports.clear();
for (int i = 0; i < Conf->Enumerate("bind"); i++)
{
// For each <bind> tag
- if (((Conf->ReadValue("bind", "type", i) == "") || (Conf->ReadValue("bind", "type", i) == "clients")) && (Conf->ReadValue("bind", "ssl", i) == "openssl"))
+ std::string x = Conf->ReadValue("bind", "type", i);
+ if (((x.empty()) || (x == "clients")) && (Conf->ReadValue("bind", "ssl", i) == "openssl"))
{
// Get the port we're meant to be listening on with SSL
std::string port = Conf->ReadValue("bind", "port", i);
if (ServerInstance->Config->AddIOHook(portno, this))
{
listenports.push_back(portno);
- for (unsigned int i = 0; i < ServerInstance->stats->BoundPortCount; i++)
- if (ServerInstance->Config->ports[i] == portno)
- ServerInstance->Config->openSockfd[i]->SetDescription("ssl");
+ for (size_t i = 0; i < ServerInstance->Config->ports.size(); i++)
+ if (ServerInstance->Config->ports[i]->GetPort() == portno)
+ ServerInstance->Config->ports[i]->SetDescription("ssl");
ServerInstance->Log(DEFAULT, "m_ssl_openssl.so: Enabling SSL for port %d", portno);
+ sslports.append("*:").append(ConvToStr(portno)).append(";");
}
else
{
}
}
- std::string confdir(CONFIG_FILE);
+ if (!sslports.empty())
+ sslports.erase(sslports.end() - 1);
+
+ std::string confdir(ServerInstance->ConfigFileName);
// +1 so we the path ends with a /
confdir = confdir.substr(0, confdir.find_last_of('/') + 1);
dhfile = Conf->ReadValue("openssl", "dhfile", 0);
// Set all the default values needed.
- if (cafile == "")
+ if (cafile.empty())
cafile = "ca.pem";
- if (certfile == "")
+ if (certfile.empty())
certfile = "cert.pem";
- if (keyfile == "")
+ if (keyfile.empty())
keyfile = "key.pem";
- if (dhfile == "")
+ if (dhfile.empty())
dhfile = "dhparams.pem";
// Prepend relative paths with the path to the config directory.
if (cafile[0] != '/')
cafile = confdir + cafile;
- //if(crlfile[0] != '/')
- // crlfile = confdir + crlfile;
-
if (certfile[0] != '/')
certfile = confdir + certfile;
DELETE(Conf);
}
+ virtual void On005Numeric(std::string &output)
+ {
+ output.append(" SSL=" + sslports);
+ }
+
virtual ~ModuleSSLOpenSSL()
{
SSL_CTX_free(ctx);
{
// 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->GlobalCulls.AddItem(user, "SSL module unloading");
+ userrec::QuitUser(ServerInstance, user, "SSL module unloading");
}
if (user->GetExt("ssl_cert", dummy) && isin(user->GetPort(), listenports))
{
for(unsigned int i = 0; i < listenports.size(); i++)
{
ServerInstance->Config->DelIOHook(listenports[i]);
- for (unsigned int j = 0; j < ServerInstance->stats->BoundPortCount; j++)
- if (ServerInstance->Config->ports[j] == listenports[i])
- if (ServerInstance->Config->openSockfd[j])
- ServerInstance->Config->openSockfd[j]->SetDescription("plaintext");
+ for (size_t j = 0; j < ServerInstance->Config->ports.size(); j++)
+ if (ServerInstance->Config->ports[j]->GetPort() == listenports[i])
+ ServerInstance->Config->ports[j]->SetDescription("plaintext");
}
}
}
void Implements(char* List)
{
- List[I_OnRawSocketConnect] = List[I_OnRawSocketAccept] = List[I_OnRawSocketClose] = List[I_OnRawSocketRead] = List[I_OnRawSocketWrite] = List[I_OnCleanup] = 1;
- List[I_OnRequest] = List[I_OnSyncUserMetaData] = List[I_OnDecodeMetaData] = List[I_OnUnloadModule] = List[I_OnRehash] = List[I_OnWhois] = List[I_OnPostConnect] = 1;
+ List[I_OnRawSocketConnect] = List[I_OnRawSocketAccept] = List[I_OnRawSocketClose] = List[I_OnRawSocketRead] = List[I_OnRawSocketWrite] = List[I_OnCleanup] = List[I_On005Numeric] = 1;
+ List[I_OnBufferFlushed] = List[I_OnRequest] = List[I_OnSyncUserMetaData] = List[I_OnDecodeMetaData] = List[I_OnUnloadModule] = List[I_OnRehash] = List[I_OnWhois] = List[I_OnPostConnect] = 1;
}
virtual char* OnRequest(Request* request)
}
else if (strcmp("IS_HSDONE", request->GetId()) == 0)
{
+ ServerInstance->Log(DEBUG,"Module checking if handshake is done");
if (ISR->Sock->GetFd() < 0)
return (char*)"OK";
}
else
{
+ errno = EAGAIN;
return -1;
}
}
{
int ret = DoRead(session);
+ ServerInstance->Log(DEBUG, "<***> DoRead count: " + ConvToStr(count));
+ ServerInstance->Log(DEBUG, "<***> DoRead ret: " + ConvToStr(ret));
+ ServerInstance->Log(DEBUG, "<***> DoRead session->inbufoffset: " + ConvToStr(session->inbufoffset));
+
if (ret > 0)
{
if (count <= session->inbufoffset)
}
session->outbuf.append(buffer, count);
+ MakePollWrite(session);
if (session->status == ISSL_HANDSHAKING)
{
// The handshake isn't finished, try to finish it.
if (session->rstat == ISSL_WRITE || session->wstat == ISSL_WRITE)
+ {
Handshake(session);
+ }
}
if (session->status == ISSL_OPEN)
{
if (session->rstat == ISSL_WRITE)
+ {
DoRead(session);
+ }
if (session->wstat == ISSL_WRITE)
+ {
return DoWrite(session);
+ }
}
return 1;
{
// Is this right? Not sure if the unencrypted data is garaunteed to be the same length.
// Read into the inbuffer, offset from the beginning by the amount of data we have that insp hasn't taken yet.
-
+
int ret = SSL_read(session->sess, session->inbuf + session->inbufoffset, inbufsize - session->inbufoffset);
if (ret == 0)
else if (err == SSL_ERROR_WANT_WRITE)
{
session->rstat = ISSL_WRITE;
+ MakePollWrite(session);
return -1;
}
else
}
}
- virtual void OnSyncUserMetaData(userrec* user, Module* proto, void* opaque, const std::string &extname)
+ virtual void OnSyncUserMetaData(userrec* user, Module* proto, void* opaque, const std::string &extname, bool displayable)
{
// check if the linking module wants to know about OUR metadata
if (extname == "ssl")
{
// call this function in the linking module, let it format the data how it
// sees fit, and send it on its way. We dont need or want to know how.
- proto->ProtoSendMetaData(opaque, TYPE_USER, user, extname, "ON");
+ proto->ProtoSendMetaData(opaque, TYPE_USER, user, extname, displayable ? "Enabled" : "ON");
}
}
}
int ret;
if (session->outbound)
+ {
ret = SSL_connect(session->sess);
+ }
else
ret = SSL_accept(session->sess);
{
session->rstat = ISSL_READ;
session->status = ISSL_HANDSHAKING;
+ return true;
}
else if (err == SSL_ERROR_WANT_WRITE)
{
session->wstat = ISSL_WRITE;
session->status = ISSL_HANDSHAKING;
MakePollWrite(session);
+ return true;
}
else
{
}
else if (ret == 0)
{
+ int ssl_err = SSL_get_error(session->sess, ret);
+ char buf[1024];
+ ERR_print_errors_fp(stderr);
+ ServerInstance->Log(DEBUG,"Handshake fail 2: %d: %s", ssl_err, ERR_error_string(ssl_err,buf));
CloseSession(session);
return true;
}
DELETE(metadata);
VerifyCertificate(&sessions[user->GetFd()], user);
+ if (sessions[user->GetFd()].sess)
+ user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick, SSL_get_cipher(sessions[user->GetFd()].sess));
}
}
void MakePollWrite(issl_session* session)
{
- OnRawSocketWrite(session->fd, NULL, 0);
+ //OnRawSocketWrite(session->fd, NULL, 0);
+ EventHandler* eh = ServerInstance->FindDescriptor(session->fd);
+ if (eh)
+ ServerInstance->SE->WantWrite(eh);
+ }
+
+ virtual void OnBufferFlushed(userrec* user)
+ {
+ if (user->GetExt("ssl"))
+ {
+ ServerInstance->Log(DEBUG,"OnBufferFlushed for ssl user");
+ issl_session* session = &sessions[user->GetFd()];
+ if (session && session->outbuf.size())
+ OnRawSocketWrite(user->GetFd(), NULL, 0);
+ }
}
void CloseSession(issl_session* session)
return 0;
}
-class ModuleSSLOpenSSLFactory : public ModuleFactory
-{
- public:
- ModuleSSLOpenSSLFactory()
- {
- }
+MODULE_INIT(ModuleSSLOpenSSL);
- ~ModuleSSLOpenSSLFactory()
- {
- }
-
- virtual Module * CreateModule(InspIRCd* Me)
- {
- return new ModuleSSLOpenSSL(Me);
- }
-};
-
-
-extern "C" void * init_module( void )
-{
- return new ModuleSSLOpenSSLFactory;
-}