commit - 64eb24873b5b63f89f43071f87f0b68d67ade4e6
commit + e240092c03160c453e59bea3aff1b6ec606b1539
blob - 14c25fdd2c16e640ef31c1abeedcb12aedee9b94
blob + 29487341845ed5d0e00ec472e2593c862e4503d1
--- gotwebd/access.c
+++ gotwebd/access.c
/*
* Copyright (c) 2025 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2015 Ted Unangst <tedu@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
#include <errno.h>
#include <event.h>
#include <imsg.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <unistd.h>
#include "got_reference.h"
#include "gotwebd.h"
#include "log.h"
+#if 0
+static int
+parseuid(const char *s, uid_t *uid)
+{
+ struct passwd *pw;
+ const char *errstr;
+
+ if ((pw = getpwnam(s)) != NULL) {
+ *uid = pw->pw_uid;
+ if (*uid == UID_MAX)
+ return -1;
+ return 0;
+ }
+ *uid = strtonum(s, 0, UID_MAX - 1, &errstr);
+ if (errstr)
+ return -1;
+ return 0;
+}
+
+static int
+uidcheck(const char *s, uid_t desired)
+{
+ uid_t uid;
+
+ if (parseuid(s, &uid) != 0)
+ return -1;
+ if (uid != desired)
+ return -1;
+ return 0;
+}
+
+static int
+parsegid(const char *s, gid_t *gid)
+{
+ struct group *gr;
+ const char *errstr;
+
+ if ((gr = getgrnam(s)) != NULL) {
+ *gid = gr->gr_gid;
+ if (*gid == GID_MAX)
+ return -1;
+ return 0;
+ }
+ *gid = strtonum(s, 0, GID_MAX - 1, &errstr);
+ if (errstr)
+ return -1;
+ return 0;
+}
+
+static int
+match_identifier(const char *identifier, gid_t *groups, int ngroups,
+ uid_t euid, gid_t egid)
+{
+ int i;
+
+ if (identifier[0] == ':') {
+ gid_t rgid;
+ if (parsegid(identifier + 1, &rgid) == -1)
+ return 0;
+ if (rgid == egid)
+ return 1;
+ for (i = 0; i < ngroups; i++) {
+ if (rgid == groups[i])
+ break;
+ }
+ if (i == ngroups)
+ return 0;
+ } else if (uidcheck(identifier, euid) != 0)
+ return 0;
+
+ return 1;
+}
+#endif
enum gotwebd_access
access_check(uid_t uid, struct gotwebd_access_rule_list *rules)
{
+#if 1
/* TODO */
return GOTWEBD_ACCESS_PERMITTED;
+#else
+ struct gotwebd_access_rule *rule;
+ enum gotwebd_access access = GOTWEBD_ACCESS_DENIED;
+ struct passwd *pw;
+ gid_t groups[NGROUPS_MAX];
+ int ngroups = NGROUPS_MAX;
+ int matched_user = 0;
+
+ pw = getpwuid(uid);
+ if (pw == NULL)
+ return GOTWEBD_ACCESS_NOTFOUND;
+
+ if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1)
+ log_warnx("group membership list truncated");
+
+ STAILQ_FOREACH(rule, rules, entry) {
+ if (!match_identifier(rule->identifier, groups, ngroups,
+ pw->pw_uid, pw->pw_gid))
+ continue;
+
+ matched_user = 1;
+ access = rule->access;
+ }
+
+ /*
+ * If a user has no explicit read or write access then
+ * do not leak the existence of a repository to them.
+ */
+ if (access == GOTWEBD_ACCESS_DENIED && !matched_user)
+ access = GOTWEBD_ACCESS_NOTFOUND;
+
+ return access;
+#endif
}
blob - ac8d4da6aca037eb97d5d8c2129641b85fb71305
blob + cc02ed610da95de3915587d1b15df67214fff46e
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
};
enum gotwebd_access {
+ GOTWEBD_ACCESS_NOTFOUND = -2,
GOTWEBD_ACCESS_DENIED = -1,
GOTWEBD_ACCESS_PERMITTED = 1
};
blob - 68741fc55a01a2ca13342f6e819878bbe5a48823
blob + 9a0ec573dc71633cac84edcd4b1cf9c6889c3fa4
--- gotwebd/login.c
+++ gotwebd/login.c
if (qs->action == INDEX) {
access = access_check(c->client_uid, &c->srv->access_rules);
switch (access) {
- case GOTWEBD_ACCESS_PERMITTED:
- break;
+ case GOTWEBD_ACCESS_NOTFOUND:
+ /* Return an empty index page. */
+ if (gotweb_reply(c, 200, "text/html", NULL) == -1)
+ return -1;
+ gotweb_render_page(c->tp, gotweb_render_repo_table_hdr);
+ return -1;
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;
+ case GOTWEBD_ACCESS_PERMITTED:
+ break;
default:
log_debug("access check error for uid %u\n",
c->client_uid);
access = access_check(c->client_uid,
&repo->access_rules);
switch (access) {
- case GOTWEBD_ACCESS_PERMITTED:
- break;
+ case GOTWEBD_ACCESS_NOTFOUND:
+ if (qs->path) {
+ error = got_error_path(qs->path,
+ GOT_ERR_NOT_GIT_REPO);
+ } else {
+ error = got_error(
+ GOT_ERR_BAD_QUERYSTRING);
+ }
+ goto err;
case GOTWEBD_ACCESS_DENIED:
if (gotweb_reply(c, 401,
"text/html", NULL) == -1)
gotweb_render_page(c->tp,
gotweb_render_unauthorized);
return -1;
+ case GOTWEBD_ACCESS_PERMITTED:
+ break;
default:
log_debug("access check error for uid %u\n",
c->client_uid);