Merge branches 'jc/daemon' and 'mw/http'

* jc/daemon:
  daemon: extend user-relative path notation.
  daemon: Set SO_REUSEADDR on listening sockets.
  daemon: do not forbid user relative paths unconditionally under --base-path

* mw/http:
  http-fetch: Tidy control flow in process_alternate_response
  http: Turn on verbose Curl messages if GIT_CURL_VERBOSE set in environment
  http-fetch: Fix message reporting rename of object file.
  http-fetch: Fix object list corruption in fill_active_slots().
This commit is contained in:
Junio C Hamano 2006-02-05 23:54:14 -08:00
commit a8c44537fe
4 changed files with 90 additions and 17 deletions

View File

@ -10,7 +10,8 @@ SYNOPSIS
[verse]
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
[--timeout=n] [--init-timeout=n] [--strict-paths]
[--base-path=path] [directory...]
[--base-path=path] [--user-path | --user-path=path]
[directory...]
DESCRIPTION
-----------
@ -42,8 +43,7 @@ OPTIONS
This is sort of "GIT root" - if you run git-daemon with
'--base-path=/srv/git' on example.com, then if you later try to pull
'git://example.com/hello.git', `git-daemon` will interpret the path
as '/srv/git/hello.git'. Home directories (the '~login' notation)
access is disabled.
as '/srv/git/hello.git'.
--export-all::
Allow pulling from all directories that look like GIT repositories
@ -70,6 +70,15 @@ OPTIONS
Log to syslog instead of stderr. Note that this option does not imply
--verbose, thus by default only error conditions will be logged.
--user-path, --user-path=path::
Allow ~user notation to be used in requests. When
specified with no parameter, requests to
git://host/~alice/foo is taken as a request to access
'foo' repository in the home directory of user `alice`.
If `--user-path=path` is specified, the same request is
taken as a request to access `path/foo` repository in
the home directory of user `alice`.
--verbose::
Log details about the incoming connections and requested files.

View File

@ -13,11 +13,13 @@
static int log_syslog;
static int verbose;
static int reuseaddr;
static const char daemon_usage[] =
"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
" [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
" [--base-path=path] [directory...]";
" [--base-path=path] [--user-path | --user-path=path]\n"
" [--reuseaddr] [directory...]";
/* List of acceptable pathname prefixes */
static char **ok_paths = NULL;
@ -29,6 +31,12 @@ static int export_all_trees = 0;
/* Take all paths relative to this one if non-NULL */
static char *base_path = NULL;
/* If defined, ~user notation is allowed and the string is inserted
* after ~user/. E.g. a request to git://host/~alice/frotz would
* go to /home/alice/pub_git/frotz with --user-path=pub_git.
*/
static char *user_path = NULL;
/* Timeout, and initial timeout */
static unsigned int timeout = 0;
static unsigned int init_timeout = 0;
@ -136,6 +144,7 @@ static int avoid_alias(char *p)
static char *path_ok(char *dir)
{
static char rpath[PATH_MAX];
char *path;
if (avoid_alias(dir)) {
@ -143,15 +152,38 @@ static char *path_ok(char *dir)
return NULL;
}
if (base_path) {
static char rpath[PATH_MAX];
if (*dir == '~') {
if (!user_path) {
logerror("'%s': User-path not allowed", dir);
return NULL;
}
if (*user_path) {
/* Got either "~alice" or "~alice/foo";
* rewrite them to "~alice/%s" or
* "~alice/%s/foo".
*/
int namlen, restlen = strlen(dir);
char *slash = strchr(dir, '/');
if (!slash)
slash = dir + restlen;
namlen = slash - dir;
restlen -= namlen;
loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
namlen, dir, user_path, restlen, slash);
dir = rpath;
}
}
else if (base_path) {
if (*dir != '/') {
/* Forbid possible base-path evasion using ~paths. */
/* Allow only absolute */
logerror("'%s': Non-absolute path denied (base-path active)", dir);
return NULL;
}
snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
dir = rpath;
else {
snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
dir = rpath;
}
}
path = enter_repo(dir, strict_paths);
@ -447,6 +479,16 @@ static void child_handler(int signo)
}
}
static int set_reuse_addr(int sockfd)
{
int on = 1;
if (!reuseaddr)
return 0;
return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
&on, sizeof(on));
}
#ifndef NO_IPV6
static int socksetup(int port, int **socklist_p)
@ -491,6 +533,11 @@ static int socksetup(int port, int **socklist_p)
}
#endif
if (set_reuse_addr(sockfd)) {
close(sockfd);
return 0; /* not fatal */
}
if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
close(sockfd);
continue; /* not fatal */
@ -533,6 +580,11 @@ static int socksetup(int port, int **socklist_p)
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
if (set_reuse_addr(sockfd)) {
close(sockfd);
return 0;
}
if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
close(sockfd);
return 0;
@ -659,6 +711,18 @@ int main(int argc, char **argv)
base_path = arg+12;
continue;
}
if (!strcmp(arg, "--reuseaddr")) {
reuseaddr = 1;
continue;
}
if (!strcmp(arg, "--user-path")) {
user_path = "";
continue;
}
if (!strncmp(arg, "--user-path=", 12)) {
user_path = arg + 12;
continue;
}
if (!strcmp(arg, "--")) {
ok_paths = &argv[i+1];
break;

View File

@ -311,7 +311,7 @@ void fill_active_slots(void)
while (active_requests < max_requests && obj_req != NULL) {
if (obj_req->state == WAITING) {
if (has_sha1_file(obj_req->sha1))
release_object_request(obj_req);
obj_req->state = COMPLETE;
else
start_object_request(obj_req);
curl_multi_perform(curlm, &num_transfers);
@ -468,13 +468,11 @@ static void process_alternates_response(void *callback_data)
alt_req->url);
active_requests++;
slot->in_use = 1;
if (start_active_slot(slot)) {
return;
} else {
if (!start_active_slot(slot)) {
got_alternates = -1;
slot->in_use = 0;
return;
}
return;
}
} else if (slot->curl_result != CURLE_OK) {
if (slot->http_code != 404 &&
@ -822,9 +820,8 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
} else if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) {
ret = error("File %s has bad hash\n", hex);
} else if (obj_req->rename < 0) {
ret = error("unable to write sha1 filename %s: %s",
obj_req->filename,
strerror(obj_req->rename));
ret = error("unable to write sha1 filename %s",
obj_req->filename);
}
release_object_request(obj_req);

3
http.c
View File

@ -192,6 +192,9 @@ static CURL* get_curl_handle(void)
curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
if (getenv("GIT_CURL_VERBOSE"))
curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
return result;
}