added SSL support for linux
This commit is contained in:
parent
0661b29519
commit
e0041ac970
2
Makefile
2
Makefile
@ -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
|
||||||
|
17
lib/irc.h
17
lib/irc.h
@ -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;
|
||||||
|
17
lib/util.h
17
lib/util.h
@ -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
|
||||||
|
@ -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;
|
||||||
|
125
src/irc.c
125
src/irc.c
@ -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
|
||||||
fflush(bot->srv_fd);
|
if (!bot->use_ssl)
|
||||||
SETBUF(bot->srv_fd, NULL);
|
{
|
||||||
|
fflush(bot->srv_fd);
|
||||||
|
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
|
||||||
fprintf(bot->srv_fd, "%s\r\n", bot->out);
|
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);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
77
src/main.c
77
src/main.c
@ -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
|
||||||
FD_SET(0, &rd);
|
if (bot.use_ssl)
|
||||||
FD_SET(fileno(bot.srv_fd), &rd);
|
{
|
||||||
|
FD_SET(SSL_get_fd(bot.ssl), &rd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FD_SET(0, &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,16 +240,60 @@ 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 (fgets(bot.in, INBUF_SIZE, bot.srv_fd) == NULL)
|
if (bot.use_ssl)
|
||||||
{
|
{
|
||||||
eprint("xbot: remote host closed connection\n");
|
bytesRecv = SSL_read(bot.ssl, bot.in, INBUF_SIZE);
|
||||||
return 0;
|
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)
|
||||||
|
{
|
||||||
|
eprint("xbot: remote host closed connection\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("recv: [%s]\n", bot.in);
|
||||||
|
irc_parse_raw(&bot, bot.in);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("recv: %s\r\n", bot.in);
|
|
||||||
irc_parse_raw(&bot, bot.in);
|
|
||||||
#endif
|
#endif
|
||||||
trespond = time(NULL);
|
trespond = time(NULL);
|
||||||
}
|
}
|
||||||
|
@ -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')
|
||||||
|
11
xbot.cfg
11
xbot.cfg
@ -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");
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user