changeset 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 9b1165b3f241
files sshfp.cgi sshfp_update.sh
diffstat 2 files changed, 145 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sshfp.cgi	Thu Nov 19 11:54:21 2009 +0000
@@ -0,0 +1,108 @@
+#!/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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sshfp_update.sh	Thu Nov 19 11:54:21 2009 +0000
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Updates this host's SSH fingerprints to the sshfp.cgi server
+#
+# 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.
+
+URL="https://admin.example.net/cgi-bin/sshfp.cgi"
+RSA_KEY=/etc/ssh/ssh_host_rsa_key.pub
+DSA_KEY=/etc/ssh/ssh_host_dsa_key.pub
+
+test -f "$RSA_KEY" || exit 1
+test -f "$DSA_KEY" || exit 1
+
+RSA_FP=$(ssh-keygen -lf "$RSA_KEY" | awk '{ print $2 }')
+DSA_FP=$(ssh-keygen -lf "$DSA_KEY" | awk '{ print $2 }')
+
+exec curl "$URL?action=update&rsa=$RSA_FP&dsa=$DSA_FP"
+