aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2016-01-12 23:48:43 -0800
committerRobin H. Johnson <robbat2@gentoo.org>2016-01-12 23:48:43 -0800
commit8ac17c4386216489d3a979da7534b9ec9e563c8f (patch)
treed8bbd3af3be8c6d02f6fbf43a1fdf3dfd00782f2
parentMerge remote-tracking branch 'upstream/master' (diff)
parentukm: use new ssh fingerprint functions. (diff)
downloadgitolite-gentoo-8ac17c4386216489d3a979da7534b9ec9e563c8f.tar.gz
gitolite-gentoo-8ac17c4386216489d3a979da7534b9ec9e563c8f.tar.bz2
gitolite-gentoo-8ac17c4386216489d3a979da7534b9ec9e563c8f.zip
Merge branch 'wip-sshfp'
-rwxr-xr-xcontrib/commands/ukm8
-rwxr-xr-xsrc/commands/sshkeys-lint32
-rwxr-xr-xsrc/commands/sskm7
-rw-r--r--src/lib/Gitolite/Common.pm42
-rwxr-xr-xsrc/triggers/post-compile/ssh-authkeys15
5 files changed, 67 insertions, 37 deletions
diff --git a/contrib/commands/ukm b/contrib/commands/ukm
index 8a2d361..3683154 100755
--- a/contrib/commands/ukm
+++ b/contrib/commands/ukm
@@ -220,10 +220,10 @@ sub cd_temp_clone {
# compute the fingerprint from the full path of a pubkey file
sub fingerprint {
- my $fp = `ssh-keygen -l -f $_[0]`;
- die "does not seem to be a valid pubkey\n"
- unless $fp =~ /(([0-9a-f]+:)+[0-9a-f]+) /i;
- return $1;
+ my ($fp, $output) = ssh_fingerprint_file(shift);
+ # Do not print the output of $output to an untrusted destination.
+ die "does not seem to be a valid pubkey\n" unless $fp;
+ return $fp;
}
diff --git a/src/commands/sshkeys-lint b/src/commands/sshkeys-lint
index ea3df2a..760b3d7 100755
--- a/src/commands/sshkeys-lint
+++ b/src/commands/sshkeys-lint
@@ -4,6 +4,8 @@ use warnings;
# complete rewrite of the sshkeys-lint program. Usage has changed, see
# usage() function or run without arguments.
+use lib $ENV{GL_LIBDIR};
+use Gitolite::Common;
use Getopt::Long;
my $admin = 0;
@@ -144,30 +146,20 @@ sub ak_comment {
sub fprint {
local $_ = shift;
- my ( $fh, $tempfn, $in );
+ my ($fp, $output);
if ( /$KEYTYPE_REGEX/ ) {
- # an actual key was passed. Since ssh-keygen requires an actual file,
- # make a temp file to take the data and pass on to ssh-keygen
- s/^.* ($KEYTYPE_REGEX)/$1/;
- use File::Temp qw(tempfile);
- ( $fh, $tempfn ) = tempfile();
- $in = $tempfn;
- print $fh $_;
- close $fh;
+ # an actual key was passed. ssh-keygen CAN correctly handle options on
+ # the front of the key, so don't bother to strip them at all.
+ ($fp, $output) = ssh_fingerprint_line($_);
} else {
# a filename was passed
- $in = $_;
+ ($fp, $output) = ssh_fingerprint_file($_);
+ # include the line of input as well, as it won't always be included by the ssh-keygen command
+ warn "Bad line: $_\n" unless $fp;
}
- # dbg("in = $in");
- -f $in or die "file not found: $in\n";
- open( $fh, "ssh-keygen -l -f $in |" ) or die "could not fork: $!\n";
- my $fp = <$fh>;
- # dbg("fp = $fp");
- close $fh;
- unlink $tempfn if $tempfn;
- warn "$fp\n" unless $fp =~ /([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f])+)/ or $fp =~ m(SHA256:([A-Za-z0-9+/]+));
-
- return $1;
+ # sshkeys-lint should only be run by a trusted admin, so we can give the output here.
+ warn "$output\n" unless $fp;
+ return $fp;
}
# ------------------------------------------------------------------------
diff --git a/src/commands/sskm b/src/commands/sskm
index fd60233..eb51f69 100755
--- a/src/commands/sskm
+++ b/src/commands/sskm
@@ -137,9 +137,10 @@ sub cd_temp_clone {
}
sub fingerprint {
- my $fp = `ssh-keygen -l -f $_[0]`;
- die "does not seem to be a valid pubkey\n" unless $fp =~ /(([0-9a-f]+:)+[0-9a-f]+ )/i;
- return $1;
+ my ($fp, $output) = ssh_fingerprint_file(shift);
+ # Do not print the output of $output to an untrusted destination.
+ die "does not seem to be a valid pubkey\n" unless $fp;
+ return $fp;
}
sub safe_stdin {
diff --git a/src/lib/Gitolite/Common.pm b/src/lib/Gitolite/Common.pm
index 5d6b749..d59118c 100644
--- a/src/lib/Gitolite/Common.pm
+++ b/src/lib/Gitolite/Common.pm
@@ -16,10 +16,14 @@ package Gitolite::Common;
dd
t_start
t_lap
+
+ ssh_fingerprint_file
+ ssh_fingerprint_line
);
#>>>
use Exporter 'import';
use File::Path qw(mkpath);
+use File::Temp qw(tempfile);
use Carp qw(carp cluck croak confess);
use strict;
@@ -333,6 +337,44 @@ sub logger_plus_stderr {
}
# ----------------------------------------------------------------------
+# Get the SSH fingerprint of a file
+# If the fingerprint cannot be parsed, it will be undef
+# In a scalar context, returns the fingerprint
+# In a list context, returns (fingerprint, output) where output
+# is the raw output of the ssh-keygen command
+sub ssh_fingerprint_file {
+ my $in = shift;
+ -f $in or die "file not found: $in\n";
+ my $fh;
+ open( $fh, "ssh-keygen -l -f $in |" ) or die "could not fork: $!\n";
+ my $output = <$fh>;
+ chomp $output;
+ # dbg("fp = $fp");
+ close $fh;
+ # Return a valid fingerprint or undef
+ my $fp = undef;
+ if($output =~ /((?:MD5:)?(?:[0-9a-f]{2}:){15}[0-9a-f]{2})/i or
+ $output =~ m{((?:RIPEMD|SHA)\d+:[A-ZA-z0-9+/=]+)}i) {
+ $fp = $1;
+ }
+ return wantarray ? ($fp, $output) : $fp;
+}
+
+# Get the SSH fingerprint of a line of text
+# If the fingerprint cannot be parsed, it will be undef
+# In a scalar context, returns the fingerprint
+# In a list context, returns (fingerprint, output) where output
+# is the raw output of the ssh-keygen command
+sub ssh_fingerprint_line {
+ my ( $fh, $fn ) = tempfile();
+ print $fh shift() . "\n";
+ close $fh;
+ my ($fp,$output) = ssh_fingerprint_file($fn);
+ unlink $fn;
+ return wantarray ? ($fp,$output) : $fp;
+}
+
+# ----------------------------------------------------------------------
# bare-minimum subset of 'Tsh' (see github.com/sitaramc/tsh)
{
diff --git a/src/triggers/post-compile/ssh-authkeys b/src/triggers/post-compile/ssh-authkeys
index 1a3b09c..fe1e7c1 100755
--- a/src/triggers/post-compile/ssh-authkeys
+++ b/src/triggers/post-compile/ssh-authkeys
@@ -2,7 +2,6 @@
use strict;
use warnings;
-use File::Temp qw(tempfile);
use Getopt::Long;
use lib $ENV{GL_LIBDIR};
@@ -126,19 +125,15 @@ sub fp {
sub fp_file {
return $selinux++ if $selinux; # return a unique "fingerprint" to prevent noise
my $f = shift;
- my $fp = `ssh-keygen -l -f '$f'`;
- chomp($fp);
- _die "fingerprinting failed for '$f'" unless $fp =~ /([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f])+)/ or $fp =~ m(SHA256:([A-ZA-z0-9+/]+));
- $fp = $1;
+ my ($fp, $output) = ssh_fingerprint_file($f);
+ _die "fingerprinting failed for '$f': $output" unless $fp;
return $fp;
}
sub fp_line {
- my ( $fh, $fn ) = tempfile();
- print $fh shift() . "\n";
- close $fh;
- my $fp = fp_file($fn);
- unlink $fn;
+ my $line = shift;
+ my ($fp, $output) = ssh_fingerprint_line($line);
+ _die "fingerprinting failed for '$line': $output" unless $fp;
return $fp;
}