treewide: Run refresh on all packages
[feed/packages.git] / net / gitolite / patches / 0100-avoid-ssh-keygen.patch
1 Author: Daniel F. Dickinson <cshored@thecshore.com>
2 Date: Sun Jan 27 01:04:25 2019 -0500
3
4 gitolite: Eliminate the need for ssh-keygen dependency
5
6 Previously gitolite used ssh-keygen to generate fingerprints
7 from OpenSSH keys to ensure non-duplication of keys when
8 processing them to create / manage user ssh access to the
9 git repositories. This ends up depending on openssl,
10 which is large and unnecessary when we are running on an
11 embedded distro such as OpenWrt.
12
13 Signed-off-by: Daniel F. Dickinson <cshored@thecshore.com>
14 --- a/src/lib/Gitolite/Common.pm
15 +++ b/src/lib/Gitolite/Common.pm
16 @@ -26,6 +26,8 @@ package Gitolite::Common;
17 use Exporter 'import';
18 use File::Path qw(mkpath);
19 use File::Temp qw(tempfile);
20 +use MIME::Base64 qw(decode_base64);
21 +use Digest::SHA qw(sha256_base64);
22 use Carp qw(carp cluck croak confess);
23
24 use strict;
25 @@ -352,43 +354,82 @@ sub logger_plus_stderr {
26 }
27
28 # ----------------------------------------------------------------------
29 +# Decode OpenSSH key
30 +# If the key cannot be parsed it will be undef
31 +# Returns (algorithm_name, algo_data1, algo_data2, ...)
32 +sub ssh_decode_key($) {
33 + my $key = shift;
34 + my $keydata = decode_base64($key);
35 + my @keyparts = ();
36 + my $partlen;
37 + my $algorithm;
38 + my $data;
39 + my $pos = 0;
40 + $partlen = unpack('N', substr $keydata, $pos, 4) or return undef;
41 + $algorithm = substr $keydata, $pos + 4, $partlen or return undef;
42 + $pos = $pos + 4 + $partlen;
43 + while ( $pos <= length($keydata) ) {
44 + $partlen = unpack('N', substr $keydata, $pos, 4) or last;
45 + $data = unpack('s>*', substr $keydata, $pos + 4, 4) or last;
46 + $pos = $pos + 4 + $partlen;
47 + push @keyparts, $data;
48 + }
49 + return ( $algorithm, @keyparts );
50 +}
51 +
52 +# ----------------------------------------------------------------------
53 +# Parse OpenSSH line
54 +# If the file cannot be parsed it will be undef
55 +# Returns (restrictions, algorithm, PEMkey, comment)
56 +sub ssh_parse_line($) {
57 + my $ssh_line = shift;
58 + my @ssh_parts = split / /, $ssh_line, 5;
59 + if (scalar @ssh_parts < 4) {
60 + @ssh_parts = ('', @ssh_parts);
61 + }
62 + if (scalar @ssh_parts > 4) {
63 + @ssh_parts = @ssh_parts[0,3]
64 + }
65 + if (scalar @ssh_parts < 4) {
66 + @ssh_parts = undef;
67 + }
68 + return ( @ssh_parts );
69 +}
70 +
71 +# ----------------------------------------------------------------------
72 +# Get the SSH fingerprint of a line of text
73 +# If the fingerprint cannot be parsed, it will be undef
74 +# In a scalar context, returns the fingerprint
75 +# In a list context, returns (fingerprint, output) where output
76 +# is the parsed input line (less algorithm)
77 +sub ssh_fingerprint_line($) {
78 + my $ssh_line = shift;
79 + my @parsed_line = ssh_parse_line($ssh_line) or return undef;
80 + my @ssh_parts = ssh_decode_key($parsed_line[2]) or return undef;
81 + ( $parsed_line[1] eq $ssh_parts[0] ) or die "algorithm mismatch: $parsed_line[1] vs. $ssh_parts[0]";
82 + my $fp = sha256_base64(join(' ', @ssh_parts[1,-1]));
83 + return wantarray ? ($fp, join(' ', @ssh_parts[1,-1])) : $fp;
84 +}
85 +
86 +# ----------------------------------------------------------------------
87 # Get the SSH fingerprint of a file
88 # If the fingerprint cannot be parsed, it will be undef
89 # In a scalar context, returns the fingerprint
90 # In a list context, returns (fingerprint, output) where output
91 -# is the raw output of the ssh-keygen command
92 -sub ssh_fingerprint_file {
93 +# is the raw input line
94 +sub ssh_fingerprint_file($) {
95 my $in = shift;
96 -f $in or die "file not found: $in\n";
97 my $fh;
98 - open( $fh, "ssh-keygen -l -f $in |" ) or die "could not fork: $!\n";
99 + open( $fh, $in ) or die "could not open $in: $!\n";
100 my $output = <$fh>;
101 chomp $output;
102 - # dbg("fp = $fp");
103 close $fh;
104 # Return a valid fingerprint or undef
105 - my $fp = undef;
106 - if($output =~ /((?:MD5:)?(?:[0-9a-f]{2}:){15}[0-9a-f]{2})/i or
107 - $output =~ m{((?:RIPEMD|SHA)\d+:[A-Za-z0-9+/=]+)}i) {
108 - $fp = $1;
109 - }
110 + my $fp = ssh_fingerprint_line($output);
111 return wantarray ? ($fp, $output) : $fp;
112 }
113
114 -# Get the SSH fingerprint of a line of text
115 -# If the fingerprint cannot be parsed, it will be undef
116 -# In a scalar context, returns the fingerprint
117 -# In a list context, returns (fingerprint, output) where output
118 -# is the raw output of the ssh-keygen command
119 -sub ssh_fingerprint_line {
120 - my ( $fh, $fn ) = tempfile();
121 - print $fh shift() . "\n";
122 - close $fh;
123 - my ($fp,$output) = ssh_fingerprint_file($fn);
124 - unlink $fn;
125 - return wantarray ? ($fp,$output) : $fp;
126 -}
127 -
128 # ----------------------------------------------------------------------
129
130 # bare-minimum subset of 'Tsh' (see github.com/sitaramc/tsh)