@matheusbsbs / matheus-bagliano / commits / 5abb013b3d
Fork 0

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>

Shawn O. Pearce committed Nov 4, 2009 at 17:16 UTC 5abb013b3ddfb42e5baa3c7de052af596a0ee82f
2 files changed +36 -6
Documentation/git-http-backend.txt
+8
@@ -29,6 +29,14 @@ SERVICES
29 These services can be enabled/disabled using the per-repository
30 configuration file:
31
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 +
40 http.uploadpack::
41 This serves 'git-fetch-pack' and 'git-ls-remote' clients.
42 It is enabled by default, but a repository can disable it
http-backend.c
+28 -6
@@ -10,6 +10,7 @@
10 static const char content_type[] = "Content-Type";
11 static const char content_length[] = "Content-Length";
12 static const char last_modified[] = "Last-Modified";
13 +static int getanyfile = 1;
14
15 static struct string_list *query_params;
16
@@ -194,6 +195,12 @@ static NORETURN void forbidden(const char *err, ...)
195 exit(0);
196 }
197
198 +static void select_getanyfile(void)
199 +{
200 + if (!getanyfile)
201 + forbidden("Unsupported service: getanyfile");
202 +}
203 +
204 static void send_strbuf(const char *type, struct strbuf *buf)
205 {
206 hdr_int(content_length, buf->len);
@@ -238,38 +245,51 @@ static void send_file(const char *the_type, const char *name)
245
246 static void get_text_file(char *name)
247 {
248 + select_getanyfile();
249 hdr_nocache();
250 send_file("text/plain", name);
251 }
252
253 static void get_loose_object(char *name)
254 {
255 + select_getanyfile();
256 hdr_cache_forever();
257 send_file("application/x-git-loose-object", name);
258 }
259
260 static void get_pack_file(char *name)
261 {
262 + select_getanyfile();
263 hdr_cache_forever();
264 send_file("application/x-git-packed-objects", name);
265 }
266
267 static void get_idx_file(char *name)
268 {
269 + select_getanyfile();
270 hdr_cache_forever();
271 send_file("application/x-git-packed-objects-toc", name);
272 }
273
274 static int http_config(const char *var, const char *value, void *cb)
275 {
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);
278 return 0;
279 }
280
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 +
293 /* we are not interested in parsing any other configuration here */
294 return 0;
295 }
@@ -293,7 +313,6 @@ static struct rpc_service *select_service(const char *name)
313 if (!svc)
314 forbidden("Unsupported service: '%s'", name);
315
296 - git_config(http_config, svc);
316 if (svc->enabled < 0) {
317 const char *user = getenv("REMOTE_USER");
318 svc->enabled = (user && *user) ? 1 : 0;
@@ -442,6 +461,7 @@ static void get_info_refs(char *arg)
461 run_service(argv);
462
463 } else {
464 + select_getanyfile();
465 for_each_ref(show_text_ref, &buf);
466 send_strbuf("text/plain", &buf);
467 }
@@ -455,6 +475,7 @@ static void get_info_packs(char *arg)
475 struct packed_git *p;
476 size_t cnt = 0;
477
478 + select_getanyfile();
479 prepare_packed_git();
480 for (p = packed_git; p; p = p->next) {
481 if (p->pack_local)
@@ -621,6 +642,7 @@ int main(int argc, char **argv)
642 if (!enter_repo(dir, 0))
643 not_found("Not a git repository: '%s'", dir);
644
645 + git_config(http_config, NULL);
646 cmd->imp(cmd_arg);
647 return 0;
648 }