added SSL support for linux
This commit is contained in:
parent
0661b29519
commit
e0041ac970
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
||||
CC=gcc
|
||||
CFLAGS=-g -std=gnu99 -c -lconfig -ldl -I./lib
|
||||
BINFLAGS=-g -rdynamic -ldl -lconfig
|
||||
BINFLAGS=-g -rdynamic -ldl -lconfig -lssl -lcrypto
|
||||
SRC=./src
|
||||
OBJ=./build
|
||||
OBJECTS=$(OBJ)/*.o
|
||||
|
17
lib/irc.h
17
lib/irc.h
@ -18,10 +18,12 @@
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
#define OUTBUF_SIZE 60000
|
||||
#define INBUF_SIZE 60000
|
||||
#define OUTBUF_SIZE 1200000
|
||||
#define INBUF_SIZE 1200000
|
||||
|
||||
struct irc_conn
|
||||
{
|
||||
@ -29,6 +31,9 @@ struct irc_conn
|
||||
SOCKET srv_fd;
|
||||
#else
|
||||
FILE *srv_fd;
|
||||
int ssl_fd;
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx;
|
||||
#endif
|
||||
|
||||
char nick[50];
|
||||
@ -38,6 +43,14 @@ struct irc_conn
|
||||
char port[5];
|
||||
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 log_file[256];
|
||||
struct db_table *db;
|
||||
|
17
lib/util.h
17
lib/util.h
@ -9,6 +9,16 @@
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#ifdef DEBUG
|
||||
#define BREAKPOINT() asm("int $3")
|
||||
#else
|
||||
#define BREAKPOINT()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define true TRUE
|
||||
#define false FALSE
|
||||
@ -34,7 +44,14 @@ MY_API void strlcpy(char *to, const char *from, int len);
|
||||
MY_API char *basename(char *path);
|
||||
#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);
|
||||
|
||||
// trim - remove leading and trailing whitespace from a string
|
||||
MY_API void trim(char *s);
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@ struct irc_conn read_config(struct irc_conn bot, char *file)
|
||||
const config_setting_t *autoload;
|
||||
const char *base = (const char*)malloc(sizeof(char) * 1024);
|
||||
const char *mod = NULL;
|
||||
int boolbase;
|
||||
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))
|
||||
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);
|
||||
|
||||
return bot;
|
||||
|
119
src/irc.c
119
src/irc.c
@ -21,6 +21,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <schannel.h>
|
||||
#define FDOPEN _fdopen
|
||||
#define SETBUF setbuf
|
||||
#else
|
||||
@ -29,6 +30,9 @@
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#define FDOPEN fdopen
|
||||
#define SETBUF setbuf
|
||||
#endif
|
||||
@ -41,6 +45,43 @@ void irc_connect(struct irc_conn *bot)
|
||||
struct sockaddr_in server;
|
||||
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);
|
||||
SetConsoleTitle(titlebuf);
|
||||
|
||||
@ -89,6 +130,26 @@ void irc_connect(struct irc_conn *bot)
|
||||
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);
|
||||
SetConsoleTitle(titlebuf);
|
||||
#else
|
||||
@ -96,6 +157,32 @@ void irc_connect(struct irc_conn *bot)
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
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);
|
||||
}
|
||||
|
||||
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+");
|
||||
xlog("[IRC] Connected!\n");
|
||||
#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);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (!bot->use_ssl)
|
||||
{
|
||||
fflush(bot->srv_fd);
|
||||
SETBUF(bot->srv_fd, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -182,7 +288,18 @@ void irc_raw(struct irc_conn *bot, char *fmt, ...)
|
||||
sprintf(outbuf, "%s\r\n", bot->out);
|
||||
send(bot->srv_fd, outbuf, strlen(outbuf), 0);
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
65
src/main.c
65
src/main.c
@ -32,15 +32,19 @@ static time_t trespond;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
int n = 0;
|
||||
fd_set rd;
|
||||
struct irc_conn bot;
|
||||
struct timeval tv;
|
||||
struct timeval last_ping;
|
||||
char conf[1024];
|
||||
unsigned long ssl_err;
|
||||
|
||||
char *p;
|
||||
int bytesRecv;
|
||||
char buf[1024];
|
||||
int bytesRecv = 0;
|
||||
int totalBytesRecv = 0;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
HICON hIcon;
|
||||
@ -146,8 +150,15 @@ int main(int argc, char **argv)
|
||||
#ifdef _WIN32
|
||||
FD_SET(bot.srv_fd, &rd);
|
||||
#else
|
||||
if (bot.use_ssl)
|
||||
{
|
||||
FD_SET(SSL_get_fd(bot.ssl), &rd);
|
||||
}
|
||||
else
|
||||
{
|
||||
FD_SET(0, &rd);
|
||||
FD_SET(fileno(bot.srv_fd), &rd);
|
||||
}
|
||||
#endif
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
@ -163,7 +174,7 @@ int main(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
#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 (errno == EINTR)
|
||||
@ -229,7 +240,49 @@ int main(int argc, char **argv)
|
||||
|
||||
free(p);
|
||||
#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)
|
||||
{
|
||||
@ -237,8 +290,10 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("recv: %s\r\n", bot.in);
|
||||
printf("recv: [%s]\n", bot.in);
|
||||
irc_parse_raw(&bot, bot.in);
|
||||
}
|
||||
|
||||
#endif
|
||||
trespond = time(NULL);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ void eprint(char *fmt, ...)
|
||||
xlog("%s", bufout);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 38)) || defined(_WIN32)
|
||||
void strlcpy(char *to, const char *from, int len)
|
||||
{
|
||||
@ -49,6 +50,7 @@ char *basename(char *path)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
char *skip(char *s, char c)
|
||||
{
|
||||
while (*s != c && *s != '\0')
|
||||
|
11
xbot.cfg
11
xbot.cfg
@ -8,7 +8,7 @@ bot:
|
||||
real = "xbot";
|
||||
|
||||
# owner of the bot (nick!user@host)
|
||||
admin = "ab3800!*@owner.ephasic.org";
|
||||
admin = "ab3800!*@*";
|
||||
|
||||
# database file name
|
||||
db = "xbot.db";
|
||||
@ -19,8 +19,11 @@ bot:
|
||||
|
||||
server:
|
||||
{
|
||||
host = "memphis.ephasic.org";
|
||||
port = "6667";
|
||||
host = "irc.newsrouters.ca";
|
||||
port = "6697";
|
||||
|
||||
ssl = true;
|
||||
ssl_verify = false;
|
||||
};
|
||||
|
||||
mods:
|
||||
@ -29,5 +32,5 @@ mods:
|
||||
blacklist = ();
|
||||
|
||||
# config option for mods/autojoin.so
|
||||
mod_autojoin = ("#lobby", "#bots");
|
||||
mod_autojoin = ("#Lobby", "#Bots");
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user