From 50affd176a3e83c728d9ce3c9b48c13833e107df Mon Sep 17 00:00:00 2001 From: Aaron Blakely Date: Thu, 14 Mar 2024 03:20:38 -0500 Subject: [PATCH] moved openssl code into a module --- Makefile | 2 +- lib/irc.h | 39 +++++++--- lib/module.h | 9 ++- lib/util.h | 2 +- mods/openssl.dll | Bin 0 -> 47104 bytes mods/openssl.lib | Bin 0 -> 3020 bytes mods/openssl/Makefile | 7 ++ mods/openssl/make.bat | 7 ++ mods/openssl/openssl.c | 76 ++++++++++++++++--- src/irc.c | 167 ++++++++++++++++++++++------------------- src/main.c | 14 +--- src/module.c | 33 +++++++- xbot.cfg | 4 +- xbot.vcxproj | 6 +- 14 files changed, 244 insertions(+), 122 deletions(-) create mode 100755 mods/openssl.dll create mode 100755 mods/openssl.lib create mode 100755 mods/openssl/Makefile create mode 100755 mods/openssl/make.bat mode change 100644 => 100755 mods/openssl/openssl.c diff --git a/Makefile b/Makefile index d095d14..eff4582 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC=gcc CFLAGS=-g -std=gnu99 -c -lconfig -ldl -I./lib -BINFLAGS=-g -rdynamic -ldl -lconfig -lssl -lcrypto +BINFLAGS=-g -rdynamic -ldl -lconfig SRC=./src OBJ=./build OBJECTS=$(OBJ)/*.o diff --git a/lib/irc.h b/lib/irc.h index d5ee148..2540b99 100755 --- a/lib/irc.h +++ b/lib/irc.h @@ -17,9 +17,6 @@ #define OUTBUF_SIZE 1200000 #define INBUF_SIZE 1200000 -#include -#include - #ifdef _WIN32 #include #else @@ -29,16 +26,16 @@ struct irc_conn { + int ssl_fd; + + int ssl_fdi; + int srv_fdi; + #ifdef _WIN32 SOCKET srv_fd; #else FILE *srv_fd; #endif - - int ssl_fd; - SSL *ssl; - SSL_CTX *ctx; - char nick[50]; char user[50]; char admin[256]; @@ -49,15 +46,24 @@ struct irc_conn #ifdef _WIN32 BOOL use_ssl; BOOL verify_ssl; + + FARPROC sslmod_init; + FARPROC sslmod_connect; + FARPROC sslmod_read; + FARPROC sslmod_write; + FARPROC sslmod_cleanup; + FARPROC sslmod_get_fd; #else bool use_ssl; bool verify_ssl; bool sslmod_loaded; + void (*sslmod_init)(); void (*sslmod_connect)(); int (*sslmod_read)(); int (*sslmod_write)(); void (*sslmod_cleanup)(); + int (*sslmod_get_fd)(); #endif @@ -74,9 +80,20 @@ typedef struct handler event_handler; void irc_connect(struct irc_conn *bot); void irc_auth(struct irc_conn *bot); -void set_ssl_connect(struct irc_conn *bot, void *func); -void set_ssl_read(struct irc_conn *bot, void *func); -void set_ssl_write(struct irc_conn *bot, void *func); + +MY_API void set_ssl_init(struct irc_conn *bot, void *func); +MY_API void set_ssl_connect(struct irc_conn *bot, void *func); +MY_API void set_ssl_read(struct irc_conn *bot, void *func); +MY_API void set_ssl_write(struct irc_conn *bot, void *func); +MY_API void set_ssl_cleanup(struct irc_conn *bot, void *func); +MY_API void set_ssl_get_fd(struct irc_conn *bot, void *func); + +MY_API void ssl_init(); +MY_API void ssl_connect(); +MY_API int ssl_read(char *buf, int len); +MY_API int ssl_write(char *buf, int len); +MY_API void ssl_cleanup(); +MY_API int ssl_get_fd(); MY_API void irc_notice(struct irc_conn *bot, char *to, char *fmt, ...); MY_API void irc_privmsg(struct irc_conn *bot, char *to, char *fmt, ...); diff --git a/lib/module.h b/lib/module.h index 4f1c9e1..9f1343b 100755 --- a/lib/module.h +++ b/lib/module.h @@ -4,6 +4,11 @@ #include "irc.h" #include "events.h" +enum module_flags +{ + MOD_FLAG_NO_UNLOAD = 1, + MOD_FLAG_NO_RELOAD = 2 +}; struct module { char name[25]; @@ -12,6 +17,7 @@ struct module { char description[256]; char fname[256]; + int flags; #ifdef _WIN32 HMODULE handle; @@ -37,7 +43,8 @@ void unload_module(struct irc_conn *bot, char *where, char *file); void list_modules(struct irc_conn *bot, char *where); void set_bot(struct irc_conn *b); void set_bot_db(struct db_table *db); -MY_API void register_module(char *name, char *author, char *version, char *description); + +MY_API void register_module(char *name, char *author, char *version, char *description, ...); MY_API void unregister_module(char *name); MY_API struct mods *get_mods(); MY_API struct irc_conn *get_bot(); diff --git a/lib/util.h b/lib/util.h index 79774d9..8c7dc11 100755 --- a/lib/util.h +++ b/lib/util.h @@ -34,7 +34,7 @@ #define MY_API #endif -void eprint(char *fmt, ...); +MY_API void eprint(char *fmt, ...); #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 38)) || defined(_WIN32) MY_API void strlcpy(char *to, const char *from, int len); diff --git a/mods/openssl.dll b/mods/openssl.dll new file mode 100755 index 0000000000000000000000000000000000000000..6b88717580d7612adee7897cec07d67625e93866 GIT binary patch literal 47104 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 #include @@ -42,9 +40,21 @@ MY_API void sslmod_init(struct irc_conn *bot) } } -MY_API void sslmod_connect(struct irc_conn *bot) +MY_API int get_ssl_fd() { - if (SSL_set_fd(ssl, fileno(bot->srv_fd)) == 0) + printf("ssl_fd: %d\n", ssl_fd); + return ssl_fd; +} + +MY_API void sslmod_connect() +{ + struct irc_conn *bot = get_bot(); + +#ifdef _WIN32 + if (SSL_set_fd(ssl, bot->srv_fd) == 0) +#else + if (SSL_set_fd(ssl, bot->srv_fdi) == 0) +#endif { eprint("Error: Cannot set SSL file descriptor\n"); } @@ -54,18 +64,66 @@ MY_API void sslmod_connect(struct irc_conn *bot) eprint("Error: Cannot connect to SSL server\n"); } - ssl_fd = fileno(bot->srv_fd); +#ifdef _WIN32 + bot->ssl_fd = bot->srv_fd; +#else + bot->ssl_fd = bot->srv_fdi; +#endif +} + +MY_API void sslmod_write(char *buf, int len) +{ + int n; + if ((n = SSL_write(ssl, buf, len)) <= 0) + { + eprint("Error: Cannot write to SSL server\n"); + } +} + +MY_API int sslmod_read(char *buf, int len) +{ + int n; + unsigned long ssl_err; + + if ((n = SSL_read(ssl, buf, len)) <= 0) + { + eprint("xbot: error on SSL_read()\n"); + + ssl_err = ERR_get_error(); + if (ssl_err) + { + eprint("SSL error: %s\n", ERR_error_string(ssl_err, NULL)); + } + + return -1; + } + return n; +} + +MY_API void sslmod_cleanup() +{ + SSL_shutdown(ssl); + SSL_free(ssl); + SSL_CTX_free(ctx); + ERR_free_strings(); + EVP_cleanup(); } MY_API void mod_init() { - register_module("openssl", "Aaron Blakely", "1.0", "SSL/TLS support using OpenSSL"); + struct irc_conn *bot = get_bot(); + register_module("openssl", "Aaron Blakely", "1.0", "SSL/TLS support using OpenSSL", MOD_FLAG_NO_UNLOAD); + set_ssl_init(bot, sslmod_init); + set_ssl_connect(bot, sslmod_connect); + set_ssl_write(bot, sslmod_write); + set_ssl_read(bot, sslmod_read); + set_ssl_cleanup(bot, sslmod_cleanup); + printf("OpenSSL module loaded\n"); } -MY_API void mod_unlaod() +MY_API void mod_unload() { - unregister_module("openssl"); - + // should never be called because of MOD_FLAG_NO_UNLOAD } diff --git a/src/irc.c b/src/irc.c index d158df7..ce2b6fb 100755 --- a/src/irc.c +++ b/src/irc.c @@ -11,6 +11,7 @@ #include "irc.h" #include "util.h" #include "events.h" +#include "module.h" #include "channel.h" #include @@ -44,29 +45,7 @@ void irc_connect(struct irc_conn *bot) SetConsoleTitle(titlebuf); if (bot->use_ssl) - { - SSL_library_init(); - SSL_load_error_strings(); - bot->ctx = SSL_CTX_new(SSLv23_client_method()); - if (bot->ctx == NULL) - { - eprint("Error: Cannot create SSL context\n"); - } - - if (bot->verify_ssl) - { - SSL_CTX_set_verify(bot->ctx, SSL_VERIFY_PEER, NULL); - } - else - { - SSL_CTX_set_verify(bot->ctx, SSL_VERIFY_NONE, NULL); - } - - if ((bot->ssl = SSL_new(bot->ctx)) == NULL) - { - eprint("Error: Cannot create SSL object\n"); - } - } + ssl_init(); if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { eprint("WSAStartup failed.\n"); @@ -115,52 +94,16 @@ void irc_connect(struct irc_conn *bot) if (bot->use_ssl) - { - if (SSL_set_fd(bot->ssl, bot->srv_fd) == 0) - { - eprint("Error: Cannot set SSL file descriptor\n"); - } - - if (SSL_connect(bot->ssl) != 1) - { - eprint("Error: Cannot connect to SSL server\n"); - } - - bot->ssl_fd = bot->srv_fd; - } + ssl_connect(); sprintf(titlebuf, "xbot [connected]: %s:%s", bot->host, bot->port); SetConsoleTitle(titlebuf); #else - int srv_fd; struct addrinfo hints; struct addrinfo *res, *r; if (bot->use_ssl) - { - SSL_library_init(); - SSL_load_error_strings(); - bot->ctx = SSL_CTX_new(SSLv23_client_method()); - if (bot->ctx == NULL) - { - eprint("Error: Cannot create SSL context\n"); - } - - if (bot->verify_ssl) - { - SSL_CTX_set_verify(bot->ctx, SSL_VERIFY_PEER, NULL); - } - else - { - SSL_CTX_set_verify(bot->ctx, SSL_VERIFY_NONE, NULL); - } - - if ((bot->ssl = SSL_new(bot->ctx)) == NULL) - { - eprint("Error: Cannot create SSL object\n"); - } - } - + ssl_init(); memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; @@ -173,17 +116,17 @@ void irc_connect(struct irc_conn *bot) for (r = res; r; r->ai_next) { - if ((srv_fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1) + if ((bot->srv_fdi = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1) { continue; } - if (connect(srv_fd, r->ai_addr, r->ai_addrlen) == 0) + if (connect(bot->srv_fdi, r->ai_addr, r->ai_addrlen) == 0) { break; } - close(srv_fd); + close(bot->srv_fdi); } freeaddrinfo(res); @@ -194,21 +137,9 @@ void irc_connect(struct irc_conn *bot) if (bot->use_ssl) - { - if (SSL_set_fd(bot->ssl, srv_fd) == 0) - { - eprint("Error: Cannot set SSL file descriptor\n"); - } + ssl_connect(); - if (SSL_connect(bot->ssl) != 1) - { - eprint("Error: Cannot connect to SSL server\n"); - } - - bot->ssl_fd = srv_fd; - } - - bot->srv_fd = FDOPEN(srv_fd, "r+"); + bot->srv_fd = FDOPEN(bot->srv_fdi, "r+"); xlog("[IRC] Connected!\n"); #endif } @@ -227,6 +158,84 @@ void irc_auth(struct irc_conn *bot) #endif } +void set_ssl_init(struct irc_conn *bot, void *func) +{ + bot->sslmod_init = func; +} + +void set_ssl_connect(struct irc_conn *bot, void *func) +{ + bot->sslmod_connect = func; +} + +void set_ssl_write(struct irc_conn *bot, void *func) +{ + bot->sslmod_write = func; +} + +void set_ssl_read(struct irc_conn *bot, void *func) +{ + bot->sslmod_read = func; +} + +void set_ssl_cleanup(struct irc_conn *bot, void *func) +{ + bot->sslmod_cleanup = func; +} + +void set_ssl_get_fd(struct irc_conn *bot, void *func) +{ + bot->sslmod_get_fd = func; +} + +void ssl_init() +{ + struct irc_conn *bot = get_bot(); + void *sslinit = bot->sslmod_init; + + ((void (*)())sslinit)(); +} + +void ssl_connect() +{ + struct irc_conn *bot = get_bot(); + void *sslconnect = bot->sslmod_connect; + + ((void (*)())sslconnect)(); +} + +int ssl_read(char *buf, int len) +{ + struct irc_conn *bot = get_bot(); + void *sslread = bot->sslmod_read; + + return ((int (*)(char *, int))sslread)(buf, len); +} + +int ssl_write(char *buf, int len) +{ + struct irc_conn *bot = get_bot(); + void *sslwrite = bot->sslmod_write; + + return ((int (*)(char *, int))sslwrite)(buf, len); +} + +void ssl_cleanup() +{ + struct irc_conn *bot = get_bot(); + void *sslcleanup = bot->sslmod_cleanup; + + ((void (*)())sslcleanup)(); +} + +int ssl_get_fd() +{ + struct irc_conn *bot = get_bot(); + void *sslgetfd = bot->sslmod_get_fd; + + return ((int (*)())sslgetfd)(); +} + void irc_notice(struct irc_conn *bot, char *to, char *fmt, ...) { char msg_[4096]; @@ -266,7 +275,7 @@ void irc_raw(struct irc_conn *bot, char *fmt, ...) if (bot->use_ssl) { sprintf(outbuf, "%s\r\n", bot->out); - if (SSL_write(bot->ssl, outbuf, strlen(outbuf)) <= 0) + if (ssl_write(outbuf, strlen(outbuf)) <= 0) { eprint("Error: Cannot write to SSL server\n"); } diff --git a/src/main.c b/src/main.c index 1b34ee1..74d808c 100755 --- a/src/main.c +++ b/src/main.c @@ -149,7 +149,7 @@ int main(int argc, char **argv) if (bot.use_ssl) { - FD_SET(SSL_get_fd(bot.ssl), &rd); + FD_SET(bot.ssl_fd, &rd); } else { @@ -210,20 +210,10 @@ int main(int argc, char **argv) { if (bot.use_ssl) { - bytesRecv = SSL_read(bot.ssl, bot.in, INBUF_SIZE); + bytesRecv = ssl_read(bot.in, INBUF_SIZE); if (bytesRecv <= 0) { - eprint("xbot: error on SSL_read()\n"); - - ssl_err = ERR_get_error(); - if (ssl_err) - { - eprint("SSL error: %s\n", ERR_error_string(ssl_err, NULL)); - } - - return -1; - } bot.in[bytesRecv] = '\0'; diff --git a/src/module.c b/src/module.c index c245d43..8cc49d2 100755 --- a/src/module.c +++ b/src/module.c @@ -5,6 +5,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -222,10 +223,23 @@ void unload_module(struct irc_conn *bot, char *where, char *file) int i; for (i = 0; i < mods->count; i++) { - (*mods->modules[i].unload)(); - if (strcmp(mods->modules[i].fname, file) == 0) { + if (mods->modules[i].flags & MOD_FLAG_NO_UNLOAD) + { + if (strcmp(PRIVMSG_CHAN, where)) + { + irc_notice(bot, where, "Module '%s' cannot be unloaded.", file); + } + else + { + xlog("[module] Module '%s' cannot be unloaded.\n", file); + } + return; + } + + + (*mods->modules[i].unload)(); #ifdef _WIN32 FreeLibrary(mods->modules[i].handle); #else @@ -270,8 +284,10 @@ void list_modules(struct irc_conn *bot, char *where) free(tmp); } -MY_API void register_module(char *name, char *author, char *version, char *description) +MY_API void register_module(char *name, char *author, char *version, char *description, ...) { + va_list args; + if (mods->count >= 512) { eprint("Error: Too many modules loaded.\n"); @@ -282,6 +298,17 @@ MY_API void register_module(char *name, char *author, char *version, char *descr strlcpy(mods->modules[mods->count].author, author, 50); strlcpy(mods->modules[mods->count].version, version, 10); strlcpy(mods->modules[mods->count].description, description, 256); + + va_start(args, description); + + mods->modules[mods->count].flags = va_arg(args, int); + + if (mods->modules[mods->count].flags & MOD_FLAG_NO_UNLOAD) + { + xlog("[module] Module '%s' cannot be unloaded.\n", name); + } + + va_end(args); } MY_API void unregister_module(char *name) diff --git a/xbot.cfg b/xbot.cfg index 0c57e62..d16b2c9 100755 --- a/xbot.cfg +++ b/xbot.cfg @@ -20,9 +20,9 @@ bot: server: { host = "memphis.ephasic.org"; - port = "6697"; + port = "6667"; - ssl = true; + ssl = false; ssl_verify = false; }; diff --git a/xbot.vcxproj b/xbot.vcxproj index 5e7348a..41b44ee 100755 --- a/xbot.vcxproj +++ b/xbot.vcxproj @@ -62,7 +62,7 @@ Disabled - .;lib;include\openssl-3.2.1\include;include\libconfig-1.7.3\lib;%(AdditionalIncludeDirectories) + .;lib;include\libconfig-1.7.3\lib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;MY_DLL_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks @@ -73,8 +73,8 @@ EditAndContinue - libcrypto.lib;libssl.lib;libconfig.lib;ws2_32.lib;%(AdditionalDependencies) - include;include\openssl-3.2.1\lib;%(AdditionalLibraryDirectories) + libconfig.lib;ws2_32.lib;%(AdditionalDependencies) + include;%(AdditionalLibraryDirectories) true Console MachineX86