commit be23710aafb9ce026a25272cb07826fd10361e87 from: Stefan Sperling via: Thomas Adam date: Mon May 06 21:33:52 2024 UTC don't leak the existence of gotd repositories to unrelated user accounts In particular, this prevents anonymous user accounts from discovering the existence of other private repositories served by gotd by correctly guessing the name of a private repository. They still wouldn't have read or write access but in some cases even knowledge about the existence of a particular repository could be cause for concern. ok op@ commit - caee5476c9a132618334bc76e9e8dd53191dba1c commit + be23710aafb9ce026a25272cb07826fd10361e87 blob - 180adda224025de845b52f7ce1692d2a8b85be51 blob + d9e38491b237bfe21ddc56c9b1f852e33ccf0f95 --- gotd/auth.c +++ gotd/auth.c @@ -136,6 +136,7 @@ auth_check(char **username, struct gotd_access_rule_li struct passwd *pw; gid_t groups[NGROUPS_MAX]; int ngroups = NGROUPS_MAX; + int matched_user = 0; *username = NULL; @@ -159,14 +160,23 @@ auth_check(char **username, struct gotd_access_rule_li euid, egid)) continue; + matched_user = 1; access = rule->access; if (rule->access == GOTD_ACCESS_PERMITTED && (rule->authorization & required_auth) != required_auth) access = GOTD_ACCESS_DENIED; } - if (access == GOTD_ACCESS_DENIED) - return got_error_set_errno(EACCES, repo_name); + if (access == GOTD_ACCESS_DENIED) { + /* + * If a user has no explicit read or write access then + * do not leak the existence of a repository to them. + */ + if (!matched_user) + return got_error(GOT_ERR_NOT_GIT_REPO); + else + return got_error_set_errno(EACCES, repo_name); + } if (access == GOTD_ACCESS_PERMITTED) return NULL; blob - cb2a4fed7b7467995301b65285bcdb7dbaac38ad blob + d210ed777ad16244f17aecd012723366f8862c8c --- regress/gotd/Makefile +++ regress/gotd/Makefile @@ -55,6 +55,7 @@ GOTD_TEST_ENV=GOTD_TEST_ROOT=$(GOTD_TEST_ROOT) \ GOTD_SOCK=$(GOTD_SOCK) \ GOTD_DEVUSER=$(GOTD_DEVUSER) \ GOTD_USER=$(GOTD_USER) \ + GOTD_CONF=$(PWD)/gotd.conf \ GOTD_TEST_SMTP_PORT=$(GOTD_TEST_SMTP_PORT) \ GOTD_TEST_HTTP_PORT=$(GOTD_TEST_HTTP_PORT) \ HOME=$(GOTD_TEST_USER_HOME) \ blob - f1eaa263ded2de0987d31ec852c1c021a68df9cc blob + 734479f1d4bb418a9468c905aed529752d696062 --- regress/gotd/repo_read_access_denied.sh +++ regress/gotd/repo_read_access_denied.sh @@ -33,8 +33,15 @@ test_clone_basic_access_denied() { grep ^got-fetch-pack: $testroot/stderr.raw > $testroot/stderr # Verify that the clone operation failed. - echo 'got-fetch-pack: test-repo: Permission denied' \ - > $testroot/stderr.expected + # The error returned will differ depending on whether read access + # is denied explicitly for GOTD_DEVUSER. + if grep -q "permit.*${GOTD_DEVUSER}$" $GOTD_CONF; then + echo 'got-fetch-pack: test-repo: Permission denied' \ + > $testroot/stderr.expected + else + echo 'got-fetch-pack: no git repository found' \ + > $testroot/stderr.expected + fi cmp -s $testroot/stderr.expected $testroot/stderr ret=$? if [ $ret -ne 0 ]; then blob - 9bfba2cfd281497c7e9b811178f4b534d191cc7e blob + c8b3337da837dcd5501b30cd8f9fc57f52366777 --- regress/gotd/repo_write_readonly.sh +++ regress/gotd/repo_write_readonly.sh @@ -58,8 +58,16 @@ EOF return 1 fi - echo "got-send-pack: test-repo: Permission denied" \ - > $testroot/stderr.expected + # Verify that the send operation failed. + # The error returned will differ depending on whether read access + # is denied explicitly for GOTD_DEVUSER. + if grep -q "permit.*${GOTD_DEVUSER}$" $GOTD_CONF; then + echo "got-send-pack: test-repo: Permission denied" \ + > $testroot/stderr.expected + else + echo 'got-send-pack: no git repository found' \ + > $testroot/stderr.expected + fi grep '^got-send-pack:' $testroot/stderr > $testroot/stderr.filtered cmp -s $testroot/stderr.expected $testroot/stderr.filtered ret=$?