From 91e09e8e9e82b1a299de0a4319f388cc0ff7dea7 Mon Sep 17 00:00:00 2001 From: Simon Menke Date: Sun, 17 Aug 2008 22:07:02 +0200 Subject: [PATCH] Added basic user authentication to the git protocol --- connect.c | 33 ++++++++++++++++++++++++++------- daemon.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/connect.c b/connect.c index 574f42fa47..038b216521 100644 --- a/connect.c +++ b/connect.c @@ -566,20 +566,39 @@ struct child_process *git_connect(int fd[2], const char *url_orig, /* These underlying connection commands die() if they * cannot connect. */ - char *target_host = xstrdup(host); - if (git_use_proxy(host)) - git_proxy_connect(fd, host); + char *target_host_and_user = xstrdup(host); + char *target_host = strstr(target_host_and_user, "@"); + char *target_user = NULL; + char *target_passwd = NULL; + if(target_host) { + *target_host = '\0'; + target_host += 1; + target_user = target_host_and_user; + target_passwd = strstr(target_host_and_user, ":"); + if (target_passwd) { + *target_passwd = '\0'; + target_passwd += 1; + } else { + target_passwd = NULL; + } + } else { + target_host = target_host_and_user; + } + if (git_use_proxy(target_host)) + git_proxy_connect(fd, target_host); else - git_tcp_connect(fd, host, flags); + git_tcp_connect(fd, target_host, flags); /* * Separate original protocol components prog and path * from extended components with a NUL byte. */ packet_write(fd[1], - "%s %s%chost=%s%c", + "%s %s%chost=%s%cuser=%s%cpassword=%s%c", prog, path, 0, - target_host, 0); - free(target_host); + target_host, 0, + target_user, 0, + target_passwd, 0); + free(target_host_and_user); free(url); if (free_path) free(path); diff --git a/daemon.c b/daemon.c index 8dcde73200..fb04a77177 100644 --- a/daemon.c +++ b/daemon.c @@ -65,6 +65,8 @@ static unsigned int init_timeout; #define INTERP_SLOT_PORT (3) #define INTERP_SLOT_DIR (4) #define INTERP_SLOT_PERCENT (5) +#define INTERP_SLOT_USER (6) +#define INTERP_SLOT_PASSWORD (7) static struct interp interp_table[] = { { "%H", 0}, @@ -73,6 +75,8 @@ static struct interp interp_table[] = { { "%P", 0}, { "%D", 0}, { "%%", 0}, + { "%U", 0}, + { "%S", 0}, }; @@ -306,14 +310,23 @@ struct daemon_service { static struct daemon_service *service_looking_at; static int service_enabled; +static char* service_user; +static char* service_password; static int git_daemon_config(const char *var, const char *value, void *cb) { if (!prefixcmp(var, "daemon.") && - !strcmp(var + 7, service_looking_at->config_name)) { + !strcmp(var + 7, service_looking_at->config_name) && + (service_looking_at->overridable)) { service_enabled = git_config_bool(var, value); return 0; } + if (!prefixcmp(var, "user.") && + !prefixcmp(var + 5, service_user) && + !strcmp(var + 5 + strlen(service_user), ".password")) { + git_config_string(&service_password, var, value); + return 0; + } /* we are not interested in parsing any other configuration here */ return 0; @@ -354,10 +367,15 @@ static int run_service(struct interp *itable, struct daemon_service *service) return -1; } + service_user = itable[INTERP_SLOT_USER].value; + service_password = NULL; + if (service->overridable) { service_looking_at = service; service_enabled = -1; - git_config(git_daemon_config, NULL); + } + git_config(git_daemon_config, NULL); + if (service->overridable) { if (0 <= service_enabled) enabled = service_enabled; } @@ -367,6 +385,12 @@ static int run_service(struct interp *itable, struct daemon_service *service) errno = EACCES; return -1; } + if((service_password == NULL) || (strcmp(service_password, itable[INTERP_SLOT_PASSWORD].value) != 0)){ + logerror("'%s': service not enabled for '%s' as user %s", + service->name, path, service_user); + errno = EACCES; + return -1; + } /* * We'll ignore SIGTERM from now on, we have a @@ -460,6 +484,16 @@ static void parse_extra_args(struct interp *table, char *extra_args, int buflen) /* On to the next one */ extra_args = val + vallen; + } else if (strncasecmp("user=", extra_args, 5) == 0) { + val = extra_args + 5; + vallen = strlen(val) + 1; + interp_set_entry(table, INTERP_SLOT_USER, val); + extra_args = val + vallen; + } else if (strncasecmp("password=", extra_args, 9) == 0) { + val = extra_args + 9; + vallen = strlen(val) + 1; + interp_set_entry(table, INTERP_SLOT_PASSWORD, val); + extra_args = val + vallen; } } } @@ -565,13 +599,20 @@ static int execute(struct sockaddr *addr) len = strlen(line); if (pktlen != len) - loginfo("Extended attributes (%d bytes) exist <%.*s>", - (int) pktlen - len, - (int) pktlen - len, line + len + 1); + loginfo("Extended attributes (%d bytes) exist <%.*s>", + (int) pktlen - len, + (int) pktlen - len, line + len + 1); if (len && line[len-1] == '\n') { line[--len] = 0; pktlen--; } + + // int idex; + // for (idex=len;idex