Download raw body.
make gitwrapper ignore "realpath: permission denied"
I came across this misbehaviour of gitwrapper while setting up
a private repository to be served by gotd.
ok?
-----------------------------------------------
make gitwrapper ignore 'permission denied' for repository paths
We recommend that gotsh users should not have direct filesystem
access to repositories served by gotd. Which means admins will be
setting things up as follows if public read-access should be denied:
chown _gotd /git
chmod 700 /git
su -m _gotd -c 'gotadmin init /git/repo.git"
However, gitwrapper would error out when repositories listed in
gotd.conf were inaccessible to the user invoking gitwrapper:
git-upload-pack: /etc/gotd.conf:2: realpath /git/repo.git: Permission denied
Make gitwrapper ignore such errors as they are expected in this situation.
While here, add a PROC_GITWRAPPER process ID for use as a global variable
parse.y can check while special-casing any specific behaviour required by
gitwrapper. (The worse alternative would have been adding a new global
variable to parse.y just to control the behaviour on realpath errors.)
diff bafea5babab6072bfa7528ad7c767bde76a446a3 c097e1a4fa86a111f516a37aff5394f8c6695d24
commit - bafea5babab6072bfa7528ad7c767bde76a446a3
commit + c097e1a4fa86a111f516a37aff5394f8c6695d24
blob - 1ed8d3dc9b6ae29d105bff2710d33de54cf0bc13
blob + 28645f07dc93480582fce4b5f7dea5813b028a23
--- gitwrapper/gitwrapper.c
+++ gitwrapper/gitwrapper.c
@@ -131,7 +131,7 @@ main(int argc, char *argv[])
confpath = getenv("GOTD_CONF_PATH");
if (confpath == NULL)
confpath = GOTD_CONF_PATH;
- parse_config(confpath, PROC_GOTD, &gotd, 0);
+ parse_config(confpath, PROC_GITWRAPPER, &gotd);
error = apply_unveil(myserver);
if (error)
blob - 68a99a122229289490584888ded7f2beb2d99042
blob + 4432aec44c71cf0db3723fa870ba885b23ddd037
--- gotd/gotd.c
+++ gotd/gotd.c
@@ -729,7 +729,8 @@ static const char *gotd_proc_names[PROC_MAX] = {
"session_read",
"session_write",
"repo_read",
- "repo_write"
+ "repo_write",
+ "gitwrapper"
};
static void
@@ -1858,7 +1859,7 @@ main(int argc, char **argv)
if (geteuid() && (proc_id == PROC_GOTD || proc_id == PROC_LISTEN))
fatalx("need root privileges");
- if (parse_config(confpath, proc_id, &gotd, 1) != 0)
+ if (parse_config(confpath, proc_id, &gotd) != 0)
return 1;
pw = getpwnam(gotd.user_name);
blob - e902d6f53b03f7682202e2b9b3d0af5fc28c25b6
blob + acb40dee8cd351b48669c3c3247c42ed5f44501b
--- gotd/gotd.h
+++ gotd/gotd.h
@@ -40,6 +40,7 @@ enum gotd_procid {
PROC_SESSION_WRITE,
PROC_REPO_READ,
PROC_REPO_WRITE,
+ PROC_GITWRAPPER,
PROC_MAX,
};
@@ -442,7 +443,7 @@ int parse_config(const char *, enum gotd_procid, struc
uint32_t client_id;
};
-int parse_config(const char *, enum gotd_procid, struct gotd *, int);
+int parse_config(const char *, enum gotd_procid, struct gotd *);
struct gotd_repo *gotd_find_repo_by_name(const char *, struct gotd *);
struct gotd_repo *gotd_find_repo_by_path(const char *, struct gotd *);
struct gotd_uid_connection_limit *gotd_find_uid_connection_limit(
blob - a3860760379f26a53fcf3788e84f9efb36efbdd3
blob + 6f3e0a082e72aca4ecc41d9b9980d9b1b7325746
--- gotd/parse.y
+++ gotd/parse.y
@@ -293,7 +293,8 @@ repository : REPOSITORY STRING {
if (gotd_proc_id == PROC_GOTD ||
gotd_proc_id == PROC_AUTH ||
- gotd_proc_id == PROC_REPO_WRITE) {
+ gotd_proc_id == PROC_REPO_WRITE ||
+ gotd_proc_id == PROC_GITWRAPPER) {
new_repo = conf_new_repo($2);
}
free($2);
@@ -304,7 +305,8 @@ repoopts1 : PATH STRING {
repoopts1 : PATH STRING {
if (gotd_proc_id == PROC_GOTD ||
gotd_proc_id == PROC_AUTH ||
- gotd_proc_id == PROC_REPO_WRITE) {
+ gotd_proc_id == PROC_REPO_WRITE ||
+ gotd_proc_id == PROC_GITWRAPPER) {
if (!got_path_is_absolute($2)) {
yyerror("%s: path %s is not absolute",
__func__, $2);
@@ -312,16 +314,28 @@ repoopts1 : PATH STRING {
YYERROR;
}
if (realpath($2, new_repo->path) == NULL) {
- yyerror("realpath %s: %s", $2,
- strerror(errno));
/*
- * Give admin a chance to create
- * missing repositories at run-time.
+ * To give admins a chance to create
+ * missing repositories at run-time
+ * we only warn about ENOENT here.
+ *
+ * And ignore 'permission denied' when
+ * running in gitwrapper. Users may be
+ * able to access this repository via
+ * gotd regardless.
*/
- if (errno != ENOENT) {
+ if (errno == ENOENT) {
+ yyerror("realpath %s: %s", $2,
+ strerror(errno));
+ } else if (errno != EACCES ||
+ gotd_proc_id != PROC_GITWRAPPER) {
+ yyerror("realpath %s: %s", $2,
+ strerror(errno));
free($2);
YYERROR;
- } else if (strlcpy(new_repo->path, $2,
+ }
+
+ if (strlcpy(new_repo->path, $2,
sizeof(new_repo->path)) >=
sizeof(new_repo->path))
yyerror("path too long");
@@ -740,10 +754,11 @@ parse_config(const char *filename, enum gotd_procid pr
int
parse_config(const char *filename, enum gotd_procid proc_id,
- struct gotd *env, int require_config_file)
+ struct gotd *env)
{
struct sym *sym, *next;
struct gotd_repo *repo;
+ int require_config_file = (proc_id == PROC_GITWRAPPER ? 0 : 1);
memset(env, 0, sizeof(*env));
make gitwrapper ignore "realpath: permission denied"