summary refs log tree commit diff
path: root/client.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-01-12 18:07:54 -0500
committerJune McEnroe <june@causal.agency>2020-01-12 18:07:54 -0500
commit5e6094e437a5437ceb6b083d16995ea629a4d720 (patch)
tree34ad1b244212caab1b832a6243988e388282434a /client.c
parentAdd a vendor capability for passive clients (diff)
downloadpounce-5e6094e437a5437ceb6b083d16995ea629a4d720.tar.gz
pounce-5e6094e437a5437ceb6b083d16995ea629a4d720.zip
Add option to set local client CA
This is a little bit messy. Allows setting either -A or -W or both.
Implements SASL EXTERNAL for clients that expect that when connecting
with a client certificate.

Need to test that reloading still works inside capsicum, since I suspect
that rewind call may be blocked.
Diffstat (limited to 'client.c')
-rw-r--r--client.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/client.c b/client.c
index a598ec0..fe5eceb 100644
--- a/client.c
+++ b/client.c
@@ -30,6 +30,7 @@
 
 #include "bounce.h"
 
+bool clientCA;
 char *clientPass;
 char *clientAway;
 
@@ -57,6 +58,9 @@ struct Client *clientAlloc(struct tls *tls) {
 	if (!client) err(EX_OSERR, "calloc");
 	client->tls = tls;
 	client->need = NeedNick | NeedUser | (clientPass ? NeedPass : 0);
+	if (clientCA && tls_peer_cert_provided(tls)) {
+		client->need &= ~NeedPass;
+	}
 	return client;
 }
 
@@ -160,7 +164,9 @@ static void handlePass(struct Client *client, struct Message *msg) {
 
 static void handleCap(struct Client *client, struct Message *msg) {
 	if (!msg->params[0]) msg->params[0] = "";
+
 	enum Cap avail = CapServerTime | CapPassive | (stateCaps & ~CapSASL);
+	if (clientCA) avail |= CapSASL;
 
 	if (!strcmp(msg->params[0], "END")) {
 		if (!client->need) return;
@@ -192,6 +198,27 @@ static void handleCap(struct Client *client, struct Message *msg) {
 	}
 }
 
+static void handleAuthenticate(struct Client *client, struct Message *msg) {
+	if (!msg->params[0]) msg->params[0] = "";
+	if (!strcmp(msg->params[0], "EXTERNAL")) {
+		clientFormat(client, "AUTHENTICATE +\r\n");
+	} else if (!strcmp(msg->params[0], "+")) {
+		clientFormat(
+			client, ":%s 900 * %s * :You are now logged in as *\r\n",
+			ORIGIN, stateEcho()
+		);
+		clientFormat(
+			client, ":%s 903 * :SASL authentication successful\r\n",
+			ORIGIN
+		);
+	} else {
+		clientFormat(
+			client, ":%s 904 * :SASL authentication failed\r\n",
+			ORIGIN
+		);
+	}
+}
+
 static void handleQuit(struct Client *client, struct Message *msg) {
 	(void)msg;
 	clientFormat(client, "ERROR :Detaching\r\n");
@@ -218,6 +245,7 @@ static const struct {
 	Handler *fn;
 	bool need;
 } Handlers[] = {
+	{ "AUTHENTICATE", handleAuthenticate, false },
 	{ "CAP", handleCap, false },
 	{ "NICK", handleNick, false },
 	{ "NOTICE", handlePrivmsg, true },