Signed-off-by: Franck Bui-Huu <vagabon.xyz@xxxxxxxxx> --- daemon.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 60 insertions(+), 17 deletions(-) diff --git a/daemon.c b/daemon.c index 66ec830..f5f6927 100644 --- a/daemon.c +++ b/daemon.c @@ -232,16 +232,57 @@ static char *path_ok(char *dir) return NULL; /* Fallthrough. Deny by default */ } -static int upload(char *dir) +/* + * Services we're able to deal with. + */ +static int service_upload_pack(const char *dir, const char *args) { /* Timeout as string */ char timeout_buf[64]; + + snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout); + + /* git-upload-pack only ever reads stuff, so this is safe */ + execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL); + return -1; +} + +/* service options */ +#define NEED_REPO (1<<0) + +struct service_info { + const char *name; + int (*fn)(const char *dir, const char *args); + int options; +}; + +static struct service_info services[] = { + { "git-upload-pack", service_upload_pack, NEED_REPO }, +}; + +static int run_service(char *cmdline) +{ + struct service_info *serv; const char *path; + size_t len; + int i; - loginfo("Request for '%s'", dir); + for (i = 0; i < ARRAY_SIZE(services); i++) { + serv = &services[i]; - if (!(path = path_ok(dir))) - return -1; + len = strlen(serv->name); + if (strncmp(cmdline, serv->name, len)) + continue; + if (cmdline[len] != ' ') + continue; + goto found; + } + return -1; +found: + cmdline += len + 1; + path = NULL; + + loginfo("Request '%s' for '%s'", serv->name, cmdline); /* * Security on the cheap. @@ -253,11 +294,16 @@ static int upload(char *dir) * path_ok() uses enter_repo() and does whitelist checking. * We only need to make sure the repository is exported. */ + if (serv->options & NEED_REPO) { + if (!(path = path_ok(cmdline))) + return -1; - if (!export_all_trees && access("git-daemon-export-ok", F_OK)) { - logerror("'%s': repository not exported.", path); - errno = EACCES; - return -1; + if (!export_all_trees && access("git-daemon-export-ok", F_OK)) { + logerror("'%s': repository not exported.", path); + errno = EACCES; + return -1; + } + cmdline += strlen(path) + 1; } /* @@ -266,17 +312,14 @@ static int upload(char *dir) */ signal(SIGTERM, SIG_IGN); - snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout); - - /* git-upload-pack only ever reads stuff, so this is safe */ - execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL); - return -1; + return serv->fn(path, cmdline); } static int execute(struct sockaddr *addr) { static char line[1000]; int pktlen, len; + int rv; if (addr) { char addrbuf[256] = ""; @@ -313,11 +356,11 @@ #endif if (len && line[len-1] == '\n') line[--len] = 0; - if (!strncmp("git-upload-pack ", line, 16)) - return upload(line+16); + rv = run_service(line); + if (rv < 0) + logerror("Protocol error: '%s'", line); - logerror("Protocol error: '%s'", line); - return -1; + return rv; } -- 1.4.2 - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html