BarryServer : Git

All the code for all my projects
// BarryServer : Git / IRCWebHooks / commit / 3f04e2245ef9565e8e9853cac3f2114fbfdd566d / src / irc.c

// Related

IRCWebHooks

Barry Adding files 3f04e22 (3 years, 3 months ago)
diff --git a/src/irc.c b/src/irc.c
new file mode 100644
index 0000000..5ab201b
--- /dev/null
+++ b/src/irc.c
@@ -0,0 +1,240 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+#include "config.h"
+#include "list.h"
+#include "irc.h"
+
+SSL_CTX *ctx;
+SSL *ssl;
+int conn;
+char sbuf[512];
+struct Node *head = NULL;
+struct Node *current = NULL;
+
+/* Auth a user */
+int
+auth(char *ident, char *vhost)
+{
+	char *pt;
+	char *identlist = strdup(ADMIN_IDENT);
+	char *vhostlist = strdup(ADMIN_VHOST);
+
+	pt = strtok(identlist,",");
+	while (pt != NULL) {
+		if (!strncmp(ident, pt, strlen(pt))) return 1;
+		pt = strtok(NULL, ",");
+	}
+
+	pt = strtok(vhostlist,",");
+	while (pt != NULL) {
+		if (!strncmp(vhost, pt, strlen(pt))) return 1;
+		pt = strtok(NULL, ",");
+	}
+
+	return 0;
+}
+
+/* Send data to server */
+void
+raw(char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vsnprintf(sbuf, 512, fmt, ap);
+	va_end(ap);
+#ifdef VERBOSE
+	printf("<< %s", sbuf);
+#endif
+	SSL_write(ssl, sbuf, strlen(sbuf));
+}
+
+/* Bot code */
+void
+bot(void)
+{
+	BIO *certbio = NULL, *outbio = NULL;
+	X509 *cert = NULL;
+	X509_NAME *certname = NULL;
+	const SSL_METHOD *method;
+
+	char *user, *ident, *vhost, *command, *where, *message, *sep, *target;
+	int i, j, l, sl, o = -1, start, wordcount;
+	char buf[513];
+	struct addrinfo hints, *res;
+
+	/* Connect to IRC */
+	printf("Connecting to IRC...\n");
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_INET;
+	hints.ai_socktype = SOCK_STREAM;
+	getaddrinfo(HOST, PORT, &hints, &res);
+	conn = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+	connect(conn, res->ai_addr, res->ai_addrlen);
+
+	/* SSL connection */
+	{
+		OpenSSL_add_all_algorithms();
+		ERR_load_BIO_strings();
+		ERR_load_crypto_strings();
+		SSL_load_error_strings();
+		certbio = BIO_new(BIO_s_file());
+		outbio = BIO_new_fp(stdout, BIO_NOCLOSE);
+		if (SSL_library_init() < 0) {
+			BIO_printf(outbio, "Could not initialise the OpenSSL library!\n");
+			exit(1);
+		}
+		method = SSLv23_client_method();
+		if ((ctx = SSL_CTX_new(method)) == NULL) {
+			BIO_printf(outbio, "Unable to create a new SSL context!\n");
+			exit(1);
+		}
+		SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
+		ssl = SSL_new(ctx);
+		SSL_set_fd(ssl, conn);
+		if (SSL_connect(ssl) != 1) {
+			BIO_printf(outbio, "Error: Could not SSL connect!\n");
+			exit(1);
+		}
+		cert = SSL_get_peer_certificate(ssl);
+		if (cert == NULL) {
+			BIO_printf(outbio, "Error: Could not get certificate!\n");
+			exit(1);
+		}
+		certname = X509_NAME_new();
+		certname = X509_get_subject_name(cert);
+	}
+
+	/* IRC user */
+	raw("USER %s 0 0 :%s\r\n", NICK, NICK);
+	raw("NICK %s\r\n", NICK);
+	printf("Joined IRC!\n");
+
+	/* Add initial channel to list */
+	char *chanlist = strdup(CHAN);
+	char *pt;
+	pt = strtok(chanlist,",");
+	while (pt != NULL) {
+		insert_first(pt);
+		pt = strtok(NULL, ",");
+	}
+
+	/* IRC messages */
+	while (sl = SSL_read(ssl, sbuf, 512))
+		for (i = 0; i < sl; i++) {
+			o++;
+			buf[o] = sbuf[i];
+			if ((i > 0 && sbuf[i] == '\n' && sbuf[i-1] == '\r') || o == 512) {
+				buf[o + 1] = '\0';
+				l = o;
+				o = -1;
+
+#ifdef VERBOSE
+				printf(">> %s", buf);
+#endif
+
+				/* Deal with PINGs */
+				if (!strncmp(buf, "PING", 4)) {
+					buf[1] = 'O';
+					raw(buf);
+				/* Messages */
+				} else if (buf[0] == ':') {
+					wordcount = 0;
+					user = command = where = message = NULL;
+					/* Separate words */
+					for (j = 1; j < l; j++) {
+						if (buf[j] == ' ') {
+							buf[j] = '\0';
+							wordcount++;
+							switch (wordcount) {
+							case 1:
+								user = buf + 1;
+								break;
+							case 2:
+								command = buf + start;
+								break;
+							case 3:
+								where = buf + start;
+								break;
+							}
+							if (j == l - 1)
+								continue;
+							start = j + 1;
+						} else if (buf[j] == ':' && wordcount == 3) {
+							if (j < l - 1)
+								message = buf + j + 1;
+							break;
+						}
+					}
+
+					if (wordcount < 2)
+
+					/* Join a channel */
+					sleep(1);
+					if (!strncmp(command, "001", 3)) {
+#ifdef PASS
+						raw("PRIVMSG NickServ :IDENTIFY %s\r\n", PASS);
+						sleep(1);
+						raw("PRIVMSG HostServ :ON\r\n", PASS);
+						sleep(1);
+#endif
+						raw("JOIN %s\r\n", CHAN);
+						printf("Identified for nick, and joined channel!\n");
+					/* Incoming messages */
+					} else if (!strncmp(command, "PRIVMSG", 7)
+					|| !strncmp(command, "NOTICE", 6)) {
+						if (where == NULL || message == NULL)
+							continue;
+						if ((sep = strchr(user, '!')) != NULL) {
+							user[sep - user] = '\0';
+							ident = sep + 1;
+							if ((sep = strchr(ident, '@')) != NULL) {
+								ident[sep - ident] = '\0';
+								vhost = sep + 1;
+							}
+						}
+						if (where[0] == '#' || where[0] == '&' || where[0] == '+' || where[0] == '!')
+							target = where;
+						else
+							target = user;
+
+						if (target == user && !strncmp(message, "JOIN ", 5) && auth(ident, vhost)) {
+							raw("%s\r\n", message);
+							char *p = message+5;
+							while (*p++) if (*p == '\n' || *p == '\r' || *p == ' ') *p = '\0';
+							insert_first(message+5);
+						} else
+						if (target == user && !strncmp(message, "LEAVE ", 6) && auth(ident, vhost)) {
+							raw("PART %s\r\n", message+6);
+							char *p = message+5;
+							while (*p++) if (*p == '\n' || *p == '\r' || *p == ' ') *p = '\0';
+							delete(message+6);
+						}
+
+#ifdef VERBOSE
+						printf(
+							"[from: %s] [reply-with: %s] [where: %s] [reply-to: %s] %s",
+							user, command, where, target, message
+						);
+#endif
+					}
+				}
+			}
+		}
+
+	SSL_free(ssl);
+	close(conn);
+	X509_free(cert);
+	SSL_CTX_free(ctx);
+}