Mercurial > hg > sshfp
view sshfp.cgi @ 0:d7fc9c3b4d87
Adding SSHFP CGI and update script
author | Dominic Cleal <dominic-cleal@cdo2.com> |
---|---|
date | Thu, 19 Nov 2009 11:54:21 +0000 |
parents | |
children |
line wrap: on
line source
#!/usr/bin/perl # # Maintains and displays a list of SSH fingerprints for remote hosts. # # Permits remote host to update their SSH fingerprint and then displays the # list of all recorded fingerprints. # # Warning: no limits are made on the number of fingerprints that can be stored, # could potentially be DDoSed with lots of small files. This script should be # locked down in the web server config. # # Copyright (c) 2009 CDO2 Limited # Author: Dominic Cleal <dominic-cleal@cdo2.com> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. use warnings; use strict; use CGI; use Socket; use POSIX qw/strftime/; my $STORE = '/var/local/sshfp/'; my $IP_REGEX = qr/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; my $FP_REGEX = qr/^([\da-f]{2}:?){16}$/; my $cgi = new CGI; print $cgi->header(-type => 'text/html', -pragma => 'no-cache', -expires => '-365d'); my $action = $cgi->param('action') || 'display'; my $sshfp_rsa = $cgi->param('rsa'); my $sshfp_dsa = $cgi->param('dsa'); if ($action eq 'update') { error('Both RSA or DSA fingerprints required') unless (defined $sshfp_rsa && defined $sshfp_dsa); error('RSA fingerprint invalid') unless ($sshfp_rsa =~ $FP_REGEX); error('DSA fingerprint invalid') unless ($sshfp_dsa =~ $FP_REGEX); my $time = time; my $ip = $ENV{'REMOTE_ADDR'} || error('IP unavailable'); error('IP invalid') unless ($ip =~ $IP_REGEX); open(FH, "> $STORE/$ip"); print FH "$time,$sshfp_rsa,$sshfp_dsa"; close(FH); } else { print<<END; <html> <head><title>SSH fingerprint records</title></head> <body> <table border="1"> <tr><th>Hostname</th><th>IP address</th><th>Last update</th> <th>RSA fingerprint</th><th>DSA fingerprint</th></tr> END opendir(my $dh, $STORE) || error("Can't open store: $!"); my @files = sort grep { $IP_REGEX && -f "$STORE/$_" } readdir($dh); closedir $dh; foreach my $ip (@files) { my $packedip = inet_aton($ip); my $host = gethostbyaddr($packedip, AF_INET); open(FH, "< $STORE/$ip"); my @text = split(/,/, <FH>); close(FH); my $time = strftime("%Y-%m-%d %H:%M:%S", gmtime $text[0]); print("<tr><td>$host</td><td>$ip</td><td>$time</td>" . "<td>$text[1]</td><td>$text[2]</td></tr>\n"); } print<<END; </table></body></html> END } sub error { my $text = shift; print "ERROR: $text\n"; die $text; }