| 50 |
of keyids on the command line, fetches them from a keyserver and calls GnuPG so |
of keyids on the command line, fetches them from a keyserver and calls GnuPG so |
| 51 |
that you can sign it. It then mails each key to all its email addresses - only |
that you can sign it. It then mails each key to all its email addresses - only |
| 52 |
including the one UID that we send to in each mail, pruned from all but self |
including the one UID that we send to in each mail, pruned from all but self |
| 53 |
sigs and sigs done by you. |
sigs and sigs done by you. The mailed key is encrypted with itself as a means |
| 54 |
|
to verify that key belongs to the recipient. |
| 55 |
|
|
| 56 |
=head1 OPTIONS |
=head1 OPTIONS |
| 57 |
|
|
| 86 |
|
|
| 87 |
Select the key that is used for signing, in case you have more than one key. |
Select the key that is used for signing, in case you have more than one key. |
| 88 |
|
|
| 89 |
|
=item B<--key-file> I<file> |
| 90 |
|
|
| 91 |
|
Import keys from file. Can be supplied more than once. |
| 92 |
|
|
| 93 |
=back |
=back |
| 94 |
|
|
| 95 |
=head1 FILES |
=head1 FILES |
| 98 |
|
|
| 99 |
=item $HOME/.caffrc - configuration file |
=item $HOME/.caffrc - configuration file |
| 100 |
|
|
| 101 |
|
=item $HOME/.caff/keys/yyyy-mm-dd/ - processed keys |
| 102 |
|
|
| 103 |
|
=item $HOME/.caff/gnupghome/ - caff's working dir for gpg |
| 104 |
|
|
| 105 |
|
=item $HOME/.caff/gnupghome/gpg.conf - gpg configuration |
| 106 |
|
|
| 107 |
|
useful options include use-agent, default-cert-level, etc. |
| 108 |
|
|
| 109 |
=back |
=back |
| 110 |
|
|
| 111 |
=head1 CONFIGURATION FILE OPTIONS |
=head1 CONFIGURATION FILE OPTIONS |
| 112 |
|
|
| 113 |
The configuration file is a perl script that sets values in the hash B<%CONFIG>. |
The configuration file is a perl script that sets values in the hash B<%CONFIG>. |
| 114 |
|
The file is generated when it does not exist. |
| 115 |
|
|
| 116 |
Example: |
Example: |
| 117 |
|
|
| 183 |
If true, then skip the step of fetching keys from the keyserver. |
If true, then skip the step of fetching keys from the keyserver. |
| 184 |
Default: B<0>. |
Default: B<0>. |
| 185 |
|
|
| 186 |
|
=item B<key-files> [list of files] |
| 187 |
|
|
| 188 |
|
A list of files containing keys to be imported. |
| 189 |
|
|
| 190 |
=head2 Signing settings |
=head2 Signing settings |
| 191 |
|
|
| 192 |
=item B<no-sign> [boolean] |
=item B<no-sign> [boolean] |
| 236 |
|
|
| 237 |
=back |
=back |
| 238 |
|
|
| 239 |
|
=item B<reply-to> [string] |
| 240 |
|
|
| 241 |
|
Add a Reply-To: header to messages sent. Default: none. |
| 242 |
|
|
| 243 |
=item B<bcc> [string] |
=item B<bcc> [string] |
| 244 |
|
|
| 245 |
Address to send blind carbon copies to when sending mail. |
Address to send blind carbon copies to when sending mail. |
| 261 |
|
|
| 262 |
http://pgp-tools.alioth.debian.org/ |
http://pgp-tools.alioth.debian.org/ |
| 263 |
|
|
| 264 |
|
=head1 SEE ALSO |
| 265 |
|
|
| 266 |
|
gpg(1), pgp-clean(1), /usr/share/doc/signing-party/caff/caffrc.sample. |
| 267 |
|
|
| 268 |
=cut |
=cut |
| 269 |
|
|
| 270 |
use strict; |
use strict; |
| 284 |
my ($REVISION_NUMER) = $REVISION =~ /(\d+)/; |
my ($REVISION_NUMER) = $REVISION =~ /(\d+)/; |
| 285 |
my $VERSION = "0.0.0.$REVISION_NUMER"; |
my $VERSION = "0.0.0.$REVISION_NUMER"; |
| 286 |
|
|
| 287 |
|
|
| 288 |
|
|
| 289 |
|
sub notice($) { |
| 290 |
|
my ($line) = @_; |
| 291 |
|
print "[NOTICE] $line\n"; |
| 292 |
|
}; |
| 293 |
|
sub info($) { |
| 294 |
|
my ($line) = @_; |
| 295 |
|
print "[INFO] $line\n"; |
| 296 |
|
}; |
| 297 |
|
sub debug($) { |
| 298 |
|
my ($line) = @_; |
| 299 |
|
#print "[DEBUG] $line\n"; |
| 300 |
|
}; |
| 301 |
|
sub trace($) { |
| 302 |
|
my ($line) = @_; |
| 303 |
|
#print "[trace] $line\n"; |
| 304 |
|
}; |
| 305 |
|
sub trace2($) { |
| 306 |
|
my ($line) = @_; |
| 307 |
|
#print "[trace2] $line\n"; |
| 308 |
|
}; |
| 309 |
|
|
| 310 |
|
|
| 311 |
|
sub generate_config() { |
| 312 |
|
notice("Error: \$LOGNAME is not set.\n") unless defined $ENV{'LOGNAME'}; |
| 313 |
|
my $gecos = defined $ENV{'LOGNAME'} ? (getpwnam($ENV{LOGNAME}))[6] : undef; |
| 314 |
|
my $email; |
| 315 |
|
my @keys; |
| 316 |
|
my $hostname = `hostname -f`; |
| 317 |
|
chomp $hostname; |
| 318 |
|
my ($Cgecos,$Cemail,$Ckeys) = ('','',''); |
| 319 |
|
if (defined $gecos) { |
| 320 |
|
$gecos =~ s/,.*//; |
| 321 |
|
|
| 322 |
|
my $gpg = GnuPG::Interface->new(); |
| 323 |
|
$gpg->call( 'gpg' ); |
| 324 |
|
$gpg->options->hash_init( |
| 325 |
|
'extra_args' => [ qw{ --no-auto-check-trustdb --trust-model=always --with-colons --fixed-list-mode } ] ); |
| 326 |
|
$gpg->options->meta_interactive( 0 ); |
| 327 |
|
my ($inputfd, $stdoutfd, $stderrfd, $statusfd, $handles) = make_gpg_fds(); |
| 328 |
|
my $pid = $gpg->list_public_keys(handles => $handles, command_args => [ $gecos ]); |
| 329 |
|
my ($stdout, $stderr, $status) = readwrite_gpg('', $inputfd, $stdoutfd, $stderrfd, $statusfd); |
| 330 |
|
waitpid $pid, 0; |
| 331 |
|
|
| 332 |
|
if ($stdout eq '') { |
| 333 |
|
warn ("No data from gpg for list-key\n"); # There should be at least 'tru:' everywhere. |
| 334 |
|
}; |
| 335 |
|
|
| 336 |
|
@keys = ($stdout =~ /^pub:[^r:]*:(?:[^:]*:){2,2}([^:]+):/mg); |
| 337 |
|
unless (scalar @keys) { |
| 338 |
|
info("Error: No keys were found using \"gpg --list-public-keys '$gecos'\"."); |
| 339 |
|
@keys = qw{0123456789abcdef 89abcdef76543210}; |
| 340 |
|
$Ckeys = '#'; |
| 341 |
|
} |
| 342 |
|
($email) = ($stdout =~ /^uid:.*<(.+?@.+?)>.*:/m); |
| 343 |
|
unless (defined $email) { |
| 344 |
|
info("Error: No email address was found using \"gpg --list-public-keys '$gecos'\"."); |
| 345 |
|
$email = $ENV{'LOGNAME'}.'@'.$hostname; |
| 346 |
|
$Cemail = '#'; |
| 347 |
|
} |
| 348 |
|
} else { |
| 349 |
|
$gecos = 'Unknown Caff User'; |
| 350 |
|
$email = $ENV{'LOGNAME'}.'@'.$hostname; |
| 351 |
|
@keys = qw{0123456789abcdef 89abcdef76543210}; |
| 352 |
|
($Cgecos,$Cemail,$Ckeys) = ('#','#','#'); |
| 353 |
|
}; |
| 354 |
|
|
| 355 |
|
return <<EOT; |
| 356 |
|
# .caffrc -- vim:syntax=perl: |
| 357 |
|
# This file is in perl(1) format - see caff(1) for details. |
| 358 |
|
|
| 359 |
|
$Cgecos\$CONFIG{'owner'} = '$gecos'; |
| 360 |
|
$Cemail\$CONFIG{'email'} = '$email'; |
| 361 |
|
|
| 362 |
|
# you can get your long keyid from |
| 363 |
|
# gpg --with-colons --list-key <yourkeyid|name|emailaddress..> |
| 364 |
|
# |
| 365 |
|
# if you have a v4 key, it will simply be the last 16 digits of |
| 366 |
|
# your fingerprint. |
| 367 |
|
# |
| 368 |
|
# Example: |
| 369 |
|
# \$CONFIG{'keyid'} = [ qw{FEDCBA9876543210} ]; |
| 370 |
|
# or, if you have more than one key: |
| 371 |
|
# \$CONFIG{'keyid'} = [ qw{0123456789ABCDEF 89ABCDEF76543210} ]; |
| 372 |
|
|
| 373 |
|
$Ckeys\$CONFIG{'keyid'} = [ qw{@keys} ]; |
| 374 |
|
EOT |
| 375 |
|
}; |
| 376 |
|
|
| 377 |
|
sub check_executable($$) { |
| 378 |
|
# (GnuPG::Interface gives lousy errors when the gpg binary isn't found, |
| 379 |
|
# so we want to check manually.) |
| 380 |
|
my ($purpose, $fn) = @_; |
| 381 |
|
# Only check provided fnames with a slash in them. |
| 382 |
|
return unless defined $fn; |
| 383 |
|
if ($fn =~ m!/!) { |
| 384 |
|
die ("$PROGRAM_NAME: $purpose executable '$fn' not found.\n") unless -x $fn; |
| 385 |
|
} else { |
| 386 |
|
for my $p (split(':', $ENV{PATH})) { |
| 387 |
|
return if -x "$p/$fn"; |
| 388 |
|
}; |
| 389 |
|
die ("$PROGRAM_NAME: $purpose executable '$fn' not found on path.\n") unless -x $fn; |
| 390 |
|
}; |
| 391 |
|
}; |
| 392 |
|
|
| 393 |
sub load_config() { |
sub load_config() { |
| 394 |
my $config = $ENV{'HOME'} . '/.caffrc'; |
my $config = $ENV{'HOME'} . '/.caffrc'; |
| 395 |
-f $config or die "No file $config present. See caff(1).\n"; |
unless (-f $config) { |
| 396 |
|
print "No configfile $config present, I will use this template:\n"; |
| 397 |
|
my $template = generate_config(); |
| 398 |
|
print "$template\nPlease edit $config and run caff again.\n"; |
| 399 |
|
open F, ">$config" or die "$config: $!"; |
| 400 |
|
print F $template; |
| 401 |
|
close F; |
| 402 |
|
exit(1); |
| 403 |
|
} |
| 404 |
unless (scalar eval `cat $config`) { |
unless (scalar eval `cat $config`) { |
| 405 |
die "Couldn't parse $config: $EVAL_ERROR\n" if $EVAL_ERROR; |
die "Couldn't parse $config: $EVAL_ERROR\n" if $EVAL_ERROR; |
| 406 |
}; |
}; |
| 407 |
|
|
| 408 |
$CONFIG{'caffhome'}=$ENV{'HOME'}.'/.caff' unless defined $CONFIG{'caffhome'}; |
$CONFIG{'caffhome'}=$ENV{'HOME'}.'/.caff' unless defined $CONFIG{'caffhome'}; |
| 409 |
die ("owner is not defined.\n") unless defined $CONFIG{'owner'}; |
die ("$PROGRAM_NAME: owner is not defined in $config.\n") unless defined $CONFIG{'owner'}; |
| 410 |
die ("email is not defined.\n") unless defined $CONFIG{'email'}; |
die ("$PROGRAM_NAME: email is not defined in $config.\n") unless defined $CONFIG{'email'}; |
| 411 |
die ("keyid is not defined.\n") unless defined $CONFIG{'keyid'}; |
die ("$PROGRAM_NAME: keyid is not defined in $config.\n") unless defined $CONFIG{'keyid'}; |
| 412 |
die ("keyid is not an array ref\n") unless (ref $CONFIG{'keyid'} eq 'ARRAY'); |
die ("$PROGRAM_NAME: keyid is not an array ref in $config.\n") unless (ref $CONFIG{'keyid'} eq 'ARRAY'); |
| 413 |
for my $keyid (@{$CONFIG{'keyid'}}) { |
for my $keyid (@{$CONFIG{'keyid'}}) { |
| 414 |
$keyid =~ /^[A-F0-9]{16}$/i or die ("key $keyid is not a long (16 digit) keyid.\n"); |
$keyid =~ /^[A-F0-9]{16}$/i or die ("$PROGRAM_NAME: key $keyid is not a long (16 digit) keyid in $config.\n"); |
| 415 |
}; |
}; |
| 416 |
@{$CONFIG{'keyid'}} = map { uc } @{$CONFIG{'keyid'}}; |
@{$CONFIG{'keyid'}} = map { uc } @{$CONFIG{'keyid'}}; |
| 417 |
$CONFIG{'export-sig-age'}= 24*60*60 unless defined $CONFIG{'export-sig-age'}; |
$CONFIG{'export-sig-age'}= 24*60*60 unless defined $CONFIG{'export-sig-age'}; |
| 419 |
$CONFIG{'gpg'} = 'gpg' unless defined $CONFIG{'gpg'}; |
$CONFIG{'gpg'} = 'gpg' unless defined $CONFIG{'gpg'}; |
| 420 |
$CONFIG{'gpg-sign'} = $CONFIG{'gpg'} unless defined $CONFIG{'gpg-sign'}; |
$CONFIG{'gpg-sign'} = $CONFIG{'gpg'} unless defined $CONFIG{'gpg-sign'}; |
| 421 |
$CONFIG{'gpg-delsig'} = $CONFIG{'gpg'} unless defined $CONFIG{'gpg-delsig'}; |
$CONFIG{'gpg-delsig'} = $CONFIG{'gpg'} unless defined $CONFIG{'gpg-delsig'}; |
| 422 |
|
check_executable("gpg", $CONFIG{'gpg'}); |
| 423 |
|
check_executable("gpg-sign", $CONFIG{'gpg-sign'}); |
| 424 |
|
check_executable("gpg-delsig", $CONFIG{'gpg-delsig'}); |
| 425 |
$CONFIG{'secret-keyring'} = $ENV{'HOME'}.'/.gnupg/secring.gpg' unless defined $CONFIG{'secret-keyring'}; |
$CONFIG{'secret-keyring'} = $ENV{'HOME'}.'/.gnupg/secring.gpg' unless defined $CONFIG{'secret-keyring'}; |
| 426 |
$CONFIG{'no-download'} = 0 unless defined $CONFIG{'no-download'}; |
$CONFIG{'no-download'} = 0 unless defined $CONFIG{'no-download'}; |
| 427 |
$CONFIG{'no-sign'} = 0 unless defined $CONFIG{'no-sign'}; |
$CONFIG{'no-sign'} = 0 unless defined $CONFIG{'no-sign'}; |
| 428 |
|
$CONFIG{'key-files'} = () unless defined $CONFIG{'key-files'}; |
| 429 |
$CONFIG{'mail-template'} = <<'EOM' unless defined $CONFIG{'mail-template'}; |
$CONFIG{'mail-template'} = <<'EOM' unless defined $CONFIG{'mail-template'}; |
| 430 |
Hi, |
Hi, |
| 431 |
|
|
| 450 |
EOM |
EOM |
| 451 |
}; |
}; |
| 452 |
|
|
|
sub notice($) { |
|
|
my ($line) = @_; |
|
|
print "[NOTICE] $line\n"; |
|
|
}; |
|
|
sub info($) { |
|
|
my ($line) = @_; |
|
|
print "[INFO] $line\n"; |
|
|
}; |
|
|
sub debug($) { |
|
|
my ($line) = @_; |
|
|
#print "[DEBUG] $line\n"; |
|
|
}; |
|
|
sub trace($) { |
|
|
my ($line) = @_; |
|
|
#print "[trace] $line\n"; |
|
|
}; |
|
|
sub trace2($) { |
|
|
my ($line) = @_; |
|
|
#print "[trace2] $line\n"; |
|
|
}; |
|
|
|
|
| 453 |
sub make_gpg_fds() { |
sub make_gpg_fds() { |
| 454 |
my %fds = ( |
my %fds = ( |
| 455 |
stdin => IO::Handle->new(), |
stdin => IO::Handle->new(), |
| 561 |
|
|
| 562 |
sub ask($$;$$) { |
sub ask($$;$$) { |
| 563 |
my ($question, $default, $forceyes, $forceno) = @_; |
my ($question, $default, $forceyes, $forceno) = @_; |
|
return $default if $forceyes and $forceno; |
|
|
return 1 if $forceyes; |
|
|
return 0 if $forceno; |
|
| 564 |
my $answer; |
my $answer; |
| 565 |
|
my $yn = $default ? '[Y/n]' : '[y/N]'; |
| 566 |
while (1) { |
while (1) { |
| 567 |
print $question,' ',($default ? '[Y/n]' : '[y/N]'), ' '; |
print $question,' ',$yn, ' '; |
| 568 |
|
if ($forceyes && $forceno) { |
| 569 |
|
print "$default (from config/command line)\n"; |
| 570 |
|
return $default; |
| 571 |
|
}; |
| 572 |
|
if ($forceyes) { |
| 573 |
|
print "YES (from config/command line)\n"; |
| 574 |
|
return 1; |
| 575 |
|
}; |
| 576 |
|
if ($forceno) { |
| 577 |
|
print "NO (from config/command line)\n"; |
| 578 |
|
return 0; |
| 579 |
|
}; |
| 580 |
|
|
| 581 |
$answer = <STDIN>; |
$answer = <STDIN>; |
| 582 |
|
if (!defined $answer) { |
| 583 |
|
$OUTPUT_AUTOFLUSH = 1; |
| 584 |
|
die "\n\n". |
| 585 |
|
"End of STDIN reached. Are you using xargs? Caff wants to read from STDIN,\n". |
| 586 |
|
"so you can't really use it with xargs. A patch against caff to read from\n". |
| 587 |
|
"the terminal would be appreciated.\n". |
| 588 |
|
"For now instead of cat keys | xargs caff do caff `cat keys`\n"; |
| 589 |
|
}; |
| 590 |
chomp $answer; |
chomp $answer; |
| 591 |
last if ((defined $answer) && (length $answer <= 1)); |
last if ((length $answer == 0) || ($answer =~ m/^[yYnN]$/) ); |
| 592 |
print "grrrrrr.\n"; |
print "What about $yn is so hard to understand?\nAnswer with either 'n' or 'y' or just press enter for the default.\n"; |
| 593 |
sleep 1; |
sleep 1; |
| 594 |
}; |
}; |
| 595 |
my $result = $default; |
my $result = $default; |
| 720 |
Type => "application/pgp-keys", |
Type => "application/pgp-keys", |
| 721 |
Disposition => 'attachment', |
Disposition => 'attachment', |
| 722 |
Encoding => "7bit", |
Encoding => "7bit", |
| 723 |
Description => "PGP Key 0x$key_id, uid ".($key->{'text'}).' ('.($key->{'serial'}).')', |
Description => "PGP Key 0x$key_id, uid ".($key->{'text'}).' ('.($key->{'serial'}).'), signed by 0x'.$CONFIG{'keyid'}[0], |
| 724 |
Data => $key->{'key'}, |
Data => $key->{'key'}, |
| 725 |
Filename => "0x$key_id.".$key->{'serial'}.".asc"); |
Filename => "0x$key_id.".$key->{'serial'}.".signed-by-0x".$CONFIG{'keyid'}[0].".asc"); |
| 726 |
}; |
}; |
| 727 |
|
|
| 728 |
if ($can_encrypt) { |
if ($can_encrypt) { |
| 747 |
$message = $stdout; |
$message = $stdout; |
| 748 |
|
|
| 749 |
$message_entity = MIME::Entity->build( |
$message_entity = MIME::Entity->build( |
| 750 |
Type => 'multipart/encrypted; protocol="application/pgp-encrypted"'); |
Type => 'multipart/encrypted; protocol="application/pgp-encrypted"', |
| 751 |
|
Encoding => '7bit'); |
| 752 |
|
|
| 753 |
$message_entity->attach( |
$message_entity->attach( |
| 754 |
Type => "application/pgp-encrypted", |
Type => "application/pgp-encrypted", |
| 767 |
$message_entity->head->add("Subject", "Your signed PGP key 0x$key_id"); |
$message_entity->head->add("Subject", "Your signed PGP key 0x$key_id"); |
| 768 |
$message_entity->head->add("To", $address); |
$message_entity->head->add("To", $address); |
| 769 |
$message_entity->head->add("From", '"'.$CONFIG{'owner'}.'" <'.$CONFIG{'email'}.'>'); |
$message_entity->head->add("From", '"'.$CONFIG{'owner'}.'" <'.$CONFIG{'email'}.'>'); |
| 770 |
|
$message_entity->head->add("Reply-To", $CONFIG{'reply-to'}) if defined $CONFIG{'reply-to'}; |
| 771 |
$message_entity->head->add("Bcc", $CONFIG{'bcc'}) if defined $CONFIG{'bcc'}; |
$message_entity->head->add("Bcc", $CONFIG{'bcc'}) if defined $CONFIG{'bcc'}; |
| 772 |
$message_entity->head->add("User-Agent", $USER_AGENT); |
$message_entity->head->add("User-Agent", $USER_AGENT); |
| 773 |
$message_entity->send(); |
$message_entity->send(); |
| 851 |
'--no-download' => \$params->{'no-download'}, |
'--no-download' => \$params->{'no-download'}, |
| 852 |
'-S' => \$params->{'no-sign'}, |
'-S' => \$params->{'no-sign'}, |
| 853 |
'--no-sign' => \$params->{'no-sign'}, |
'--no-sign' => \$params->{'no-sign'}, |
| 854 |
|
'--key-file=s@' => \$params->{'key-files'}, |
| 855 |
)) { |
)) { |
| 856 |
usage(\*STDERR, 1); |
usage(\*STDERR, 1); |
| 857 |
}; |
}; |
| 893 |
$CONFIG{'no-mail'} = $params->{'no-mail'} if defined $params->{'no-mail'}; |
$CONFIG{'no-mail'} = $params->{'no-mail'} if defined $params->{'no-mail'}; |
| 894 |
$CONFIG{'mail'} = $params->{'mail'} if defined $params->{'mail'}; |
$CONFIG{'mail'} = $params->{'mail'} if defined $params->{'mail'}; |
| 895 |
$CONFIG{'no-sign'} = $params->{'no-sign'} if defined $params->{'no-sign'}; |
$CONFIG{'no-sign'} = $params->{'no-sign'} if defined $params->{'no-sign'}; |
| 896 |
|
push @{$CONFIG{'key-files'}}, @{$params->{'key-files'}} if defined $params->{'key-files'}; |
| 897 |
|
|
| 898 |
|
|
| 899 |
################# |
################# |
| 929 |
} |
} |
| 930 |
} |
} |
| 931 |
|
|
| 932 |
|
######################## |
| 933 |
|
# import keys from files |
| 934 |
|
######################## |
| 935 |
|
foreach my $keyfile (@{$CONFIG{'key-files'}}) { |
| 936 |
|
my $gpg = GnuPG::Interface->new(); |
| 937 |
|
$gpg->call( $CONFIG{'gpg'} ); |
| 938 |
|
$gpg->options->hash_init('homedir' => $GNUPGHOME); |
| 939 |
|
$gpg->options->meta_interactive( 0 ); |
| 940 |
|
my ($inputfd, $stdoutfd, $stderrfd, $statusfd, $handles) = make_gpg_fds(); |
| 941 |
|
my $pid = $gpg->import_keys(handles => $handles, command_args => $keyfile); |
| 942 |
|
my ($stdout, $stderr, $status) = readwrite_gpg('', $inputfd, $stdoutfd, $stderrfd, $statusfd); |
| 943 |
|
info ("Importing keys from $keyfile"); |
| 944 |
|
waitpid $pid, 0; |
| 945 |
|
if ($status !~ /^\[GNUPG:\] IMPORT_OK/m) { |
| 946 |
|
warn $stderr; |
| 947 |
|
} |
| 948 |
|
} |
| 949 |
|
|
| 950 |
############################# |
############################# |
| 951 |
# receive keys from keyserver |
# receive keys from keyserver |
| 952 |
############################# |
############################# |
| 972 |
# [GNUPG:] NODATA 1 |
# [GNUPG:] NODATA 1 |
| 973 |
# [GNUPG:] IMPORT_OK 0 25FC1614B8F87B52FF2F99B962AF4031C82E0039 |
# [GNUPG:] IMPORT_OK 0 25FC1614B8F87B52FF2F99B962AF4031C82E0039 |
| 974 |
my %local_keyids = map { $_ => 1 } @KEYIDS; |
my %local_keyids = map { $_ => 1 } @KEYIDS; |
| 975 |
|
my $had_v3_keys = 0; |
| 976 |
for my $line (split /\n/, $status) { |
for my $line (split /\n/, $status) { |
| 977 |
if ($line =~ /^\[GNUPG:\] IMPORT_OK \d+ ([0-9A-F]{40})/) { |
if ($line =~ /^\[GNUPG:\] IMPORT_OK \d+ ([0-9A-F]{40})/) { |
| 978 |
my $imported_key = $1; |
my $imported_key = $1; |
| 991 |
delete $local_keyids{$speced_key}; |
delete $local_keyids{$speced_key}; |
| 992 |
unshift @keyids_ok, $imported_key; |
unshift @keyids_ok, $imported_key; |
| 993 |
} elsif ($line =~ /^\[GNUPG:\] (NODATA|IMPORT_RES|IMPORTED) /) { |
} elsif ($line =~ /^\[GNUPG:\] (NODATA|IMPORT_RES|IMPORTED) /) { |
| 994 |
|
} elsif ($line =~ /^\[GNUPG:\] IMPORT_OK \d+ ([0-9A-F]{32})/) { |
| 995 |
|
my $imported_key = $1; |
| 996 |
|
notice ("Imported key $1 is a version 3 key. Version 3 keys are obsolete, should not be used, and are not and will not be properly supported."); |
| 997 |
|
$had_v3_keys = 1; |
| 998 |
} else { |
} else { |
| 999 |
notice ("got unknown reply from gpg: $line"); |
notice ("got unknown reply from gpg: $line"); |
| 1000 |
} |
} |
| 1001 |
}; |
}; |
| 1002 |
if (scalar %local_keyids) { |
if (scalar %local_keyids) { |
| 1003 |
notice ("Import failed for: ". (join ' ', keys %local_keyids)."."); |
notice ("Import failed for: ". (join ' ', keys %local_keyids)."." . ($had_v3_keys ? " (Or maybe it's one of those ugly v3 keys?)" : "")); |
| 1004 |
exit 1 unless ask ("Some keys could not be imported - continue anyway?", 0); |
exit 1 unless ask ("Some keys could not be imported - continue anyway?", 0); |
| 1005 |
} |
} |
| 1006 |
}; |
}; |
| 1252 |
if (!$uid->{'is_uat'} && ($uid->{'text'} =~ /@/)) { |
if (!$uid->{'is_uat'} && ($uid->{'text'} =~ /@/)) { |
| 1253 |
my $address = $uid->{'text'}; |
my $address = $uid->{'text'}; |
| 1254 |
$address =~ s/.*<(.*)>.*/$1/; |
$address =~ s/.*<(.*)>.*/$1/; |
| 1255 |
if (ask("Send signature for $uid->{'text'} to '$address'?", 1, $CONFIG{'mail'})) { |
if (ask("Mail signature for $uid->{'text'} to '$address'?", 1, $CONFIG{'mail'})) { |
| 1256 |
my $mail = send_mail($address, $can_encrypt, $longkeyid, $uid, @attached); |
my $mail = send_mail($address, $can_encrypt, $longkeyid, $uid, @attached); |
| 1257 |
|
|
| 1258 |
my $keydir = "$KEYSBASE/$DATE_STRING"; |
my $keydir = "$KEYSBASE/$DATE_STRING"; |