added support for rfc4716-style SSH pubkeys
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Fri, 29 Oct 2010 07:49:08 +0000 (03:49 -0400)
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Fri, 29 Oct 2010 07:49:08 +0000 (03:49 -0400)
Changelog
Crypt/Monkeysphere/MSVA.pm
Crypt/Monkeysphere/MSVA/Client.pm
tests/basic

index 6c50e6c9973a7b9b063f2515d28d97bc288f5aa8..df1a6e79ded5fc34d958305f88a572a5260e307f 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -12,10 +12,10 @@ msva-perl (0.6~pre) upstream;
     (closes MS #2567)
   * report server implementation name and version with every query (closes
     MS # 2564)
-  * support x509pem and opensshpubkey PKC formats in addition to x509der
-    (addresses MS #2566)
+  * support x509pem, opensshpubkey, and rfc4716 PKC formats in addition to
+    x509der (addresses MS #2566)
 
- -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Fri, 29 Oct 2010 02:55:37 -0400
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net>  Fri, 29 Oct 2010 03:48:50 -0400
 
 msva-perl (0.5) upstream;
 
index d1d6b1294ecf6f25133a2c357246712a5e46ba02..b92821b362af28bb9f57f5a783aee366cf119705 100755 (executable)
     return $out;
   }
 
+  sub rfc47162key {
+    my $data = shift;
+
+    my @goodlines;
+    my $continuation = '';
+    my $state = 'outside';
+    foreach my $line (split(/\n/, $data)) {
+      last if ($state eq 'body' && $line eq '---- END SSH2 PUBLIC KEY ----');
+      if ($state eq 'outside' && $line eq '---- BEGIN SSH2 PUBLIC KEY ----') {
+        $state = 'header';
+        next;
+      }
+      if ($state eq 'header') {
+        $line = $continuation.$line;
+        $continuation = '';
+        if ($line =~ /^(.*)\\$/) {
+          $continuation = $1;
+          next;
+        }
+        if (! ($line =~ /:/)) {
+          $state = 'body';
+        }
+      }
+      push(@goodlines, $line) if ($state eq 'body');
+    }
+
+    msvalog('debug', "Found %d lines of RFC4716 body:\n%s\n", 
+            scalar(@goodlines),
+            join("\n", @goodlines));
+    my $out = parse_rfc4716body(join('', @goodlines));
+
+    return $out;
+  }
+
   sub parse_rfc4716body {
     my $data = shift;
     $data = decode_base64($data) or return undef;
       $key = der2key(pem2der($data->{pkc}->{data}));
     } elsif (lc($data->{pkc}->{type}) eq 'opensshpubkey') {
       $key = opensshpubkey2key($data->{pkc}->{data});
+    } elsif (lc($data->{pkc}->{type}) eq 'rfc4716') {
+      $key = rfc47162key($data->{pkc}->{data});
     } else {
       $ret->{message} = sprintf("Don't know this public key carrier type: %s", $data->{pkc}->{type});
       return $status,$ret;
index 623e9e8a792fcaa765c27798ece74bae781f3d93..9b3991d26d0a4283fcbe176e9c8486e663c07d57 100644 (file)
       # remap raw pkc data into numeric array
       $transformed_data = [map(ord, split(//,$pkcdata))];
     } elsif ($pkctype eq 'x509pem' ||
-             $pkctype eq 'opensshpubkey') {
+             $pkctype eq 'opensshpubkey' ||
+             $pkctype eq 'rfc4716'
+            ) {
       $transformed_data = $pkcdata;
     } else {
       $self->log('error', "unknown pkc type '%s'.\n", $pkctype);
index c36099f99cd240d0529ac19006b07933fc9cb2b4..8605b132ad0228ece111b9b804ff621f79f2624c 100755 (executable)
@@ -25,6 +25,8 @@ srcdir=$(dirname $0)/..
 
 REPS=5
 
+CERTTYPES="x509pem x509der opensshpubkey rfc4716"
+
 printf "testing %d reps of simple/quick true/false:\n" "$REPS"
 for n in $(seq 1 "$REPS") ; do
     "${srcdir}"/test-msva msva-perl true
@@ -55,6 +57,7 @@ for name in x y z ; do
     chmod 0400  "${WORKDIR}/sec/${name}.key"
     openssl x509 -inform DER -outform PEM < "${WORKDIR}/pkc/${name}.x509der" > "${WORKDIR}/pkc/${name}.x509pem"
     ssh-keygen -y -P '' -f "${WORKDIR}/sec/${name}.key" > "${WORKDIR}/pkc/${name}.opensshpubkey"
+    ssh-keygen -e -P '' -f "${WORKDIR}/sec/${name}.key" > "${WORKDIR}/pkc/${name}.rfc4716"
 done
 
 # translate X and Y's keys into OpenPGP cert
@@ -65,7 +68,7 @@ done
 runtests() {
     # X should not validate as X or Y or Z:
     for name in x y z; do
-        for ctype in x509pem x509der opensshpubkey; do
+        for ctype in $CERTTYPES; do
             ! "${srcdir}"/test-msva msva-perl "${srcdir}"/test-msva msva-query-agent https "${name}.example.net" "${ctype}" < "${WORKDIR}/pkc/x.${ctype}"
         done
     done
@@ -73,11 +76,13 @@ runtests() {
     # certify X's OpenPGP cert with CA
     gpg --batch --yes --sign-key https://x.example.net
 
+    echo "Testing bad data:"
     # it should fail if we pass it the wrong kind of data:
     ! "${srcdir}"/test-msva msva-perl "${srcdir}"/test-msva msva-query-agent https x.example.net "x509der" < "${WORKDIR}/pkc/x.x509pem"
     ! "${srcdir}"/test-msva msva-perl "${srcdir}"/test-msva msva-query-agent https x.example.net "x509pem" < "${WORKDIR}/pkc/x.x509der"
+    echo "Done testing bad data."
         
-    for ctype in x509pem x509der opensshpubkey; do 
+    for ctype in $CERTTYPES; do 
     # X should now validate as X
         "${srcdir}"/test-msva msva-perl "${srcdir}"/test-msva msva-query-agent https x.example.net "${ctype}" < "${WORKDIR}/pkc/x.${ctype}"
         
@@ -95,8 +100,9 @@ runtests() {
     done
 }
 
+set -x
 MSVA_KEYSERVER_POLICY=never runtests
-
+set +x
 echo "Completed all tests as expected!"
 
 rm -rf "$WORKDIR"