Lines 1-4
Link Here
|
1 |
#!/usr/bin/perl -T |
1 |
#!/usr/bin/perl |
2 |
## ----------------------------------------------------------------------- |
2 |
## ----------------------------------------------------------------------- |
3 |
## |
3 |
## |
4 |
## Copyright 2011 Intel Corporation; author: H. Peter Anvin |
4 |
## Copyright 2011 Intel Corporation; author: H. Peter Anvin |
Lines 68-79
Link Here
|
68 |
|
68 |
|
69 |
use Digest::SHA; |
69 |
use Digest::SHA; |
70 |
|
70 |
|
71 |
my $VERSION = '0.3.6'; |
71 |
use lib $ENV{GL_LIBDIR}; |
72 |
|
72 |
use Gitolite::Easy; |
73 |
# Scrub the environment completely |
73 |
use Gitolite::Conf::Load; |
74 |
%ENV = ('PATH' => '/bin:/usr/bin', |
74 |
|
75 |
'LANG' => 'C', |
75 |
my $VERSION = '0.3.6 (gitolite integrated)'; |
76 |
'SHELL' => '/bin/false'); # Nothing in this program should shell out |
76 |
|
|
|
77 |
# Scrub the environment completely, except gitolite variables and HOME |
78 |
{ |
79 |
my %env = %ENV; |
80 |
%ENV = ('PATH' => '/bin:/usr/bin', |
81 |
'LANG' => 'C', |
82 |
'SHELL' => '/bin/false'); # Nothing in this program should shell out |
83 |
$ENV{$_} = $env{$_} for ('HOME', grep(/^GL_/, keys %env)); |
84 |
} |
77 |
|
85 |
|
78 |
# The standard function to call on bail |
86 |
# The standard function to call on bail |
79 |
sub fatal($) { |
87 |
sub fatal($) { |
Lines 88-103
Link Here
|
88 |
} |
96 |
} |
89 |
|
97 |
|
90 |
sub my_username() { |
98 |
sub my_username() { |
91 |
my $whoami = getuid(); |
99 |
return $ENV{GL_USER}; |
92 |
my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwuid($whoami); |
|
|
93 |
|
94 |
if (!defined($name) || $whoami != $uid) { |
95 |
# We haven't called openlog() yet so we need to do it here |
96 |
openlog("kup-server($whoami)", 'ndelay,pid', LOG_LOCAL5); |
97 |
fatal("You don't exist, go away!"); |
98 |
} |
99 |
|
100 |
return (defined($name) && $whoami == $uid) ? $name : $whoami; |
101 |
} |
100 |
} |
102 |
|
101 |
|
103 |
my $user_name = my_username(); |
102 |
my $user_name = my_username(); |
Lines 106-112
Link Here
|
106 |
|
105 |
|
107 |
|
106 |
|
108 |
# Get config values from kup-server.cfg |
107 |
# Get config values from kup-server.cfg |
109 |
my $cfg_file = '/etc/kup/kup-server.cfg'; |
108 |
my $cfg_file = '/var/lib/gitolite3/.gitolite/local-code/configs/kup-server.cfg'; |
110 |
|
109 |
|
111 |
my $cfg = new Config::Simple($cfg_file); |
110 |
my $cfg = new Config::Simple($cfg_file); |
112 |
|
111 |
|
Lines 371-376
Link Here
|
371 |
return 1; |
370 |
return 1; |
372 |
} |
371 |
} |
373 |
|
372 |
|
|
|
373 |
# kup-server may "read" files from the kup data_path, or repos. If a repo is |
374 |
# supplied, we assume it's a gitolite repo and check access accordingly (while |
375 |
# remembering that kup seems to add a leading slash). If a repo is *not* |
376 |
# supplied, we assume we're talking about the kup data_path, which means we |
377 |
# make gitolite access rules from the "fake" repo called "@kup-server" |
378 |
sub read_allowed |
379 |
{ |
380 |
Gitolite::Common::trace( 1, 'read_allowed', @_ ); |
381 |
my $repo = shift || '@kup-server'; |
382 |
|
383 |
# gitolite expects a "normalised" repo name; no leading slash, no trailing ".git" |
384 |
$repo =~ s(^/)(); $repo =~ s/\.git$//; |
385 |
|
386 |
return can_read($repo); |
387 |
} |
388 |
|
389 |
# kup-server does not write to normal repos, it only writes to files in the |
390 |
# kup data_path. So we don't have to worry about any repo other than |
391 |
# "@kup-server", which is therefore hardcoded in here. |
392 |
sub write_allowed |
393 |
{ |
394 |
Gitolite::Common::trace( 1, 'write_allowed', @_ ); |
395 |
my($path, $perm) = @_; |
396 |
|
397 |
# other values for perm are + (rm) and C (mkdir), analogous to gitolite's |
398 |
# "+ means delete or rewind branch, C means create branch" |
399 |
$perm ||= 'W'; |
400 |
|
401 |
my $repo = '@kup-server'; |
402 |
|
403 |
# the paths that gitolite expects start with "refs/heads/", since we are |
404 |
# simply re-using the existing ACL for this. (But remember $path, in |
405 |
# kup-land, already starts with a "/".) |
406 |
$path = "refs/heads" . $path; |
407 |
|
408 |
return can_write($repo, $perm, $path) || |
409 |
can_write($repo, $perm, "$path/"); |
410 |
# the second check is because, when specifying a permission on a directory |
411 |
# in gitolite, you end with a "/", say "RW+C foo/ = user". To exercise |
412 |
# that right, the user runs "kup mkdir foo" or "kup rm foo". This fails, |
413 |
# because the regex "foo/" won't match. (In a *git* repo it doesn't |
414 |
# matter, because git doesn't allow empty directories, so it never |
415 |
# happens). |
416 |
} |
417 |
|
374 |
# Return a percentage, valid even if the denominator is zero |
418 |
# Return a percentage, valid even if the denominator is zero |
375 |
sub percentage($$) |
419 |
sub percentage($$) |
376 |
{ |
420 |
{ |
Lines 526-531
Link Here
|
526 |
fatal("Invalid pathname in TAR command"); |
570 |
fatal("Invalid pathname in TAR command"); |
527 |
} |
571 |
} |
528 |
|
572 |
|
|
|
573 |
if (!read_allowed($tree)) { |
574 |
fatal("Read access denied"); |
575 |
} |
576 |
|
529 |
if (!is_clean_string($prefix)) { |
577 |
if (!is_clean_string($prefix)) { |
530 |
fatal("Invalid prefix string"); |
578 |
fatal("Invalid prefix string"); |
531 |
} |
579 |
} |
Lines 569-574
Link Here
|
569 |
fatal("Invalid pathname in DIFF command"); |
617 |
fatal("Invalid pathname in DIFF command"); |
570 |
} |
618 |
} |
571 |
|
619 |
|
|
|
620 |
if (!read_allowed($tree)) { |
621 |
fatal("Read access denied"); |
622 |
} |
623 |
|
572 |
if ($tree !~ /\.git$/ || ! -d $git_path.$tree || |
624 |
if ($tree !~ /\.git$/ || ! -d $git_path.$tree || |
573 |
! -d $git_path.$tree.'/objects') { |
625 |
! -d $git_path.$tree.'/objects') { |
574 |
fatal("No such git tree"); |
626 |
fatal("No such git tree"); |
Lines 788-795
Link Here
|
788 |
or fatal("dup error"); |
840 |
or fatal("dup error"); |
789 |
close($devnull); |
841 |
close($devnull); |
790 |
|
842 |
|
|
|
843 |
my $gpgvbin = '/opt/gnupg22/bin/gpgv'; |
844 |
if ( ! -x $gpgvbin) { |
845 |
$gpgvbin = '/usr/bin/gpgv'; |
846 |
} |
847 |
|
791 |
my $status = |
848 |
my $status = |
792 |
system('/usr/bin/gpgv', |
849 |
system($gpgvbin, |
793 |
'--quiet', |
850 |
'--quiet', |
794 |
'--homedir', $tmpdir, |
851 |
'--homedir', $tmpdir, |
795 |
'--keyring', $pgp_path."/${user_name}.gpg", |
852 |
'--keyring', $pgp_path."/${user_name}.gpg", |
Lines 839-844
Link Here
|
839 |
fatal("Invalid filename in PUT command"); |
896 |
fatal("Invalid filename in PUT command"); |
840 |
} |
897 |
} |
841 |
|
898 |
|
|
|
899 |
if (!write_allowed($file)) { |
900 |
fatal("Write access denied"); |
901 |
} |
902 |
|
842 |
my @install_ext; |
903 |
my @install_ext; |
843 |
my @conflic_ext; |
904 |
my @conflic_ext; |
844 |
my $stem; |
905 |
my $stem; |
Lines 917-922
Link Here
|
917 |
fatal("Invalid filename in MKDIR command"); |
978 |
fatal("Invalid filename in MKDIR command"); |
918 |
} |
979 |
} |
919 |
|
980 |
|
|
|
981 |
if (!write_allowed($file, 'C')) { |
982 |
fatal("MKDIR access denied"); |
983 |
} |
984 |
|
920 |
my @badext = ('.sign', keys(%zformats)); |
985 |
my @badext = ('.sign', keys(%zformats)); |
921 |
|
986 |
|
922 |
foreach my $e (@badext) { |
987 |
foreach my $e (@badext) { |
Lines 991-996
Link Here
|
991 |
fatal("Invalid filename in $cmd command"); |
1056 |
fatal("Invalid filename in $cmd command"); |
992 |
} |
1057 |
} |
993 |
|
1058 |
|
|
|
1059 |
if ($cmd eq 'MOVE') { |
1060 |
if (!write_allowed($from, '+')) { |
1061 |
fatal("Delete (as part of MOVE) access denied"); |
1062 |
} |
1063 |
} |
1064 |
|
1065 |
if (!write_allowed($to)) { |
1066 |
fatal("Write access denied"); |
1067 |
} |
1068 |
|
994 |
if ($from =~ /\.gz$/) { |
1069 |
if ($from =~ /\.gz$/) { |
995 |
if ($to !~ /\.gz$/) { |
1070 |
if ($to !~ /\.gz$/) { |
996 |
fatal("$cmd of .gz file must itself end in .gz"); |
1071 |
fatal("$cmd of .gz file must itself end in .gz"); |
Lines 1093-1098
Link Here
|
1093 |
fatal("Invalid pathname in DELETE command"); |
1168 |
fatal("Invalid pathname in DELETE command"); |
1094 |
} |
1169 |
} |
1095 |
|
1170 |
|
|
|
1171 |
if (!write_allowed($file, "+")) { |
1172 |
fatal("Delete access denied"); |
1173 |
} |
1174 |
|
1096 |
if ($file !~ /\.gz$/ && |
1175 |
if ($file !~ /\.gz$/ && |
1097 |
has_extension($file, '.sign', keys(%zformats))) { |
1176 |
has_extension($file, '.sign', keys(%zformats))) { |
1098 |
fatal("DELETE of auxiliary files not supported"); |
1177 |
fatal("DELETE of auxiliary files not supported"); |
Lines 1222-1227
Link Here
|
1222 |
|
1301 |
|
1223 |
my($dir) = @args; |
1302 |
my($dir) = @args; |
1224 |
|
1303 |
|
|
|
1304 |
if (!read_allowed()) { |
1305 |
fatal("Read access denied"); |
1306 |
} |
1307 |
|
1225 |
# DIR / is permitted unlike any other command |
1308 |
# DIR / is permitted unlike any other command |
1226 |
$dir =~ s:/$::g; |
1309 |
$dir =~ s:/$::g; |
1227 |
if ($dir ne '' && !is_valid_filename($dir)) { |
1310 |
if ($dir ne '' && !is_valid_filename($dir)) { |
Lines 1261-1267
Link Here
|
1261 |
|
1344 |
|
1262 |
sub do_info() |
1345 |
sub do_info() |
1263 |
{ |
1346 |
{ |
1264 |
print "kup-server $VERSION\n"; |
1347 |
print "kup-server $VERSION\n\n"; |
|
|
1348 |
|
1349 |
my %xlat = ( |
1350 |
R => 'ls', |
1351 |
RW => 'put', |
1352 |
'RW+' => 'put/rm/mv', |
1353 |
'RWC' => 'put/mkdir', |
1354 |
'RW+C' => 'put/rm/mv/mkdir', |
1355 |
'-' => '(denied)', |
1356 |
); |
1357 |
Gitolite::Conf::Load::load('@kup-server'); |
1358 |
my @rules = Gitolite::Conf::Load::rules('@kup-server', $ENV{GL_USER}); |
1359 |
for my $r (@rules) { |
1360 |
my ($dummy, $perm, $ref) = @$r; |
1361 |
$ref =~ s(^refs/heads/)(); |
1362 |
$ref =~ s(/USER/)(/$ENV{GL_USER}/); |
1363 |
$ref = ($ref eq 'refs/.*') ? '/*' : '/' . $ref . '*'; |
1364 |
printf "%-24s %s\n", ($xlat{$perm} || $perm), $ref; |
1365 |
} |
1265 |
} |
1366 |
} |
1266 |
|
1367 |
|
1267 |
sub get_command() |
1368 |
sub get_command() |