| 1 | #!/usr/bin/perl |
| 2 | # |
| 3 | # A very simple userv git-daemon wrapper. |
| 4 | # |
| 5 | # This reads the first packet-line of the protocol, checks the syntax |
| 6 | # of the user, pathname, and hostname, then uses userv to invoke the |
| 7 | # real git daemon as the target user with safe arguments. |
| 8 | # |
| 9 | # This was written by Tony Finch <dot@dotat.at> |
| 10 | # You may do anything with it, at your own risk. |
| 11 | # http://creativecommons.org/publicdomain/zero/1.0/ |
| 12 | |
| 13 | use strict; |
| 14 | use warnings; |
| 15 | |
| 16 | use POSIX; |
| 17 | |
| 18 | my $USER = qr{[0-9a-z]+}; |
| 19 | my $PATH = qr{[-+,._/0-9A-Za-z]+}; |
| 20 | my $HOST = qr{[-.0-9A-Za-z]+}; |
| 21 | |
| 22 | sub xread { |
| 23 | my $length = shift; |
| 24 | my $buffer = ""; |
| 25 | my $count = 0; |
| 26 | while ($length > length $buffer) { |
| 27 | my $data; |
| 28 | my $ret = sysread STDIN, $data, $len |
| 29 | while not defined $ret and ($! == EINTR or $! == EAGAIN); |
| 30 | die "read" unless defined $ret; |
| 31 | die "short read: expected $length bytes, got $count\n" if $ret == 0; |
| 32 | $buffer .= $data; |
| 33 | $count += $ret; |
| 34 | } |
| 35 | return $buffer; |
| 36 | } |
| 37 | |
| 38 | my $len_hex = xread 4; |
| 39 | die "bad packet length" unless $len_hex =~ m{^[0-9a-zA-Z]{4}$}; |
| 40 | my $len = hex $len; |
| 41 | |
| 42 | my $line = xread $len; |
| 43 | $line =~ m{^git-upload-pack ~($USER)/($PATH[.]git)\0host=($HOST)\0$}; |
| 44 | my ($user,$path,$host) = ($1,$2,$3); |
| 45 | |
| 46 | # child's output will go directly to inetd |
| 47 | open CHILD, '-|', 'userv', $user, |
| 48 | qw(git daemon --inetd --strict-paths |
| 49 | --user-path=public-git --forbid-override=receive-pack) |
| 50 | or die "open pipe to userv: $!\n"; |
| 51 | |
| 52 | # proxy command line to child |
| 53 | syswrite CHILD, $len_hex.$line |
| 54 | or die "write to userv: $!\n"; |
| 55 | |
| 56 | # relay stdin to child |
| 57 | open STDOUT, ">&CHILD" |
| 58 | or die "dup: $!\n"; |
| 59 | exec 'cat' |
| 60 | or die "exec: $!\n"; |
| 61 | |
| 62 | die |