diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/db_plain.cpp | 3 | ||||
-rw-r--r-- | src/main.c | 12 | ||||
-rw-r--r-- | src/misc.c | 15 | ||||
-rw-r--r-- | src/modules/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/modules/ssl/m_ssl.cpp | 150 |
5 files changed, 175 insertions, 6 deletions
diff --git a/src/core/db_plain.cpp b/src/core/db_plain.cpp index 65f936650..0ae6c47f8 100644 --- a/src/core/db_plain.cpp +++ b/src/core/db_plain.cpp @@ -556,8 +556,7 @@ class DBPlain : public Module void BackupDatabase() { /* Do not backup a database that doesn't exist */ - struct stat DBInfo; - if (stat(DatabaseFile.c_str(), &DBInfo)) + if (!IsFile(DatabaseFile)) { return; } diff --git a/src/main.c b/src/main.c index 234a2e023..4c91fcde2 100644 --- a/src/main.c +++ b/src/main.c @@ -389,10 +389,16 @@ std::string GetFullProgDir(char *argv0) static bool Connect() { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreServerConnect, OnPreServerConnect()); + if (MOD_RESULT != EVENT_CONTINUE) + { + return (MOD_RESULT == EVENT_ALLOW ? true : false); + } + /* Connect to the remote server */ - std::list<Uplink *>::iterator curr_uplink = Config.Uplinks.begin(), end_uplink = Config.Uplinks.end(); int servernum = 1; - for (; curr_uplink != end_uplink; ++curr_uplink, ++servernum) + for (std::list<Uplink *>::iterator curr_uplink = Config.Uplinks.begin(); curr_uplink != Config.Uplinks.end(); ++curr_uplink, ++servernum) { uplink_server = *curr_uplink; @@ -472,8 +478,6 @@ int main(int ac, char **av, char **envp) if ((i = init_secondary(ac, av)) != 0) return i; - FOREACH_MOD(I_OnPreServerConnect, OnPreServerConnect()); - /* If the first connect fails give up, don't sit endlessly trying to reconnect */ if (!Connect()) fatal_perror("Can't connect to any servers"); diff --git a/src/misc.c b/src/misc.c index 338737007..9b535b1ab 100644 --- a/src/misc.c +++ b/src/misc.c @@ -27,6 +27,21 @@ struct arc4_stream { /*************************************************************************/ +/** Check if a file exists + * @param filename The file + * @return true if the file exists, false if it doens't + */ +bool IsFile(const std::string &filename) +{ + struct stat fileinfo; + if (!stat(filename.c_str(), &fileinfo)) + { + return true; + } + + return false; +} + /** * toupper: Like the ANSI functions, but make sure we return an * int instead of a (signed) char. diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index ad66663c3..6cb5b5612 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -58,6 +58,7 @@ endforeach(SRC) file(GLOB MODULES_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*") remove_item_from_list(MODULES_FILES "CMakeFiles") remove_item_from_list(MODULES_FILES "mysql") +remove_item_from_list(MODULES_FILES "ssl") # Iterate through this directory searching for subdirectories, and creating modules for those subdirectories foreach(FILE ${MODULES_FILES}) diff --git a/src/modules/ssl/m_ssl.cpp b/src/modules/ssl/m_ssl.cpp new file mode 100644 index 000000000..8036de6ce --- /dev/null +++ b/src/modules/ssl/m_ssl.cpp @@ -0,0 +1,150 @@ +/* RequiredLibraries: ssl,crypt */ + +#include "module.h" + +#include <openssl/bio.h> +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <openssl/crypto.h> +#include <openssl/evp.h> + +#define CERTFILE "anope.cert" +#define KEYFILE "anope.key" + +static SSL_CTX *ctx; + +class SSLSocket : public Socket +{ + private: + SSL *sslsock; + + int RecvInternal(char *buf, size_t sz) const + { + return SSL_read(sslsock, buf, sz); + } + + int SendInternal(const std::string &buf) const + { + return SSL_write(sslsock, buf.c_str(), buf.size()); + } + public: + SSLSocket(const std::string &nTargetHost, int nPort, const std::string &nBindHost = "", bool nIPv6 = false) : Socket(nTargetHost, nPort, nBindHost, nIPv6) + { + sslsock = SSL_new(ctx); + + if (!sslsock) + throw CoreException("Unable to initialize SSL socket"); + + SSL_set_connect_state(sslsock); + SSL_set_fd(sslsock, Sock); + SSL_connect(sslsock); + + UplinkSock = this; + } + + ~SSLSocket() + { + SSL_shutdown(sslsock); + SSL_free(sslsock); + + UplinkSock = NULL; + } + + bool Read(const std::string &buf) + { + process(buf); + return true; + } +}; + +class SSLModule : public Module +{ + public: + SSLModule(const std::string &modname, const std::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetVersion("$Id$"); + this->SetType(SUPPORTED); + + SSL_load_error_strings(); + SSLeay_add_ssl_algorithms(); + + ctx = SSL_CTX_new(SSLv23_client_method()); + + if (!ctx) + { + throw ModuleException("Error initializing SSL CTX"); + } + + if (IsFile(CERTFILE)) + { + if (!SSL_CTX_use_certificate_file(ctx, CERTFILE, SSL_FILETYPE_PEM)) + { + SSL_CTX_free(ctx); + throw ModuleException("Error loading certificate"); + } + } + else + { + Alog() << "m_ssl: No certificate file found"; + } + + if (IsFile(KEYFILE)) + { + if (!SSL_CTX_use_PrivateKey_file(ctx, KEYFILE, SSL_FILETYPE_PEM)) + { + SSL_CTX_free(ctx); + throw ModuleException("Error loading private key"); + } + } + else + { + if (IsFile(CERTFILE)) + { + SSL_CTX_free(ctx); + throw ModuleException("Error loading private key - file not found"); + } + else + { + Alog() << "m_ssl: No private key found"; + } + } + + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(ctx, SSL_OP_TLS_ROLLBACK_BUG | SSL_OP_ALL); +// SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, always_accept_verify_cb); + + ModuleManager::Attach(I_OnPreServerConnect, this); + } + + ~SSLModule() + { + SSL_CTX_free(ctx); + } + + EventReturn OnPreServerConnect() + { + int servernum = 1; + for (std::list<Uplink *>::iterator curr_uplink = Config.Uplinks.begin(); curr_uplink != Config.Uplinks.end(); ++curr_uplink, ++servernum) + { + uplink_server = *curr_uplink; + + try + { + new SSLSocket(uplink_server->host, uplink_server->port, Config.LocalHost ? Config.LocalHost : "", uplink_server->ipv6); + } + catch (SocketException& ex) + { + Alog() << "Unable to connect to server" << servernum << " (" << uplink_server->host << ":" << uplink_server->port << "), " << ex.GetReason(); + continue; + } + + Alog() << "Connected to Server " << servernum << " (" << uplink_server->host << ":" << uplink_server->port << ")"; + return EVENT_ALLOW; + } + + return EVENT_STOP; + } +}; + +MODULE_INIT(SSLModule) |