Skip to content

Commit 5abb013

Browse files
spearcegitster
authored andcommitted
http-backend: Use http.getanyfile to disable dumb HTTP serving
Some repository owners may wish to enable smart HTTP, but disallow dumb content serving. Disallowing dumb serving might be because the owners want to rely upon reachability to control which objects clients may access from the repository, or they just want to encourage clients to use the more bandwidth efficient transport. If http.getanyfile is set to false the backend CGI will return with '403 Forbidden' when an object file is accessed by a dumb client. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 7da4e22 commit 5abb013

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed

Documentation/git-http-backend.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ SERVICES
2929
These services can be enabled/disabled using the per-repository
3030
configuration file:
3131

32+
http.getanyfile::
33+
This serves older Git clients which are unable to use the
34+
upload pack service. When enabled, clients are able to read
35+
any file within the repository, including objects that are
36+
no longer reachable from a branch but are still present.
37+
It is enabled by default, but a repository can disable it
38+
by setting this configuration item to `false`.
39+
3240
http.uploadpack::
3341
This serves 'git-fetch-pack' and 'git-ls-remote' clients.
3442
It is enabled by default, but a repository can disable it

http-backend.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
static const char content_type[] = "Content-Type";
1111
static const char content_length[] = "Content-Length";
1212
static const char last_modified[] = "Last-Modified";
13+
static int getanyfile = 1;
1314

1415
static struct string_list *query_params;
1516

@@ -194,6 +195,12 @@ static NORETURN void forbidden(const char *err, ...)
194195
exit(0);
195196
}
196197

198+
static void select_getanyfile(void)
199+
{
200+
if (!getanyfile)
201+
forbidden("Unsupported service: getanyfile");
202+
}
203+
197204
static void send_strbuf(const char *type, struct strbuf *buf)
198205
{
199206
hdr_int(content_length, buf->len);
@@ -238,38 +245,51 @@ static void send_file(const char *the_type, const char *name)
238245

239246
static void get_text_file(char *name)
240247
{
248+
select_getanyfile();
241249
hdr_nocache();
242250
send_file("text/plain", name);
243251
}
244252

245253
static void get_loose_object(char *name)
246254
{
255+
select_getanyfile();
247256
hdr_cache_forever();
248257
send_file("application/x-git-loose-object", name);
249258
}
250259

251260
static void get_pack_file(char *name)
252261
{
262+
select_getanyfile();
253263
hdr_cache_forever();
254264
send_file("application/x-git-packed-objects", name);
255265
}
256266

257267
static void get_idx_file(char *name)
258268
{
269+
select_getanyfile();
259270
hdr_cache_forever();
260271
send_file("application/x-git-packed-objects-toc", name);
261272
}
262273

263274
static int http_config(const char *var, const char *value, void *cb)
264275
{
265-
struct rpc_service *svc = cb;
266-
267-
if (!prefixcmp(var, "http.") &&
268-
!strcmp(var + 5, svc->config_name)) {
269-
svc->enabled = git_config_bool(var, value);
276+
if (!strcmp(var, "http.getanyfile")) {
277+
getanyfile = git_config_bool(var, value);
270278
return 0;
271279
}
272280

281+
if (!prefixcmp(var, "http.")) {
282+
int i;
283+
284+
for (i = 0; i < ARRAY_SIZE(rpc_service); i++) {
285+
struct rpc_service *svc = &rpc_service[i];
286+
if (!strcmp(var + 5, svc->config_name)) {
287+
svc->enabled = git_config_bool(var, value);
288+
return 0;
289+
}
290+
}
291+
}
292+
273293
/* we are not interested in parsing any other configuration here */
274294
return 0;
275295
}
@@ -293,7 +313,6 @@ static struct rpc_service *select_service(const char *name)
293313
if (!svc)
294314
forbidden("Unsupported service: '%s'", name);
295315

296-
git_config(http_config, svc);
297316
if (svc->enabled < 0) {
298317
const char *user = getenv("REMOTE_USER");
299318
svc->enabled = (user && *user) ? 1 : 0;
@@ -442,6 +461,7 @@ static void get_info_refs(char *arg)
442461
run_service(argv);
443462

444463
} else {
464+
select_getanyfile();
445465
for_each_ref(show_text_ref, &buf);
446466
send_strbuf("text/plain", &buf);
447467
}
@@ -455,6 +475,7 @@ static void get_info_packs(char *arg)
455475
struct packed_git *p;
456476
size_t cnt = 0;
457477

478+
select_getanyfile();
458479
prepare_packed_git();
459480
for (p = packed_git; p; p = p->next) {
460481
if (p->pack_local)
@@ -621,6 +642,7 @@ int main(int argc, char **argv)
621642
if (!enter_repo(dir, 0))
622643
not_found("Not a git repository: '%s'", dir);
623644

645+
git_config(http_config, NULL);
624646
cmd->imp(cmd_arg);
625647
return 0;
626648
}

0 commit comments

Comments
 (0)