about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-10-22 22:49:05 -0400
committerJune McEnroe <june@causal.agency>2019-10-22 22:49:05 -0400
commit72cee2b26449468734de68c797d0cc6945f176f9 (patch)
treee89834666eef7a5615cfc8857c3592d2aa37bfec
parentMention server-time in manual page (diff)
downloadpounce-72cee2b26449468734de68c797d0cc6945f176f9.tar.gz
pounce-72cee2b26449468734de68c797d0cc6945f176f9.zip
Implement serverLogin
-rw-r--r--bounce.c10
-rw-r--r--bounce.h5
-rw-r--r--listen.c3
-rw-r--r--server.c79
4 files changed, 94 insertions, 3 deletions
diff --git a/bounce.c b/bounce.c
index b3d8b33..43d3ef8 100644
--- a/bounce.c
+++ b/bounce.c
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/socket.h>
 #include <sysexits.h>
 #include <tls.h>
 #include <unistd.h>
@@ -91,6 +92,15 @@ int main(int argc, char *argv[]) {
 	int bind[BindCap];
 	size_t bindLen = listenBind(bind, BindCap, localHost, localPort);
 
+	int server = serverConnect(host, port);
+	serverLogin(pass, auth, nick, user, real);
+
+	// TODO: Wait for successful login before listening.
+	for (size_t i = 0; i < bindLen; ++i) {
+		int error = listen(bind[i], 1);
+		if (error) err(EX_IOERR, "listen");
+	}
+
 	// Wishing for struct-of-arrays...
 	struct pollfd fds[BindCap];
 	for (size_t i = 0; i < bindLen; ++i) {
diff --git a/bounce.h b/bounce.h
index e731ac0..999180f 100644
--- a/bounce.h
+++ b/bounce.h
@@ -30,3 +30,8 @@ size_t listenBind(int fds[], size_t cap, const char *host, const char *port);
 int listenAccept(struct tls **client, int fd);
 
 int serverConnect(const char *host, const char *port);
+void serverLogin(
+	const char *pass, const char *auth,
+	const char *nick, const char *user, const char *real
+);
+void serverSend(const char *ptr, size_t len);
diff --git a/listen.c b/listen.c
index d758b9d..1179a8b 100644
--- a/listen.c
+++ b/listen.c
@@ -69,9 +69,6 @@ size_t listenBind(int fds[], size_t cap, const char *host, const char *port) {
 			continue;
 		}
 
-		error = listen(fds[len], 1);
-		if (error) err(EX_IOERR, "listen");
-
 		len++;
 	}
 	freeaddrinfo(head);
diff --git a/server.c b/server.c
index b86d769..4c22287 100644
--- a/server.c
+++ b/server.c
@@ -17,7 +17,10 @@
 #include <err.h>
 #include <netdb.h>
 #include <netinet/in.h>
+#include <stdarg.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sysexits.h>
 #include <tls.h>
@@ -25,6 +28,8 @@
 
 #include "bounce.h"
 
+typedef unsigned char byte;
+
 static struct tls *client;
 
 int serverConnect(const char *host, const char *port) {
@@ -69,3 +74,77 @@ int serverConnect(const char *host, const char *port) {
 
 	return sock;
 }
+
+void serverSend(const char *ptr, size_t len) {
+	while (len) {
+		ssize_t ret = tls_write(client, ptr, len);
+		if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue;
+		if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client));
+		ptr += ret;
+		len -= ret;
+	}
+}
+
+static void format(const char *format, ...) {
+	char *buf;
+	va_list ap;
+	va_start(ap, format);
+	int len = vasprintf(&buf, format, ap);
+	va_end(ap);
+	if (!buf) err(EX_OSERR, "vasprintf");
+	serverSend(format, len);
+	free(buf);
+}
+
+static const char Base64[64] = {
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+};
+
+static char *base64(const byte *src, size_t len) {
+	char *dst = malloc(1 + (len + 2) / 3 * 4);
+	if (!dst) err(EX_OSERR, "malloc");
+
+	size_t i = 0;
+	while (len > 2) {
+		dst[i++] = Base64[0x3F & (src[0] >> 2)];
+		dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
+		dst[i++] = Base64[0x3F & (src[1] << 2 | src[2] >> 6)];
+		dst[i++] = Base64[0x3F & src[2]];
+		src += 3;
+		len -= 3;
+	}
+
+	if (len) {
+		dst[i++] = Base64[0x3F & (src[0] >> 2)];
+		if (len > 1) {
+			dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)];
+			dst[i++] = Base64[0x3F & (src[1] << 2)];
+		} else {
+			dst[i++] = Base64[0x3F & (src[0] << 4)];
+			dst[i++] = '=';
+		}
+		dst[i++] = '=';
+	}
+
+	dst[i] = '\0';
+	return dst;
+}
+
+static char *authBase64;
+
+void serverLogin(
+	const char *pass, const char *auth,
+	const char *nick, const char *user, const char *real
+) {
+	if (pass) format("PASS :%s\r\n", pass);
+	if (auth) {
+		byte plain[1 + strlen(auth)];
+		plain[0] = 0;
+		for (size_t i = 0; auth[i]; ++i) {
+			plain[1 + i] = (auth[i] == ':' ? 0 : auth[i]);
+		}
+		authBase64 = base64(plain, sizeof(plain));
+		format("CAP REQ :sasl\r\n");
+	}
+	format("NICK %s\r\nUSER %s 0 * :%s\r\n", nick, user, real);
+}