successfully parsing out the packets in pem2openpgp keytrans operation.
[monkeysphere.git] / src / keytrans / pem2openpgp
index 4e6ebe71a21f47d5ab7bfe4d3d6e3d94dc60e5e2..94fd3c89de16fdba5bb427b861b89b54ac9d36a9 100755 (executable)
@@ -23,6 +23,7 @@
 
 use strict;
 use warnings;
+use File::Basename;
 use Crypt::OpenSSL::RSA;
 use Crypt::OpenSSL::Bignum;
 use Crypt::OpenSSL::Bignum::CTX;
@@ -508,29 +509,120 @@ sub pem2openpgp {
 }
 
 
-my $rsa;
-my $stdin;
-if (defined $ENV{PEM2OPENPGP_NEWKEY}) {
-  $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY});
-} else {
-  $stdin = do {
-    local $/; # slurp!
-    <STDIN>;
-  };
 
-  $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin);
+
+sub openpgp2ssh {
+  my $instr = shift;
+  my $fpr = shift;
+
+  my $packettag;
+  my $dummy;
+  my $tag;
+
+  while (! eof($instr)) {
+    read($instr, $packettag, 1);
+    $packettag = ord($packettag);
+
+    my $packetlen;
+    if ( ! (0x80 & $packettag)) {
+      die "This is not an OpenPGP packet\n";
+    }
+    if (0x40 & $packettag) {
+      print STDERR "This is a new-style packet header\n";
+      $tag = (0x3f & $packettag);
+      my $nextlen = 0;
+      read($instr, $nextlen, 1);
+      $nextlen = ord($nextlen);
+      if ($nextlen < 192) {
+       $packetlen = $nextlen;
+      } elsif ($nextlen < 224) {
+       my $newoct;
+       read($instr, $newoct, 1);
+       $newoct = ord($newoct);
+       $packetlen = (($nextlen - 192) << 8) + ($newoct) + 192;
+      } elsif ($nextlen == 255) {
+       read($instr, $nextlen, 4);
+       $packetlen = unpack('%L', $nextlen);
+      } else {
+       # packet length is undefined.
+      }
+    } else {
+      my $lentype;
+      print STDERR "This is an old-style packet header\n";
+      $lentype = 0x03 & $packettag;
+      $tag = ( 0x3c & $packettag ) >> 2;
+      if ($lentype == 0) {
+       read($instr, $packetlen, 1) or die "could not read packet length\n";
+       $packetlen = unpack('C', $packetlen);
+      } elsif ($lentype == 1) {
+       read($instr, $packetlen, 2) or die "could not read packet length\n";
+       $packetlen = unpack('n', $packetlen);
+      } elsif ($lentype == 2) {
+       read($instr, $packetlen, 4) or die "could not read packet length\n";
+       $packetlen = unpack('N', $packetlen);
+      } else {
+       # packet length is undefined.
+      }
+    }
+
+    if (! defined($packetlen)) {
+      die "Undefined packet lengths are not supported.\n";
+    }
+    printf(STDERR "Packet is %d long\n", $packetlen);
+
+    if ($tag == $packet_types->{pubkey} ||
+       $tag == $packet_types->{pub_subkey} ||
+       $tag == $packet_types->{seckey} ||
+       $tag == $packet_types->{sec_subkey}) {
+      printf(STDERR "Packet type %d\n", $tag);
+      read($instr, $dummy, $packetlen) or die "Could not seek!\n";
+    } else {
+      printf(STDERR "We do not care about this packet.\n");
+      read($instr, $dummy, $packetlen) or die "Could not seek!\n";
+    }
+  }
+
+  print $tag;
 }
 
-my $uid = shift;
 
-# FIXME: fail if there is no given user ID; or should we default to
-# hostname_long() from Sys::Hostname::Long ?
+for (basename($0)) {
+  if (/^pem2openpgp$/) {
+    my $rsa;
+    my $stdin;
+    if (defined $ENV{PEM2OPENPGP_NEWKEY}) {
+      $rsa = Crypt::OpenSSL::RSA->generate_key($ENV{PEM2OPENPGP_NEWKEY});
+    } else {
+      $stdin = do {
+       local $/; # slurp!
+       <STDIN>;
+      };
+
+      $rsa = Crypt::OpenSSL::RSA->new_private_key($stdin);
+    }
+
+    my $uid = shift;
+
+    # FIXME: fail if there is no given user ID; or should we default to
+    # hostname_long() from Sys::Hostname::Long ?
 
-print pem2openpgp($rsa,
-                 $uid,
-                 { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP},
-                   expiration => $ENV{PEM2OPENPGP_EXPIRATION},
-                   usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS},
-                  }
-                );
+    print pem2openpgp($rsa,
+                     $uid,
+                     { timestamp => $ENV{PEM2OPENPGP_TIMESTAMP},
+                       expiration => $ENV{PEM2OPENPGP_EXPIRATION},
+                       usage_flags => $ENV{PEM2OPENPGP_USAGE_FLAGS},
+                     }
+                    );
+  }
+  elsif (/^openpgp2ssh$/) {
+      my $fpr = shift;
+      my $instream;
+      open($instream,'-');
+      binmode($instream, ":bytes");
+      openpgp2ssh($instream, $fpr);
+  }
+  else {
+    die "Unrecognized keytrans call.\n";
+  }
+}