/[pgp-tools]/trunk/caff/caff
ViewVC logotype

Diff of /trunk/caff/caff

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 133 by weasel, Tue Jul 19 16:50:48 2005 UTC revision 266 by weasel, Wed Mar 1 15:01:44 2006 UTC
# Line 50  CA Fire and Forget is a script that help Line 50  CA Fire and Forget is a script that help
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    
# Line 85  Do not sign the keys. Line 86  Do not sign the keys.
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
# Line 93  Select the key that is used for signing, Line 98  Select the key that is used for signing,
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    
# Line 169  Keyserver to download keys from.  Defaul Line 183  Keyserver to download keys from.  Defaul
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]
# Line 218  The UIDs for which signatures are includ Line 236  The UIDs for which signatures are includ
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.
# Line 239  Default: none. Line 261  Default: none.
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;
# Line 258  my $REVISION = '$Rev$'; Line 284  my $REVISION = '$Rev$';
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'};
# Line 279  sub load_config() { Line 419  sub load_config() {
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    
# Line 306  Regards, Line 450  Regards,
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(),
# Line 438  sub readwrite_gpg($$$$$%) { Line 561  sub readwrite_gpg($$$$$%) {
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;
# Line 578  sub send_mail($$$@) { Line 720  sub send_mail($$$@) {
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) {
# Line 605  sub send_mail($$$@) { Line 747  sub send_mail($$$@) {
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",
# Line 624  sub send_mail($$$@) { Line 767  sub send_mail($$$@) {
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();
# Line 707  if (!GetOptions ( Line 851  if (!GetOptions (
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  };  };
# Line 748  $CONFIG{'no-download'} = $params->{'no-d Line 893  $CONFIG{'no-download'} = $params->{'no-d
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  #################  #################
# Line 783  for my $keyid (@{$CONFIG{'keyid'}}) { Line 929  for my $keyid (@{$CONFIG{'keyid'}}) {
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  #############################  #############################
# Line 808  if ($CONFIG{'no-download'}) { Line 972  if ($CONFIG{'no-download'}) {
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;
# Line 826  if ($CONFIG{'no-download'}) { Line 991  if ($CONFIG{'no-download'}) {
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  };  };
# Line 1083  for my $keyid (@keyids_ok) { Line 1252  for my $keyid (@keyids_ok) {
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";

Legend:
Removed from v.133  
changed lines
  Added in v.266

  ViewVC Help
Powered by ViewVC 1.1.5