updated Crypt::Monkeysphere::Validator to provide a lookup() function (instead of...
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Wed, 20 Apr 2011 19:52:22 +0000 (15:52 -0400)
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Wed, 20 Apr 2011 19:52:22 +0000 (15:52 -0400)
Crypt/Monkeysphere/MSVA.pm
Crypt/Monkeysphere/Validator.pm
unit-tests/20.validator/20.remote.t

index fd3540b54405f15f8418174955dcfaa5f6654858..6d27a2b135cd262e440ecfbf6dbbd27a10b3254f 100755 (executable)
                                                     gnupg=>$gnupg,
                                                     logger=>$logger);
 
-    my $uid_query=$validator->query(uid=>$uid,fpr=>$fpr, key=>$key );
+    my $uid_query=$validator->lookup(uid=>$uid,fpr=>$fpr,key=>$key);
 
     # only show the marginal UI if the UID of the corresponding
     # key is not fully valid.
-    if (scalar(@{$uid_query->{valid_keys}}) > 0) {
+    if (defined($uid_query->{valid_key})) {
       $ret->{valid} = JSON::true;
       $ret->{message} = sprintf('Successfully validated "%s" through the OpenPGP Web of Trust.', $uid);
     } else {
index b49c7a636b235366a31575ef321adbfa778101c2..732001b4565cceaedc89990140dca99d18680485 100644 (file)
@@ -15,14 +15,41 @@ Arguments
 
      Param hash, all optional.
 
-     context => 'e-mail' | 'https' | 'ssh', etc.
-                       control what counts as a suitable user IDs.
+     context => 'e-mail|https|ssh|...'
+                       control what counts as suitable user IDs and key capabilities.
 
      kspolicy => 'always|never|unlessvalid'
-                       when to fetch keys from keyserver.
+                       when to fetch keys and key updates from keyserver.
 
   (plus arguments for Crypt::Monkeysphere::{Keyserver,Logger}::new )
 
+=head2 lookup
+
+Arguments
+
+    Param hash.
+
+    uid => (mandatory) OpenPGP User ID desired.
+
+    fpr => fingerprint of the key to compare
+
+    key => hash of pubkey parameters as Math::BigInt values
+
+one of either fpr or key must be supplied.
+
+Return Value
+
+    Returns a hashref
+
+    If the lookup succeeded, then the hashref has a key named
+    valid_key that points to a hashref { fingerprint => $fpr, val =>
+    $validity }.
+
+    If no fully-valid keys+userid were found, but some keys matched
+    with less-than-valid user IDs, then the hashref has a key named
+    subvalid_keys that points to an arrayref of { fingerprint => $fpr,
+    val => $validity } hashrefs.
+
 =cut
 
 sub new {
@@ -58,79 +85,66 @@ sub test_capable {
   return 0;
 }
 
-sub query{
+sub _tryquery {
   my $self=shift;
-  my %opts=@_;
-
-  my $uid=$opts{uid} || croak "uid argument is mandatory";
-  my $fpr=$opts{fpr};
-  my $key=$opts{key};
+  my %args=@_;
 
-  my $gpgquery = defined($fpr) ?  '0x'.$fpr : '='.$uid;
+  my $uid=$args{uid} || croak "uid argument is mandatory";
+  my $fpr=$args{fpr};
+  my $key=$args{key};
+  defined($fpr) || defined($key) || croak "Must supply either a fingerprint or a key";
 
-  my $ret= { valid_keys => [],
-            subvalid_keys => [] };
+  my $subvalid_keys = [];
 
-  # setup variables
-  my $lastloop = 0;
-  my $foundvalid = 0;
+  my $gpgquery = defined($fpr) ? '0x'.$fpr : '='.$uid;
 
-  if ($self->{kspolicy} eq 'always') {
-    if (defined $fpr) {
-      $self->fetch_fpr($fpr);
-    } else {
-      $self->fetch_uid($uid);
-    }
-    $lastloop = 1;
-  } elsif ($self->{kspolicy} eq 'never') {
-    $lastloop = 1;
-  }
-
-  while (1) {
-    foreach my $gpgkey ($self->{gnupg}->get_public_keys($gpgquery)) {
-      my $validity = '-';
-      foreach my $tryuid ($gpgkey->user_ids) {
-       if ($tryuid->as_string eq $uid) {
-         $validity = $tryuid->validity;
-       }
+  foreach my $gpgkey ($self->{gnupg}->get_public_keys($gpgquery)) {
+    my $validity = '-';
+    foreach my $tryuid ($gpgkey->user_ids) {
+      if ($tryuid->as_string eq $uid) {
+        $validity = $tryuid->validity;
       }
-      # treat primary keys just like subkeys:
-      foreach my $subkey ($gpgkey, @{$gpgkey->subkeys}) {
-          if ((!defined($key) && (!defined($fpr))) ||
-             (defined($key) && $self->keycomp($key, $subkey)) ||
-              (defined($fpr) && ($subkey->fingerprint->as_hex_string eq $fpr))) {
-           $self->log('verbose', "key 0x%s matches...\n",$subkey->hex_id);
-           if ($self->test_capable($subkey) ) {
-             if ($validity =~ /^[fu]$/) {
-               $foundvalid = 1;
-               $self->log('verbose', "...and is fully valid!\n");
-               push(@{$ret->{valid_keys}},
-                    { fingerprint => $subkey->fingerprint, val => $validity });
-               last;
-             } else {
-               $self->log('verbose', "...but is not fully valid (%s).\n",$validity);
-               push(@{$ret->{subvalid_keys}},
-                    {fingerprint => $subkey->fingerprint, val => $validity }) if $lastloop;
-             }
-           }
-         }
-       }
-      last if ($foundvalid);
     }
-    if ($lastloop || $foundvalid) {
-      last;
-    } else {
-      if (!$foundvalid) {
-        if (defined $fpr) {
-          $self->fetch_fpr($fpr);
-        } else {
-          $self->fetch_uid($uid);
+    # treat primary keys just like subkeys:
+    foreach my $subkey ($gpgkey, @{$gpgkey->subkeys}) {
+      if ((defined($key) && $self->keycomp($key, $subkey)) ||
+          (defined($fpr) && ($subkey->fingerprint->as_hex_string eq $fpr))) {
+        $self->log('verbose', "key 0x%s matches...\n",$subkey->hex_id);
+        if ($self->test_capable($subkey) ) {
+          if ($validity =~ /^[fu]$/) {
+            $self->log('verbose', "...and is fully valid!\n");
+            # we have a key that matches with a valid userid -- no need to look further.
+            return {valid_key => { fingerprint => $subkey->fingerprint, val => $validity }};
+          } else {
+            $self->log('verbose', "...but is not fully valid (%s).\n",$validity);
+            push(@{$subvalid_keys},
+                 {fingerprint => $subkey->fingerprint, val => $validity });
+          }
         }
       }
-      $lastloop = 1;
     }
   }
-  return $ret;
+  return { subvalid_keys => $subvalid_keys };
+}
+
+sub lookup {
+  my $self=shift;
+  my %opts=@_;
+
+  if ($self->{kspolicy} eq 'unlessvalid') {
+    my $ret = $self->_tryquery(uid => $opts{uid}, fpr => $opts{fpr}, key => $opts{key}, subvalid => 0);
+    return $ret
+      if exists($ret->{valid_key});
+  };
+
+  if ($self->{kspolicy} ne 'never') {
+    if (defined($opts{fpr})) {
+      $self->fetch_fpr($opts{fpr});
+    } else {
+      $self->fetch_uid($opts{uid});
+    }
+  }
+  return $self->_tryquery(uid => $opts{uid}, fpr => $opts{fpr}, key => $opts{key}, subvalid => 1);
 }
 
 sub keycomp {
index 509399b76b8ea3128f7d7c2e8d69d71a9ea13437..1f3125c91caf63f8fdea5296e902b13988b1dc7a 100644 (file)
@@ -24,11 +24,11 @@ my $validator=new Crypt::Monkeysphere::Validator(gnupg=>$gnupg,
 
 isa_ok($validator,'Crypt::Monkeysphere::Validator');
 
-my $return=$validator->query(uid=>$uid);
+my $return=$validator->lookup(uid=>$uid,fpr=>'F8841978E8FA6FC65D3405155A5EA5837BD0B401');
 
 print Dumper($return) if ($ENV{MSTEST_DEBUG});
 
-ok(scalar @{$return->{valid_keys}} > 0);
+ok(defined($return->{valid_key}));