caff: Make importing of keys to be signed from the normal gpg optional (--keys-from...
[pgp-tools.git] / caff / caff
index 9378562164c4c916d1a46e72119ce6372d183a1c..11655a4dcc2a3fd8f8269ea97981abd72a535304 100755 (executable)
--- a/caff/caff
+++ b/caff/caff
@@ -90,6 +90,10 @@ configuration file.
 
 Import keys from file. Can be supplied more than once.
 
+=item B<--keys-from-gnupg> I<file>
+
+Try to import keys from your standard GnuPG keyrings.
+
 =back
 
 =head1 FILES
@@ -305,7 +309,7 @@ http://pgp-tools.alioth.debian.org/
 
 =head1 SEE ALSO
 
-gpg(1), pgp-clean(1), /usr/share/doc/signing-party/caff/caffrc.sample.
+gpg(1), pgp-clean(1), /usr/share/doc/signing-party/caff/
 
 =cut
 
@@ -325,8 +329,12 @@ use GnuPG::Interface;
 my %CONFIG;
 my $REVISION = '$Rev$';
 my ($REVISION_NUMER) = $REVISION =~ /(\d+)/;
+$REVISION_NUMER = 'unknown' unless defined $REVISION_NUMER;
 my $VERSION = "0.0.0.$REVISION_NUMER";
 
+# Global variables
+my @KEYIDS;
+my $params;
 
 ##
 # Display an error message on STDERR and then exit.
@@ -907,15 +915,13 @@ sub delete_signatures($$$$$$) {
 # Check the local user keys.
 #
 # This function checks if the keyids defined through the --local-user
-# command line option or set in .caffrc are valid and known to be one of the
-# keyids listed in ./caffrc. The last check ensure we have those keyids
-# available in the caff's gnupghome directory.
+# command line option or set in ~/.caffrc are valid and known to be one of the
+# keyids listed in ~/.caffrc.
 #
 # @return an array containing the local user keys\n
-#         (undef) if no key has been specified
+#         (undef) if no valid key has been found
 #
-sub get_local_user_keys()
-{
+sub get_local_user_keys() {
        my @local_user = ();
        my @key_list;
        
@@ -945,7 +951,7 @@ sub get_local_user_keys()
                }
                
                unless (grep (/$user_key$/, @{$CONFIG{'keyid'}})) {
-                       mywarn "Local-user $user_key is not defined as one of your keyid in ./caffrc (it will not be used).";
+                       mywarn "Local-user $user_key is not defined as one of your keyid in ~/.caffrc (it will not be used).";
                        next;
                }
                
@@ -954,19 +960,108 @@ sub get_local_user_keys()
 
        # If no local-user key are valid, there is no need to go further
        unless (defined $local_user[0]) {
-               myerror (1, "None of the local-user keys seem to be known as a keyid listed in ./caffrc.");
+               myerror (1, "None of the local-user keys seem to be known as a keyid listed in ~/.caffrc.");
        }
 
        return @local_user;
 }
 
+##
+# Import a key from the user gnupghome into a specified gnupghome.
+#
+# @param asciikey      ascii format of the gpg key to import
+# @param dst_gnupghome gnupghome directory where to import the key
+#
+# @return 0 if successful\n
+#         1 if the key could not be exported.\n
+#         2 if the key could not be imported.
+#
+sub import_key_from_user_gnupghome($$) {
+       my $err;
+       my ($asciikey, $dst_gpghome) = @_;
+
+       trace("Exporting key $asciikey from your normal GnuPGHOME.");
+       my $key = export_key(undef, $asciikey);
+       if (defined $key && $key ne '') {
+               trace("Importing key $asciikey into $GNUPGHOME.");
+               if (import_key($GNUPGHOME, $key)) {
+                       $err = 0;
+               } else {
+                       warn("Could not import $asciikey into caff's gnupghome.");
+                       $err = 2;
+               }
+       } else {
+               $err = 1;
+       }
+
+       return $err;
+}
+
+##
+# Import a key file into a specified gnupghome.
+#
+# @param keyfile       file containing the keys to import
+# @param dst_gnupghome gnupghome directory where to import the key
+#
+# @return 0 if successful\n
+#         1 if an error occured.
+#
+sub import_key_files($$) {
+       my $err;
+       my ($keyfile, $dst_gpghome) = @_;
+
+       my $gpg = GnuPG::Interface->new();
+       $gpg->call( $CONFIG{'gpg'} );
+       $gpg->options->hash_init(
+               'homedir' => $dst_gpghome,
+               'extra_args' => [ qw{ --no-auto-check-trustdb --trust-model=always } ] );
+       $gpg->options->meta_interactive( 0 );
+       my ($inputfd, $stdoutfd, $stderrfd, $statusfd, $handles) = make_gpg_fds();
+       my $pid = $gpg->import_keys(handles => $handles, command_args => $keyfile);
+       my ($stdout, $stderr, $status) = readwrite_gpg('', $inputfd, $stdoutfd, $stderrfd, $statusfd);
+       info("Importing keys from file $keyfile");
+       waitpid $pid, 0;
+
+       if ($status !~ /^\[GNUPG:\] IMPORT_OK/m) {
+               warn $stderr;
+               $err = 1;
+       } else {
+               $err = 0;
+       }
+
+       return $err;
+}
+
+##
+# Import keys to be signed into caff gnupghome directory.
+#
+# This function imports the keys the user wants to sign into the caff gnupghome
+# directory. We looks for the keys in the the user gnupghome directory first,
+# and in the key files specified by the user if not all of the keys have been
+# found.
+#
+sub import_keys_to_sign() {
+       # Check if we can find the gpg key from our normal gnupghome, and then
+       # try to import it into our working gnupghome directory
+       if ($CONFIG{'keys-from-gnupg'}) {
+               foreach my $keyid (@KEYIDS) {
+                       if (!import_key_from_user_gnupghome($keyid, $GNUPGHOME)) {
+                               info("Key $keyid imported from your normal GnuPGHOME.");
+                       }
+               }
+       };
+
+       # Import user specified key files
+       foreach my $keyfile (@{$CONFIG{'key-files'}}) {
+               import_key_files($keyfile, $GNUPGHOME);
+       }
+
+       return 0;
+}
 
 ###################
 # argument handling
 ###################
-my @KEYIDS;
-my $params;
-
 Getopt::Long::config('bundling');
 if (!GetOptions (
        '-h'              =>  \$params->{'help'},
@@ -988,6 +1083,7 @@ if (!GetOptions (
        '-S'              =>  \$params->{'no-sign'},
        '--no-sign'       =>  \$params->{'no-sign'},
        '--key-file=s@'   =>  \$params->{'key-files'},
+       '--keys-from-gnupg' =>  \$params->{'keys-from-gnupg'},
        )) {
        usage(\*STDERR, 1);
 };
@@ -1007,6 +1103,8 @@ $CONFIG{'no-sign'}     = $params->{'no-sign'}     if defined $params->{'no-sign'
 $CONFIG{'no-mail'}     = $params->{'no-mail'}     if defined $params->{'no-mail'};
 $CONFIG{'mail'}        = $params->{'mail'}        if defined $params->{'mail'};
 
+$CONFIG{'keys-from-gnupg'} = $params->{'keys-from-gnupg'} if defined $params->{'keys-from-gnupg'};
+
 # If old 'no-mail' parameter, or if the 'mail' parameter is set to 'no'
 if ( defined $CONFIG{'no-mail'} || 
      ( defined $CONFIG{'mail'} && $CONFIG{'mail'}  eq 'no' ) ) {
@@ -1036,36 +1134,13 @@ for my $keyid (map { split /\n/ } @ARGV) { # caff "`cat txt`" is a single argume
 # import own keys
 #################
 for my $keyid (@{$CONFIG{'keyid'}}) {
-               info("Importing key $keyid from your normal GnuPGHome.");
-               my $key = export_key(undef, $keyid);
-               if (!defined $key || $key eq '') {
-                       warn ("Did not get key $keyid from your normal GnuPGHome\n");
-                       next;
-               };
-               my $result = import_key($GNUPGHOME, $key);
-               unless ($result) {
-                       warn ("Could not import $keyid into caff's gnupghome.\n");
-                       next;
-               };
+       info("Importing key $keyid from your normal GnuPGHome.");
+       if (import_key_from_user_gnupghome($keyid, $GNUPGHOME)) {
+               mywarn("Key $keyid not found.");
+       }
 }
 
-########################
-# import keys from files
-########################
-foreach my $keyfile (@{$CONFIG{'key-files'}}) {
-    my $gpg = GnuPG::Interface->new();
-    $gpg->call( $CONFIG{'gpg'} );
-    $gpg->options->hash_init('homedir' => $GNUPGHOME);
-    $gpg->options->meta_interactive( 0 );
-    my ($inputfd, $stdoutfd, $stderrfd, $statusfd, $handles) = make_gpg_fds();
-    my $pid = $gpg->import_keys(handles => $handles, command_args => $keyfile);
-    my ($stdout, $stderr, $status) = readwrite_gpg('', $inputfd, $stdoutfd, $stderrfd, $statusfd);
-    info ("Importing keys from $keyfile");
-    waitpid $pid, 0;
-    if ($status !~ /^\[GNUPG:\] IMPORT_OK/m) {
-       warn $stderr;
-    }
-}
+&import_keys_to_sign();
 
 #############################
 # receive keys from keyserver
@@ -1143,9 +1218,8 @@ if ($CONFIG{'ask-sign'} && ! $CONFIG{'no-sign'}) {
        $CONFIG{'no-sign'} = ! ask("Continue with signing?", 1);
 }
        
-unless ($CONFIG{'no-sign'})
-{
-       my @local_user = &get_local_user_keys();
+unless ($CONFIG{'no-sign'}) {
+       my @local_user = get_local_user_keys();
 
        info("Sign the following keys according to your policy, then exit gpg with 'save' after signing each key");
        for my $keyid (@keyids_ok) {