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

From:
Stefan Sperling <stsp@stsp.name>
Subject:
fix gotwebd login when URL location != "/"
To:
gameoftrees@openbsd.org
Date:
Tue, 2 Dec 2025 10:10:12 +0100

Download raw body.

Thread
Add the gotwebd root URL to login links. Otherwise gotwebd will not receive
login requests if the webserver is not running gotwebd at URL location "/".

E.g. a config like this just won't work otherwise:

httpd.conf:

server "example.com" {
	location "/gotweb" {
		fastcgi socket "/run/gotweb.sock"
	}
	location "/gotweb/*" {
		fastcgi socket "/run/gotweb.sock"
	}
}

gotwebd.conf:

server "example.com" {
	repos_path "/git"
	gotweb_url_root "/gotweb"
	repos_url_path "/"  # example.com/gotweb/
	enable authentication
	permit anonymous
}

gotsh would still return login URLs such as https://example.com/?login=token
which result in "404 not found" from httpd.


ok?

Double-slashes are not a concern this time around since srv->gotweb_url_root
is normalized to "/some/path" while parsing the configuration file (leading
slash will be present, trailing slash won't be).


M  gotwebd/login.c  |  15+  7-

1 file changed, 15 insertions(+), 7 deletions(-)

commit - 222a9d10ecceca6ca66c57d1a0dc84d13f5a2047
commit + 290598312f95a3869921f733a9b67cbe9a0bebf0
blob - 05a894bc5a6b1fdebdf747acaf7d215b24352cbd
blob + b951cb0492a42bb97681b5a7909f7ffb83f76726
--- gotwebd/login.c
+++ gotwebd/login.c
@@ -478,7 +478,7 @@ client_read(struct bufferevent *bev, void *d)
 	struct evbuffer *out = EVBUFFER_OUTPUT(bev);
 	char *line, *cmd, *code;
 	size_t linelen;
-	const char *hostname;
+	const char *hostname, *path = NULL;
 
 	if (client->cmd_done) {
 		log_warnx("%s: client sent data even though login command "
@@ -501,12 +501,12 @@ client_read(struct bufferevent *bev, void *d)
 
 	cmd = line;
 	if (strncmp(cmd, "login", 5) == 0) {
+		struct server *srv = NULL;
+
 		cmd += 5;
 		cmd += strspn(cmd, " \t");
 		hostname = cmd;
 		if (hostname[0] == '\0') {
-			struct server *srv;
-
 			/*
 			 * In a multi-server setup we do not want to leak our
 			 * first server's hostname to random people. But if
@@ -515,9 +515,13 @@ client_read(struct bufferevent *bev, void *d)
 			srv = TAILQ_FIRST(&gotwebd_env->servers);
 			if (TAILQ_NEXT(srv, entry) == NULL)
 				hostname = srv->name;
+			else {
+				log_warnx("%s: no hostname provided for "
+				    "weblogin", __func__);
+				client_err(bev, EVBUFFER_READ, client);
+				return;
+			}
 		} else {
-			struct server *srv;
-
 			/* Match hostname against available servers. */
 			TAILQ_FOREACH(srv, &gotwebd_env->servers, entry) {
 				if (strcmp(srv->name, hostname) == 0)
@@ -541,8 +545,12 @@ client_read(struct bufferevent *bev, void *d)
 			return;
 		}
 
-		if (evbuffer_add_printf(out, "ok https://%s/?login=%s\n",
-		    hostname, code) == -1) {
+		if (srv->gotweb_url_root[0] != '\0' &&
+		    !got_path_is_root_dir(srv->gotweb_url_root))
+			path = srv->gotweb_url_root;
+
+		if (evbuffer_add_printf(out, "ok https://%s%s/?login=%s\n",
+		    hostname, path ? path : "", code) == -1) {
 			log_warnx("%s: evbuffer_add_printf failed", __func__);
 			client_err(bev, EVBUFFER_READ, client);
 			free(code);