Merge early part of branch 'jc/daemon'
commit
1efca00ad8
117
daemon.c
117
daemon.c
|
@ -232,13 +232,42 @@ static char *path_ok(char *dir)
|
||||||
return NULL; /* Fallthrough. Deny by default */
|
return NULL; /* Fallthrough. Deny by default */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int upload(char *dir)
|
typedef int (*daemon_service_fn)(void);
|
||||||
{
|
struct daemon_service {
|
||||||
/* Timeout as string */
|
const char *name;
|
||||||
char timeout_buf[64];
|
const char *config_name;
|
||||||
const char *path;
|
daemon_service_fn fn;
|
||||||
|
int enabled;
|
||||||
|
int overridable;
|
||||||
|
};
|
||||||
|
|
||||||
loginfo("Request for '%s'", dir);
|
static struct daemon_service *service_looking_at;
|
||||||
|
static int service_enabled;
|
||||||
|
|
||||||
|
static int git_daemon_config(const char *var, const char *value)
|
||||||
|
{
|
||||||
|
if (!strncmp(var, "daemon.", 7) &&
|
||||||
|
!strcmp(var + 7, service_looking_at->config_name)) {
|
||||||
|
service_enabled = git_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we are not interested in parsing any other configuration here */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_service(char *dir, struct daemon_service *service)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
int enabled = service->enabled;
|
||||||
|
|
||||||
|
loginfo("Request %s for '%s'", service->name, dir);
|
||||||
|
|
||||||
|
if (!enabled && !service->overridable) {
|
||||||
|
logerror("'%s': service not enabled.", service->name);
|
||||||
|
errno = EACCES;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(path = path_ok(dir)))
|
if (!(path = path_ok(dir)))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -260,12 +289,34 @@ static int upload(char *dir)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (service->overridable) {
|
||||||
|
service_looking_at = service;
|
||||||
|
service_enabled = -1;
|
||||||
|
git_config(git_daemon_config);
|
||||||
|
if (0 <= service_enabled)
|
||||||
|
enabled = service_enabled;
|
||||||
|
}
|
||||||
|
if (!enabled) {
|
||||||
|
logerror("'%s': service not enabled for '%s'",
|
||||||
|
service->name, path);
|
||||||
|
errno = EACCES;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We'll ignore SIGTERM from now on, we have a
|
* We'll ignore SIGTERM from now on, we have a
|
||||||
* good client.
|
* good client.
|
||||||
*/
|
*/
|
||||||
signal(SIGTERM, SIG_IGN);
|
signal(SIGTERM, SIG_IGN);
|
||||||
|
|
||||||
|
return service->fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int upload_pack(void)
|
||||||
|
{
|
||||||
|
/* Timeout as string */
|
||||||
|
char timeout_buf[64];
|
||||||
|
|
||||||
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
|
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
|
||||||
|
|
||||||
/* git-upload-pack only ever reads stuff, so this is safe */
|
/* git-upload-pack only ever reads stuff, so this is safe */
|
||||||
|
@ -273,10 +324,36 @@ static int upload(char *dir)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct daemon_service daemon_service[] = {
|
||||||
|
{ "upload-pack", "uploadpack", upload_pack, 1, 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void enable_service(const char *name, int ena) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
|
||||||
|
if (!strcmp(daemon_service[i].name, name)) {
|
||||||
|
daemon_service[i].enabled = ena;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die("No such service %s", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_service_overridable(const char *name, int ena) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
|
||||||
|
if (!strcmp(daemon_service[i].name, name)) {
|
||||||
|
daemon_service[i].overridable = ena;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die("No such service %s", name);
|
||||||
|
}
|
||||||
|
|
||||||
static int execute(struct sockaddr *addr)
|
static int execute(struct sockaddr *addr)
|
||||||
{
|
{
|
||||||
static char line[1000];
|
static char line[1000];
|
||||||
int pktlen, len;
|
int pktlen, len, i;
|
||||||
|
|
||||||
if (addr) {
|
if (addr) {
|
||||||
char addrbuf[256] = "";
|
char addrbuf[256] = "";
|
||||||
|
@ -313,8 +390,14 @@ static int execute(struct sockaddr *addr)
|
||||||
if (len && line[len-1] == '\n')
|
if (len && line[len-1] == '\n')
|
||||||
line[--len] = 0;
|
line[--len] = 0;
|
||||||
|
|
||||||
if (!strncmp("git-upload-pack ", line, 16))
|
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
|
||||||
return upload(line+16);
|
struct daemon_service *s = &(daemon_service[i]);
|
||||||
|
int namelen = strlen(s->name);
|
||||||
|
if (!strncmp("git-", line, 4) &&
|
||||||
|
!strncmp(s->name, line + 4, namelen) &&
|
||||||
|
line[namelen + 4] == ' ')
|
||||||
|
return run_service(line + namelen + 5, s);
|
||||||
|
}
|
||||||
|
|
||||||
logerror("Protocol error: '%s'", line);
|
logerror("Protocol error: '%s'", line);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -805,6 +888,22 @@ int main(int argc, char **argv)
|
||||||
group_name = arg + 8;
|
group_name = arg + 8;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strncmp(arg, "--enable=", 9)) {
|
||||||
|
enable_service(arg + 9, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(arg, "--disable=", 10)) {
|
||||||
|
enable_service(arg + 10, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(arg, "--enable-override=", 18)) {
|
||||||
|
make_service_overridable(arg + 18, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strncmp(arg, "--disable-override=", 19)) {
|
||||||
|
make_service_overridable(arg + 19, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--")) {
|
if (!strcmp(arg, "--")) {
|
||||||
ok_paths = &argv[i+1];
|
ok_paths = &argv[i+1];
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue