added SSL support for linux

This commit is contained in:
Aaron Blakely 2024-03-11 05:22:05 -05:00
parent 0661b29519
commit e0041ac970
8 changed files with 237 additions and 22 deletions

View File

@ -1,6 +1,6 @@
CC=gcc CC=gcc
CFLAGS=-g -std=gnu99 -c -lconfig -ldl -I./lib CFLAGS=-g -std=gnu99 -c -lconfig -ldl -I./lib
BINFLAGS=-g -rdynamic -ldl -lconfig BINFLAGS=-g -rdynamic -ldl -lconfig -lssl -lcrypto
SRC=./src SRC=./src
OBJ=./build OBJ=./build
OBJECTS=$(OBJ)/*.o OBJECTS=$(OBJ)/*.o

View File

@ -18,10 +18,12 @@
#include <winsock2.h> #include <winsock2.h>
#else #else
#include <stdbool.h> #include <stdbool.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif #endif
#define OUTBUF_SIZE 60000 #define OUTBUF_SIZE 1200000
#define INBUF_SIZE 60000 #define INBUF_SIZE 1200000
struct irc_conn struct irc_conn
{ {
@ -29,6 +31,9 @@ struct irc_conn
SOCKET srv_fd; SOCKET srv_fd;
#else #else
FILE *srv_fd; FILE *srv_fd;
int ssl_fd;
SSL *ssl;
SSL_CTX *ctx;
#endif #endif
char nick[50]; char nick[50];
@ -38,6 +43,14 @@ struct irc_conn
char port[5]; char port[5];
char real_name[512]; char real_name[512];
#ifdef _WIN32
BOOL use_ssl;
BOOL verify_ssl;
#else
bool use_ssl;
bool verify_ssl;
#endif
char db_file[256]; char db_file[256];
char log_file[256]; char log_file[256];
struct db_table *db; struct db_table *db;

View File

@ -9,6 +9,16 @@
#include "logger.h" #include "logger.h"
#define DEBUG 1
#ifdef DEBUG
#define BREAKPOINT() asm("int $3")
#else
#define BREAKPOINT()
#endif
#ifdef _WIN32 #ifdef _WIN32
#define true TRUE #define true TRUE
#define false FALSE #define false FALSE
@ -34,7 +44,14 @@ MY_API void strlcpy(char *to, const char *from, int len);
MY_API char *basename(char *path); MY_API char *basename(char *path);
#endif #endif
// skip - skip over characters in a string
// s - the string to skip over
// c - the character to skip over
//
// returns a pointer to the first non-matching character
MY_API char *skip(char *s, char c); MY_API char *skip(char *s, char c);
// trim - remove leading and trailing whitespace from a string
MY_API void trim(char *s); MY_API void trim(char *s);
#endif #endif

View File

@ -13,6 +13,7 @@ struct irc_conn read_config(struct irc_conn bot, char *file)
const config_setting_t *autoload; const config_setting_t *autoload;
const char *base = (const char*)malloc(sizeof(char) * 1024); const char *base = (const char*)malloc(sizeof(char) * 1024);
const char *mod = NULL; const char *mod = NULL;
int boolbase;
char *modpath = (char *)malloc(sizeof(char) * 500); char *modpath = (char *)malloc(sizeof(char) * 500);
@ -54,6 +55,13 @@ struct irc_conn read_config(struct irc_conn bot, char *file)
if (config_lookup_string(cf, "bot.log", &base)) if (config_lookup_string(cf, "bot.log", &base))
strlcpy(bot.log_file, base, sizeof bot.log_file); strlcpy(bot.log_file, base, sizeof bot.log_file);
if (config_lookup_bool(cf, "server.ssl", &boolbase))
bot.use_ssl = boolbase;
if (config_lookup_bool(cf, "server.ssl_verify", &boolbase))
bot.verify_ssl = boolbase;
config_destroy(cf); config_destroy(cf);
return bot; return bot;

119
src/irc.c
View File

@ -21,6 +21,7 @@
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <schannel.h>
#define FDOPEN _fdopen #define FDOPEN _fdopen
#define SETBUF setbuf #define SETBUF setbuf
#else #else
@ -29,6 +30,9 @@
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define FDOPEN fdopen #define FDOPEN fdopen
#define SETBUF setbuf #define SETBUF setbuf
#endif #endif
@ -41,6 +45,43 @@ void irc_connect(struct irc_conn *bot)
struct sockaddr_in server; struct sockaddr_in server;
struct hostent *host; struct hostent *host;
// SChannel stuff
SCHANNEL_CRED schannelCred;
CtxtHandle ctxtHandle;
SecBufferDesc outBufferDesc;
SecBuffer outBuffer;
SECURITY_STATUS secStatus;
DWORD dwSSPIFlags;
if (bot->use_ssl)
{
ZeroMemory(&schannelCred, sizeof(schannelCred));
ZeroMemory(&ctxtHandle, sizeof(ctxtHandle));
ZeroMemory(&outBufferDesc, sizeof(outBufferDesc));
ZeroMemory(&outBuffer, sizeof(outBuffer));
// init outbufferdesc and outbuffer
outBufferDesc.ulVersion = SECBUFFER_VERSION;
outBufferDesc.cBuffers = 1;
outBufferDesc.pBuffers = &outBuffer;
outBuffer.BufferType = SECBUFFER_TOKEN;
outBuffer.cbBuffer = 0;
outBuffer.pvBuffer = NULL;
// setup the credentials
schannelCred.dwVersion = SCHANNEL_CRED_VERSION;
schannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
schannelCred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SYSTEM_MAPPER;
schannelCred.cCreds = 1;
schannelCred.paCred = &bot->cred;
schannelCred.hRootStore = NULL;
schannelCred.dwMinimumCipherStrength = 128;
schannelCred.dwMaximumCipherStrength = 128;
schannelCred.dwSessionLifespan = 0;
}
sprintf(titlebuf, "xbot [connecting]: %s:%s", bot->host, bot->port); sprintf(titlebuf, "xbot [connecting]: %s:%s", bot->host, bot->port);
SetConsoleTitle(titlebuf); SetConsoleTitle(titlebuf);
@ -89,6 +130,26 @@ void irc_connect(struct irc_conn *bot)
return; return;
} }
if (bot->use_ssl)
{
// perform the handshake
secStatus = InitalizeSecurityContet(NULL, NULL, NULL, dwSSPIFlags, 0, 0, NULL, 0, &ctxtHandle, &outBufferDesc, NULL, NULL);
if (secStatus != SEC_I_CONTINUE_NEEDED)
{
eprint("Error: Handshake failed\n");
exit(EXIT_FAILURE);
}
// send the handshake
if (send(bot->srv_fd, outBuffer.pvBuffer, outBuffer.cbBuffer, 0) == SOCKET_ERROR)
{
eprint("Error: Handshake failed\n");
exit(EXIT_FAILURE);
}
}
sprintf(titlebuf, "xbot [connected]: %s:%s", bot->host, bot->port); sprintf(titlebuf, "xbot [connected]: %s:%s", bot->host, bot->port);
SetConsoleTitle(titlebuf); SetConsoleTitle(titlebuf);
#else #else
@ -96,6 +157,32 @@ void irc_connect(struct irc_conn *bot)
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *res, *r; 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");
}
}
memset(&hints, 0, sizeof hints); memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
@ -126,8 +213,24 @@ void irc_connect(struct irc_conn *bot)
eprint("[IRC] Error: Cannot connect to host '%s'\n", bot->host); eprint("[IRC] Error: Cannot connect to host '%s'\n", bot->host);
} }
xlog("[IRC] Connected!\n");
if (bot->use_ssl)
{
if (SSL_set_fd(bot->ssl, 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 = srv_fd;
}
bot->srv_fd = FDOPEN(srv_fd, "r+"); bot->srv_fd = FDOPEN(srv_fd, "r+");
xlog("[IRC] Connected!\n");
#endif #endif
} }
@ -137,8 +240,11 @@ void irc_auth(struct irc_conn *bot)
irc_raw(bot, "USER %s \" %s :%s", bot->user, bot->host, bot->real_name); irc_raw(bot, "USER %s \" %s :%s", bot->user, bot->host, bot->real_name);
#ifndef _WIN32 #ifndef _WIN32
if (!bot->use_ssl)
{
fflush(bot->srv_fd); fflush(bot->srv_fd);
SETBUF(bot->srv_fd, NULL); SETBUF(bot->srv_fd, NULL);
}
#endif #endif
} }
@ -182,7 +288,18 @@ void irc_raw(struct irc_conn *bot, char *fmt, ...)
sprintf(outbuf, "%s\r\n", bot->out); sprintf(outbuf, "%s\r\n", bot->out);
send(bot->srv_fd, outbuf, strlen(outbuf), 0); send(bot->srv_fd, outbuf, strlen(outbuf), 0);
#else #else
if (bot->use_ssl)
{
sprintf(outbuf, "%s\r\n", bot->out);
if (SSL_write(bot->ssl, outbuf, strlen(outbuf)) <= 0)
{
eprint("Error: Cannot write to SSL server\n");
}
}
else
{
fprintf(bot->srv_fd, "%s\r\n", bot->out); fprintf(bot->srv_fd, "%s\r\n", bot->out);
}
#endif #endif
} }

View File

@ -32,15 +32,19 @@ static time_t trespond;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int n; int n = 0;
fd_set rd; fd_set rd;
struct irc_conn bot; struct irc_conn bot;
struct timeval tv; struct timeval tv;
struct timeval last_ping; struct timeval last_ping;
char conf[1024]; char conf[1024];
unsigned long ssl_err;
char *p; char *p;
int bytesRecv; char buf[1024];
int bytesRecv = 0;
int totalBytesRecv = 0;
#ifdef _WIN32 #ifdef _WIN32
HICON hIcon; HICON hIcon;
@ -146,8 +150,15 @@ int main(int argc, char **argv)
#ifdef _WIN32 #ifdef _WIN32
FD_SET(bot.srv_fd, &rd); FD_SET(bot.srv_fd, &rd);
#else #else
if (bot.use_ssl)
{
FD_SET(SSL_get_fd(bot.ssl), &rd);
}
else
{
FD_SET(0, &rd); FD_SET(0, &rd);
FD_SET(fileno(bot.srv_fd), &rd); FD_SET(fileno(bot.srv_fd), &rd);
}
#endif #endif
tv.tv_sec = 1; tv.tv_sec = 1;
tv.tv_usec = 0; tv.tv_usec = 0;
@ -163,7 +174,7 @@ int main(int argc, char **argv)
return -1; return -1;
} }
#else #else
n = select(fileno(bot.srv_fd) + 1, &rd, 0, 0, &tv); n = select(bot.use_ssl ? bot.ssl_fd + 1 : fileno(bot.srv_fd) + 1, &rd, 0, 0, &tv);
if (n < 0) if (n < 0)
{ {
if (errno == EINTR) if (errno == EINTR)
@ -229,7 +240,49 @@ int main(int argc, char **argv)
free(p); free(p);
#else #else
if (FD_ISSET(fileno(bot.srv_fd), &rd)) if (FD_ISSET(bot.use_ssl ? bot.ssl_fd : fileno(bot.srv_fd), &rd))
{
if (bot.use_ssl)
{
bytesRecv = SSL_read(bot.ssl, 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';
while (1)
{
// remove \r
p = strchr(bot.in, '\r');
p = strchr(bot.in, '\n');
if (p == NULL)
break;
*p = '\0';
// remove \r at end of line
if (p[-1] == '\r')
p[-1] = '\0';
irc_parse_raw(&bot, bot.in);
memmove(bot.in, p + 1, strlen(p + 1) + 1);
}
free(p);
}
else
{ {
if (fgets(bot.in, INBUF_SIZE, bot.srv_fd) == NULL) if (fgets(bot.in, INBUF_SIZE, bot.srv_fd) == NULL)
{ {
@ -237,8 +290,10 @@ int main(int argc, char **argv)
return 0; return 0;
} }
printf("recv: %s\r\n", bot.in); printf("recv: [%s]\n", bot.in);
irc_parse_raw(&bot, bot.in); irc_parse_raw(&bot, bot.in);
}
#endif #endif
trespond = time(NULL); trespond = time(NULL);
} }

View File

@ -33,6 +33,7 @@ void eprint(char *fmt, ...)
xlog("%s", bufout); xlog("%s", bufout);
} }
#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 38)) || defined(_WIN32) #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 38)) || defined(_WIN32)
void strlcpy(char *to, const char *from, int len) void strlcpy(char *to, const char *from, int len)
{ {
@ -49,6 +50,7 @@ char *basename(char *path)
} }
#endif #endif
char *skip(char *s, char c) char *skip(char *s, char c)
{ {
while (*s != c && *s != '\0') while (*s != c && *s != '\0')

View File

@ -8,7 +8,7 @@ bot:
real = "xbot"; real = "xbot";
# owner of the bot (nick!user@host) # owner of the bot (nick!user@host)
admin = "ab3800!*@owner.ephasic.org"; admin = "ab3800!*@*";
# database file name # database file name
db = "xbot.db"; db = "xbot.db";
@ -19,8 +19,11 @@ bot:
server: server:
{ {
host = "memphis.ephasic.org"; host = "irc.newsrouters.ca";
port = "6667"; port = "6697";
ssl = true;
ssl_verify = false;
}; };
mods: mods:
@ -29,5 +32,5 @@ mods:
blacklist = (); blacklist = ();
# config option for mods/autojoin.so # config option for mods/autojoin.so
mod_autojoin = ("#lobby", "#bots"); mod_autojoin = ("#Lobby", "#Bots");
}; };