From 40cf3d17d331612074b75262ed724cf22103eed9 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 7 Nov 2013 18:51:34 +0000 Subject: [PATCH 1/1] git-cache-proxy: copy starting point from userv-utils git-daemon.in, git-service.in userv-utils has a git proxy, of which we are going to reuse some parts. Copy them from userv-utils.git#f90cb5738a194fc1b873ffc6212f3aa9a537e2fe --- scripts/git-daemon.in | 87 ++++++++++++++++++++++++++++++++++++++++++ scripts/git-service.in | 51 +++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100755 scripts/git-daemon.in create mode 100755 scripts/git-service.in diff --git a/scripts/git-daemon.in b/scripts/git-daemon.in new file mode 100755 index 0000000..1b1b540 --- /dev/null +++ b/scripts/git-daemon.in @@ -0,0 +1,87 @@ +#!/usr/bin/perl +# +# A git daemon with an added userv security boundary. +# +# This was written by Tony Finch and subsequently +# heavily modified by Ian Jackson +# http://creativecommons.org/publicdomain/zero/1.0/ + +use strict; +use warnings; + +use POSIX; +use Socket; +use Sys::Syslog; + +BEGIN { + if ($ARGV[0] =~ s/^-L//) { + my $logfile= shift @ARGV; + open STDERR, ">> $logfile" or die $!; + } +} + +sub ntoa { + my $sockaddr = shift; + return ('(local)') unless defined $sockaddr; + my ($port,$addr) = sockaddr_in $sockaddr; + $addr = inet_ntoa $addr; + return ("[$addr]:$port",$addr,$port); +} +our ($client,$client_addr,$client_port) = ntoa getpeername STDIN; +our ($server,$server_addr,$server_port) = ntoa getsockname STDIN; +our ($service,$specpath,$spechost); + +printf STDERR "%s [$$] %s %s\n", + strftime("%Y-%m-%d %H:%M:%S %Z", localtime), $server, $client; + +openlog 'userv-git-daemon', 'pid', 'daemon'; +sub fail { syslog 'err', "$client @_"; exit } + +$SIG{ALRM} = sub { fail "timeout" }; +alarm 30; + +sub xread { + my $length = shift; + my $buffer = ""; + while ($length > length $buffer) { + my $ret = sysread STDIN, $buffer, $length, length $buffer; + fail "Expected $length bytes, got ".length $buffer + if defined $ret and $ret == 0; + fail "read: $!" if not defined $ret and $! != EINTR and $! != EAGAIN; + } + return $buffer; +} +my $hex_len = xread 4; +fail "Bad hex in packet length" unless $hex_len =~ m|^[0-9a-fA-F]{4}$|; +my $line = xread -4 + hex $hex_len; +unless (($service,$specpath,$spechost) = $line =~ + m|^(git-[a-z-]+) /*([!-~]+)\0host=([!-~]+)\0$|) { + $line =~ s|[^ -~]+| |g; + fail "Could not parse \"$line\"" +} + +@@READ_URLMAP@@ + +fail "No global mapping for $uri" unless defined $serve_user; + +my ($hn,$ha,$at,$naddrs,@addrs) = gethostbyname $spechost; +fail "hostname/address mismatch ($spechost $server_addr)" unless grep { + $server_addr eq inet_ntoa $_ + } @addrs; + +our @opts; + +push @opts, "-D$_=${$::{$_}}" + for qw(service specpath spechost + client client_addr client_port + server server_addr server_port); + +fail "no user $serve_user" unless getpwnam($serve_user); + +syslog 'notice', "$client $service $uri $serve_user"; + +my @cmd = ('userv', '-t300', @opts, $serve_user, $service); +no warnings; # suppress errors to stderr +exec @cmd or fail "exec userv: $!"; + +# end diff --git a/scripts/git-service.in b/scripts/git-service.in new file mode 100755 index 0000000..2b8aff3 --- /dev/null +++ b/scripts/git-service.in @@ -0,0 +1,51 @@ +#!/usr/bin/perl +# +# userv-git-daemon service script +# +# This was written by Tony Finch and subsequently +# heavily modified by Ian Jackson +# http://creativecommons.org/publicdomain/zero/1.0/ + +use strict; +use warnings; + +use POSIX; +use Sys::Syslog; + +our ($client,$service,$specpath,$spechost,@opts); + +${$::{$_}} = $ENV{"USERV_U_$_"} + for qw(service specpath spechost client); + +openlog "userv-$service:$ENV{USER}", 'pid', 'daemon'; +sub fail { syslog 'err', "$client @_"; exit } + +@@READ_URLMAP@@ + +fail "No user $ENV{USER} mapping for $uri" unless defined $serve_user; + +$serve_dir = "$ENV{HOME}/$serve_dir" unless $serve_dir =~ m|^/|; + +if (length $serve_repo) { + my $inspect= $serve_repo; + $inspect =~ s,^/,,; + fail "Bad subdirectory $serve_repo" unless $inspect =~ m/$repo_regexp/o; + fail "bad config - repo-regexp does not capture" unless defined $1; + $serve_repo= "/$1"; +} + +my $dir = $serve_dir.$serve_repo; + +my $path = $check_export ? "$dir/git-daemon-export-ok" : $dir; +fail "$! $path" unless -e $path; + +syslog 'notice', "$client $uri $dir"; + +@opts = qw( --strict ) + if @opts == 0 and $service eq 'git-upload-pack'; + +my @cmd = ($service =~ m|^(git)-(.*)$|, @opts, $dir); +no warnings; # suppress errors to stderr +exec @cmd or fail "exec $service: $!"; + +# end -- 2.30.2