"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
got-notify-http: implement basic auth
To:
gameoftrees@openbsd.org
Date:
Tue, 16 Apr 2024 01:25:04 +0200

Download raw body.

Thread
with this the authentication is properly implemented.  I'm unsure how to
plug it in the regress, so for the moment no tests.

diff /home/op/w/got
commit - c1003102a22a77d068a14f9ffa7877f67c28e95d
path + /home/op/w/got
blob - 9c8a90e392c27e03eb1dd32a88414aa62a355012
file + gotd/libexec/got-notify-http/got-notify-http.c
--- gotd/libexec/got-notify-http/got-notify-http.c
+++ gotd/libexec/got-notify-http/got-notify-http.c
@@ -18,6 +18,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
+#include <assert.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -730,17 +731,70 @@ jsonify(FILE *fp, const char *repo)
 	return 0;
 }
 
+static char
+sixet2ch(int c)
+{
+	c &= 0x3F;
+
+	if (c < 26)
+		return 'A' + c;
+	c -= 26;
+	if (c < 26)
+		return 'a' + c;
+	c -= 26;
+	if (c < 10)
+		return '0' + c;
+	c -= 10;
+	if (c == 0)
+		return '+';
+	if (c == 1)
+		return '/';
+
+	errx(1, "invalid sixet 0x%x", c);
+}
+
 static char *
 basic_auth(const char *username, const char *password)
 {
-	char	*tmp;
-	int	 len;
+	char	*str, *tmp, *end, *s, *p;
+	char	 buf[3];
+	int	 len, i, r;
 
-	len = asprintf(&tmp, "%s:%s", username, password);
-	if (len == -1)
+	r = asprintf(&str, "%s:%s", username, password);
+	if (r == -1)
 		err(1, "asprintf");
 
-	/* XXX base64-ify */
+	/*
+	 * Will need 4 * r/3 bytes to encode the string, plus a
+	 * rounding to the next multiple of 4 for padding, plus NUL.
+	 */
+	len = 4 * r / 3;
+	len = (len + 3) & ~3;
+	len++;
+
+	tmp = calloc(1, len);
+	if (tmp == NULL)
+		err(1, "malloc");
+
+	s = str;
+	p = tmp;
+	while (*s != '\0') {
+		memset(buf, 0, sizeof(buf));
+		for (i = 0; i < 3 && *s != '\0'; ++i, ++s)
+			buf[i] = *s;
+
+		*p++ = sixet2ch(buf[0] >> 2);
+		*p++ = sixet2ch((buf[1] >> 4) | (buf[0] << 4));
+		if (i > 1)
+			*p++ = sixet2ch((buf[1] << 2) | (buf[2] >> 6));
+		if (i > 2)
+			*p++ = sixet2ch(buf[2]);
+	}
+
+	for (end = tmp + len - 1; p < end; ++p)
+		*p = '=';
+
+	free(str);
 	return tmp;
 }
 
blob - 682368c09afd8f26371f3c0eb5b63f700ac39026
file + gotd/notify.c
--- gotd/notify.c
+++ gotd/notify.c
@@ -161,7 +161,8 @@ gotd_notify_sighdlr(int sig, short event, void *arg)
 }
 
 static void
-run_notification_helper(const char *prog, const char **argv, int fd)
+run_notification_helper(const char *prog, const char **argv, int fd,
+    const char *user, const char *pass)
 {
 	const struct got_error *err = NULL;
 	pid_t pid;
@@ -185,6 +186,11 @@ run_notification_helper(const char *prog, const char *
 
 		closefrom(STDERR_FILENO + 1);
 
+		if (user != NULL && pass != NULL) {
+			setenv("GOT_NOTIFY_HTTP_USER", user, 1);
+			setenv("GOT_NOTIFY_HTTP_PASS", pass, 1);
+		}
+
 		if (execv(prog, (char *const *)argv) == -1) {
 			fprintf(stderr, "%s: exec %s: %s\n", getprogname(),
 			    prog, strerror(errno));
@@ -249,7 +255,8 @@ notify_email(struct gotd_notification_target *target, 
 
 	argv[i] = NULL;
 
-	run_notification_helper(GOTD_PATH_PROG_NOTIFY_EMAIL, argv, fd);
+	run_notification_helper(GOTD_PATH_PROG_NOTIFY_EMAIL, argv, fd,
+	    NULL, NULL);
 }
 
 static void
@@ -273,7 +280,8 @@ notify_http(struct gotd_notification_target *target, c
 
 	argv[argc] = NULL;
 
-	run_notification_helper(GOTD_PATH_PROG_NOTIFY_HTTP, argv, fd);
+	run_notification_helper(GOTD_PATH_PROG_NOTIFY_HTTP, argv, fd,
+	    target->conf.http.user, target->conf.http.password);
 }
 
 static const struct got_error *