When the git-daemon is asked about an inaccessible repository, it simply
hangs up the connection without saying anything further. This makes it
hard to distinguish between a repository we cannot access (e.g., due to
typo), and a service or network outage.
Instead, let's print an "ERR" line, which git clients understand since
v1.6.1 (2008-12-24).
Because there is a risk of leaking information about non-exported
repositories, by default all errors simply say "access denied or
repository not exported". Sites which don't have hidden repositories, or
don't care, can pass a flag to turn on more specific messages.
Signed-off-by: Jeff King <peff@peff.net>
Helped-by: Sitaram Chamarty <sitaramc@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
repository configuration. By default, all the services
are overridable.
repository configuration. By default, all the services
are overridable.
+--informative-errors::
+--no-informative-errors::
+ When informative errors are turned on, git-daemon will report
+ more verbose errors to the client, differentiating conditions
+ like "no such repository" from "repository not exported". This
+ is more convenient for clients, but may leak information about
+ the existence of unexported repositories. When informative
+ errors are not enabled, all errors report "access denied" to the
+ client. The default is --no-informative-errors.
+
<directory>::
A directory to add to the whitelist of allowed directories. Unless
--strict-paths is specified this will also include subdirectories
<directory>::
A directory to add to the whitelist of allowed directories. Unless
--strict-paths is specified this will also include subdirectories
static int log_syslog;
static int verbose;
static int reuseaddr;
static int log_syslog;
static int verbose;
static int reuseaddr;
+static int informative_errors;
static const char daemon_usage[] =
"git daemon [--verbose] [--syslog] [--export-all]\n"
static const char daemon_usage[] =
"git daemon [--verbose] [--syslog] [--export-all]\n"
+static int daemon_error(const char *dir, const char *msg)
+{
+ if (!informative_errors)
+ msg = "access denied or repository not exported";
+ packet_write(1, "ERR %s: %s", msg, dir);
+ return -1;
+}
+
static int run_service(char *dir, struct daemon_service *service)
{
const char *path;
static int run_service(char *dir, struct daemon_service *service)
{
const char *path;
if (!enabled && !service->overridable) {
logerror("'%s': service not enabled.", service->name);
errno = EACCES;
if (!enabled && !service->overridable) {
logerror("'%s': service not enabled.", service->name);
errno = EACCES;
+ return daemon_error(dir, "service not enabled");
}
if (!(path = path_ok(dir)))
}
if (!(path = path_ok(dir)))
+ return daemon_error(dir, "no such repository");
/*
* Security on the cheap.
/*
* Security on the cheap.
if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
logerror("'%s': repository not exported.", path);
errno = EACCES;
if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
logerror("'%s': repository not exported.", path);
errno = EACCES;
+ return daemon_error(dir, "repository not exported");
}
if (service->overridable) {
}
if (service->overridable) {
logerror("'%s': service not enabled for '%s'",
service->name, path);
errno = EACCES;
logerror("'%s': service not enabled for '%s'",
service->name, path);
errno = EACCES;
+ return daemon_error(dir, "service not enabled");
make_service_overridable(arg + 18, 0);
continue;
}
make_service_overridable(arg + 18, 0);
continue;
}
+ if (!prefixcmp(arg, "--informative-errors")) {
+ informative_errors = 1;
+ continue;
+ }
+ if (!prefixcmp(arg, "--no-informative-errors")) {
+ informative_errors = 0;
+ continue;
+ }
if (!strcmp(arg, "--")) {
ok_paths = &argv[i+1];
break;
if (!strcmp(arg, "--")) {
ok_paths = &argv[i+1];
break;