Commit Diff


commit - f64cf10ded89231621f05a9b05aabd596a63334a
commit + 64eb24873b5b63f89f43071f87f0b68d67ade4e6
blob - b1cce23ab2d6c57ab08fca454362fe66b498584a
blob + f65c7285ed12b1a7d26ab953399839b996373ff0
--- gotwebd/Makefile
+++ gotwebd/Makefile
@@ -5,7 +5,7 @@
 .include "Makefile.inc"
 
 PROG =		gotwebd
-SRCS =		auth.c config.c sockets.c login.c gotwebd.c parse.y \
+SRCS =		access.c auth.c config.c sockets.c login.c gotwebd.c parse.y \
 		fcgi.c gotweb.c got_operations.c tmpl.c pages.c
 SRCS +=		blame.c commit_graph.c delta.c diff.c \
 		diffreg.c error.c object.c object_cache.c \
blob - /dev/null
blob + 14c25fdd2c16e640ef31c1abeedcb12aedee9b94 (mode 644)
--- /dev/null
+++ gotwebd/access.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2025 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/queue.h>
+
+#include <errno.h>
+#include <event.h>
+#include <imsg.h>
+
+#include "got_reference.h"
+
+#include "gotwebd.h"
+#include "log.h"
+
+enum gotwebd_access
+access_check(uid_t uid, struct gotwebd_access_rule_list *rules)
+{
+	/* TODO */
+	return GOTWEBD_ACCESS_PERMITTED;
+}
blob - 7fa1ab0f5de4526e17c35977ee3c1a068f457846
blob + 6f4d5068996fb62cd514e840c9e6fc1a5570d3ec
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -563,6 +563,28 @@ gotweb_get_server(const char *server_name)
 
 	/* otherwise, use the first server */
 	return TAILQ_FIRST(&gotwebd_env->servers);
+};
+
+struct gotwebd_repo *
+gotweb_get_repository(struct server *server, const char *name)
+{
+	struct gotwebd_repo *repo;
+
+	TAILQ_FOREACH(repo, &server->repos, entry) {
+		if (strncmp(repo->name, name, strlen(repo->name)) != 0)
+			continue;
+	
+		if (strlen(name) == strlen(repo->name))
+			return repo;
+
+		if (strlen(name) != strlen(repo->name) + 4)
+			continue;
+
+		if (strcmp(name + strlen(repo->name), ".git") == 0)
+			return repo;
+	}
+
+	return NULL;
 };
 
 const struct got_error *
blob - 81ed267b63329b626454173f2072d58cb1364aa0
blob + ac8d4da6aca037eb97d5d8c2129641b85fb71305
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -540,6 +540,7 @@ void gotwebd_login(struct gotwebd *, int);
 const struct got_error *gotweb_init_querystring(struct querystring **);
 const struct got_error *gotweb_parse_querystring(struct querystring *, char *);
 struct server *gotweb_get_server(const char *);
+struct gotwebd_repo * gotweb_get_repository(struct server *, const char *);
 int gotweb_reply(struct request *c, int status, const char *ctype,
     struct gotweb_url *);
 void gotweb_index_navs(struct request *, struct gotweb_url *, int *,
@@ -626,3 +627,6 @@ char *auth_gen_token(uint64_t, const char *, time_t, c
 int auth_check_token(uid_t *, char **, const char *, const char *, size_t);
 void gotwebd_auth(struct gotwebd *, int);
 int auth_privinit(struct gotwebd *env, uid_t, gid_t);
+
+/* access.c */
+enum gotwebd_access access_check(uid_t, struct gotwebd_access_rule_list *);
blob - 6bdcc9df4d1bed48fa079aab23a472e9fc2f15a7
blob + 68741fc55a01a2ca13342f6e819878bbe5a48823
--- gotwebd/login.c
+++ gotwebd/login.c
@@ -290,6 +290,8 @@ process_request(struct request *c, struct imsg *imsg)
 	struct querystring *qs = NULL;
 	int ret;
 	char *hostname = NULL;
+	struct gotwebd_repo *repo;
+	enum gotwebd_access access;
 
 	switch (env->auth_config) {
 	case GOTWEBD_AUTH_SECURE:
@@ -330,6 +332,50 @@ process_request(struct request *c, struct imsg *imsg)
 
 	log_debug("authenticated uid %u for server \"%s\"",
 	    c->client_uid, hostname);
+
+	if (qs->action == INDEX) {
+		access = access_check(c->client_uid, &c->srv->access_rules);
+		switch (access) {
+		case GOTWEBD_ACCESS_PERMITTED:
+			break;
+		case GOTWEBD_ACCESS_DENIED:
+			if (gotweb_reply(c, 401, "text/html", NULL) == -1)
+				return -1;
+			gotweb_render_page(c->tp, gotweb_render_unauthorized);
+			return -1;
+		default:
+			log_debug("access check error for uid %u\n",
+			    c->client_uid);
+			return -1;
+		}
+	} else {
+		if (qs->path == NULL) {
+			error = got_error(GOT_ERR_BAD_QUERYSTRING);
+			goto err;
+		}
+
+		repo = gotweb_get_repository(c->srv, qs->path);
+		if (repo) {
+			access = access_check(c->client_uid,
+			    &repo->access_rules);
+			switch (access) {
+			case GOTWEBD_ACCESS_PERMITTED:
+				break;
+			case GOTWEBD_ACCESS_DENIED:
+				if (gotweb_reply(c, 401,
+				    "text/html", NULL) == -1)
+					return -1;
+				gotweb_render_page(c->tp,
+				    gotweb_render_unauthorized);
+				return -1;
+			default:
+				log_debug("access check error for uid %u\n",
+				    c->client_uid);
+				return -1;
+			}
+		}
+	}
+
 forward:
 	ret = imsg_compose_event(env->iev_gotweb, GOTWEBD_IMSG_REQ_PROCESS,
 	    GOTWEBD_PROC_LOGIN, -1, c->fd, c, sizeof(*c));