From: Daniel Kahn Gillmor Date: Wed, 20 Apr 2011 19:52:22 +0000 (-0400) Subject: updated Crypt::Monkeysphere::Validator to provide a lookup() function (instead of... X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=7dac3646ed1ddc10345ed1eb0b8ce77003f96da1;p=monkeysphere-validation-agent.git updated Crypt::Monkeysphere::Validator to provide a lookup() function (instead of query()): useful for looking up a specific key or fingerprint --- diff --git a/Crypt/Monkeysphere/MSVA.pm b/Crypt/Monkeysphere/MSVA.pm index fd3540b..6d27a2b 100755 --- a/Crypt/Monkeysphere/MSVA.pm +++ b/Crypt/Monkeysphere/MSVA.pm @@ -675,11 +675,11 @@ 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 { diff --git a/Crypt/Monkeysphere/Validator.pm b/Crypt/Monkeysphere/Validator.pm index b49c7a6..732001b 100644 --- a/Crypt/Monkeysphere/Validator.pm +++ b/Crypt/Monkeysphere/Validator.pm @@ -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 { diff --git a/unit-tests/20.validator/20.remote.t b/unit-tests/20.validator/20.remote.t index 509399b..1f3125c 100644 --- a/unit-tests/20.validator/20.remote.t +++ b/unit-tests/20.validator/20.remote.t @@ -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}));