#!/usr/bin/perl -w # # gpgsign: assistant for signing keys # # $dotat: scripts/gpgsign,v 1.27 2006/05/15 09:59:20 fanf2 Exp $ use strict; use DB_File; use Getopt::Long; sub check_key ($); sub command ($); sub debugp ($@); sub debugs ($&); sub find_status ($); sub ndebug ($&); sub receive_email (); sub sign_pending (); sub poo ($); sub shit ($); sub shite ($); use vars qw( %status %option ); my $self = 'Tony Finch '; my $dotdir = "$ENV{HOME}/.gnupg"; my $status = "$dotdir/sign-status"; my $message = "$dotdir/sign-message"; my $addr_re = '; shit "Aborting." unless $yn =~ m/^(y|yes)$/i; my %addresses; if (defined $key2addrs{$longid}) { for my $addr (@{$key2addrs{$longid}}) { $addresses{$addr} = 1 if $option{force} or not ($done{$addr} or $ok{$addr}); } my $addrs = join " ", keys %addresses; print "Re-send challenges to $addrs?\n"; $yn = ; shit "Aborting." unless $yn =~ m/^(y|yes)$/i; } else { for my $line (split /\n/, $fingerprint) { debugp 2, "fingerprint line $line"; $addresses{$1} = 1 if $line =~ /^uid +(.*)/; } debugp 1, "Email addresses:\n", map "$_\n", keys %addresses; } for my $address (keys %addresses) { $address =~ /$addr_re/io; my $addr = $1; my $cookie = $addr2cookie{$addr}; unless (defined $cookie) { $cookie = command "dd if=/dev/random count=1 2>/dev/null | md5" or shit "Could not get a cookie"; chomp $cookie; } my $status = "$longid\t$address\t$cookie"; debugp 1, $status; print "Preparing message for: $address\n"; open MESSAGE, "> $message" or shite "open > $message"; print MESSAGE <> $message" or shite "open | gpg"; print GPG <) { debugp 2, "read $_"; for my $cookie (keys %cookie2key) { debugp 2, "looking for $cookie"; next unless /\b$cookie\b/; debugp 2, "Found"; my $addr = $cookie2addr{$cookie}; poo "No address for cookie?!" unless defined $addr; debugp 1, "$cookie -> $addr"; if (not exists $status{$addr}) { poo "No status for address?!"; } elsif ($status{$addr} =~ /\tDONE$/) { debugp 1, "Already signed"; } elsif ($status{$addr} =~ /\tOK$/) { debugp 1, "Already seen"; } else { $status{$addr} .= "\tOK"; $ok++; } } } shit "Couldn't find a valid cookie!" unless $ok; } ######################################################################## # # Look for any pending signs that we can do # sub sign_pending () { for my $keyid (keys %total) { debugp 1, "$keyid total=$total{$keyid} ok=$ok{$keyid}"; debugp 1, "@{$key2addrs{$keyid}}"; next unless $total{$keyid} == $ok{$keyid} or $option{force} and $ok{$keyid}; poo $status{$_} for @{$key2addrs{$keyid}}; my $gpgid = $keyid; $gpgid =~ s/ //g; 0 == system "gpg --sign-key $gpgid" or shit "gpg failed!"; 0 == system "gpg --send-keys $gpgid" or shit "gpg failed!"; my $address; for my $addr (@{$key2addrs{$keyid}}) { ndebug 3, sub { $status{$addr} =~ s/\tOK$/\tDONE/ or next; debugp 1, $status{$addr}; $address = $1 if not defined $address and $status{$addr} =~ /\t([^\t]+)\t/; }; } shit "No email address!" unless defined $address; open MESSAGE, "> $message" or shite "open > $message"; if ($total{$keyid} == $ok{$keyid}) { print MESSAGE <> $message" or shit "gpg failed!"; debugs 2, sub { system "cat $message" }; ndebug 3, sub { 0 == system "sendmail -t < $message" or shit "Failed to send mail to $address"; }; unlink $message; } } ######################################################################## # # Run a command and return the output # sub command ($) { my $cmd = shift; my $out = `$cmd 2>&1`; if ($?) { print STDERR $out; return undef; } else { return $out; } } ######################################################################## # # Debugging and error handling # sub debugp ($@) { return if not defined $main::option{debug} or $main::option{debug} < shift; print STDERR @_, "\n"; } sub debugs ($&) { return if not defined $main::option{debug} or $main::option{debug} < shift; &{$_[0]}; } sub ndebug ($&) { return if defined $main::option{debug} and $main::option{debug} >= shift; &{$_[0]}; } sub poo ($) { warn "@_\n"; } sub shit ($) { die "@_\n"; } sub shite ($) { die "@_: $!\n"; } ########################################################################