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"