IRCWebHooks
Barry Adding files 3f04e22 (3 years, 3 months ago)#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); }