[Pgp-tools-commit] r790 - in trunk: caff debian

Guilhem Moulin guilhem-guest at moszumanska.debian.org
Fri Feb 20 19:37:15 UTC 2015


Author: guilhem-guest
Date: 2015-02-20 19:37:15 +0000 (Fri, 20 Feb 2015)
New Revision: 790

Modified:
   trunk/caff/caff
   trunk/debian/changelog
Log:
caff: Fix $CONFIG{'also-lsign-in-gnupghome'}

Local signatures are directly imported from caff's GNUPGHOME to our own;
in auto-lsign'ing mode, lsign UID for which we have an exportable
signature (preserving the signer and cert level).

Modified: trunk/caff/caff
===================================================================
--- trunk/caff/caff	2015-02-20 19:37:09 UTC (rev 789)
+++ trunk/caff/caff	2015-02-20 19:37:15 UTC (rev 790)
@@ -976,14 +976,19 @@
 	return $good_uid;
 };
 
-sub delete_signatures($$$$) {
-	my ($handles, $longkeyid, $uid, $keyids) = @_;
+# Delete all non self-sigs that are not made by one of the @$keyids, and
+# return the date of the most recent signature and a hash reference
+# {$signer => $level} of the keys in @$keyids that have an exportable
+# signature on that $uid.  If $keep_lsigs_only, our exportable
+# signatures are removed as well.
+sub delete_signatures($$$$;$) {
+	my ($handles, $longkeyid, $uid, $keyids, $keep_lsigs_only) = @_;
 
 	readwrite_gpg($handles, command => "uid 0",    status => $KEYEDIT_PROMPT); # unmark all uids from delsig
 	readwrite_gpg($handles, command => "uid $uid", status => $KEYEDIT_PROMPT); # mark $uid for delsig
 
 	my $last_signed_on = 0;
-	my %signers;
+	my %xsigners;
 
 	my %output = readwrite_gpg($handles, command => "delsig", status => $KEYEDIT_DELSIG_PROMPT);
 
@@ -996,7 +1001,7 @@
 		}
 		else { # only if we found a sig here - we never remove revocation packets for instance
 			my $sig = pop @sigline;
-			$sig =~ /^sig:(?:[^:]*:){3}([0-9A-F]{16}):(\d+):(?:[^:]*:){4}(1[0-3]|30)[lx](?::.*)?$/ or
+			$sig =~ /^sig:(?:[^:]*:){3}([0-9A-F]{16}):(\d+):(?:[^:]*:){4}(1[0-3]|30)([lx])(?::.*)?$/ or
 				mywarn("I hit a bug, please report: Couldn't parse sigline $sig");
 			debug("[sigremoval] doing sigline $sig");
 			if ($1 eq $longkeyid) {
@@ -1004,9 +1009,9 @@
 				$answer = "no";
 			} elsif (grep { $1 eq $_ } @$keyids and $3 != 30) {
 				debug("[sigremoval] signed by us ($1)");
-				$answer = "no";
+				$answer = ($keep_lsigs_only and $4 eq 'x') ? "yes" : "no";
 				$last_signed_on = $2 if $last_signed_on < $2;
-				$signers{$1} = $3-10;
+				$xsigners{$1} = $3-10 if $4 eq 'x';
 			} else {
 				debug("[sigremoval] not interested in that sig ($1)");
 				$answer = "yes";
@@ -1014,10 +1019,10 @@
 			mywarn("I hit a bug, please report: Found the following ".($#sigline+2)." siglines in that part of the dialog:\n".$output{stdout}) if @sigline;
 		}
 		%output = readwrite_gpg($handles, command => $answer, status => $KEYEDIT_KEYEDIT_OR_DELSIG_PROMPT);
-	};
+	}
 
-	return ($last_signed_on, \%signers);
-};
+	return ($last_signed_on, \%xsigners);
+}
 
 ##
 # Check the local user keys.
@@ -1081,6 +1086,7 @@
 
 	my @extra_args;
 	push @import_options, 'import-local-sigs' if $CONFIG{'gpg-sign-type'} =~ /l/ and !grep /import-local-sigs$/, @import_options;
+	push @import_options, 'keep-ownertrust' unless defined $dst_gpghome or $GNUPG_VERSION >= 2.1; # don't modify our own trustdb
 	push @extra_args, '--min-cert-level=1' if grep { $_ eq 'import-clean' } @import_options;
 	push @extra_args, '--import-options', join (',', @import_options) if @import_options;
 
@@ -1598,7 +1604,7 @@
 		# delete signatures
 		###################
 		# this shouldn't delete anything as $longkeyid is already clean, but maybe we didn't sign that uid with all keys in @{$CONFIG{'keyid'}}
-		my ($last_signed_on, $signers) = delete_signatures($handles, $longkeyid, $uid->{hash}, $CONFIG{'keyid'});
+		my ($last_signed_on, $xsigners) = delete_signatures($handles, $longkeyid, $uid->{hash}, $CONFIG{'keyid'});
 
 		delete_signatures($handles, $longkeyid, $first_uid->{hash}, [])
 			if $uid->{type} ne 'uid'; # delete all sigs on the first UID if $uid is an attribute
@@ -1620,88 +1626,98 @@
 			# it's a bit inefficient to store the $asciikey in memory,
 			# but it has been pruned so it's shouldn't be too big
 			$uid->{key} = $asciikey;
-			$uid->{signers} = $signers;
+			$uid->{xsigners} = $xsigners;
 			$uid->{last_signed_on} = $last_signed_on;
 		};
 	};
+
+
+	unless ($CONFIG{'also-lsign-in-gnupghome'} eq 'no') {
+		# remove all exportable sigs, and import into our GnuPGHOME
+		###########################################################
+		my $gpg = mkGnuPG( homedir => $keydir, extra_args => ['--with-colons'] );
+		my $handles = mkGnuPG_fds( command => undef, stdout => undef, status => undef );
+		my $pid = $gpg->wrap_call(
+			commands     => [ '--edit-key' ],
+			command_args => [ $keyid ],
+			handles      => $handles );
+
+		debug("Starting edit session on $keyid");
+		my %output = readwrite_gpg($handles, status => $KEYEDIT_PROMPT);
+		delete_signatures($handles, $longkeyid, $uids[$_]->{hash}, $CONFIG{'keyid'}, 1) foreach (0 .. $#uids);
+
+		readwrite_gpg($handles, command => "save");
+		done_gpg($pid, $handles);
+		debug("Done editing");
+
+		# import the pruned keys with our own local sigs only; this is
+		# required even if there are no lsigs, to ensure we've got all
+		# UIDs in our own GnuPGHOME
+		import_keys_from_gnupghome( [$keyid], $keydir, undef, 'import-local-sigs' );
+	}
 	undef $keydir; # delete dir
 
-	if ($CONFIG{'also-lsign-in-gnupghome'} ne 'no') {
-		###############################
-		# add non-exportable signatures
-		###############################
-
-		import_keys_from_gnupghome( [ $keyid ], $GNUPGHOME, undef,
-									# do not export our own exportable signatures, but ensure we've got the same UID list
-									$CONFIG{'gpg-sign-type'} =~ /l/ ? () : 'export-minimal' );
-		if ( $CONFIG{'gpg-sign-type'} =~ /l/ ) {
-			# we've copied the (local) signature to our GnuPHOME and we're done
+	if ($CONFIG{'also-lsign-in-gnupghome'} eq 'ask') {
+		# manually lsign the key
+		########################
+		foreach my $local_user (@LOCAL_USER) {
+			my @command = ($CONFIG{'gpg'});
+			push @command, '--local-user', $local_user;
+			push @command, '--secret-keyring', $CONFIG{'secret-keyring'};
+			push @command, qw/--no-auto-check-trustdb --trust-model=always/;
+			push @command, '--edit-key', $keyid;
+			push @command, 'showphoto' if $CONFIG{'show-photos'};
+			push @command, 'lsign';
+			push @command, split ' ', $CONFIG{'gpg-sign-args'} || "";
+			print join(' ', @command),"\n";
+			mysystem(@command);
 		}
-		elsif ( $CONFIG{'also-lsign-in-gnupghome'} ne 'auto' ) {
-			# manually lsign the key
-			########################
-			foreach my $local_user (@LOCAL_USER) {
-				my @command = ($CONFIG{'gpg'});
-				push @command, '--local-user', $local_user;
-				push @command, '--secret-keyring', $CONFIG{'secret-keyring'};
-				push @command, qw/--no-auto-check-trustdb --trust-model=always/;
-				push @command, '--edit-key', $keyid;
-				push @command, 'showphoto' if $CONFIG{'show-photos'};
-				push @command, 'lsign';
-				push @command, split ' ', $CONFIG{'gpg-sign-args'} || "";
-				print join(' ', @command),"\n";
-				mysystem(@command);
-			};
-		}
-		else {
-			# auto lsign the relevant uids
-			##############################
-			my @uids = grep {$_->{last_signed_on}} @{$KEYS{$keyid}->{uids}};
-			my @signers = map {keys %{$_->{signers}}} @uids;
-			if (@LOCAL_USER && defined $LOCAL_USER[0]) {
-				# which of @LOCAL_USER has signed at least one UID in this key?
-				@signers = grep { my $u = $_; grep { $u eq $_ } @signers } @LOCAL_USER;
-			} else {
-				# no @LOCAL_USER was defined; remove duplicates to avoid double signing
-				@signers = keys %{{ map { $_ => 1 } @signers }}
-			};
+	}
+	elsif ($CONFIG{'also-lsign-in-gnupghome'} eq 'auto') {
+		# auto lsign the uids we for which we have an exportable sig
+		############################################################
+		my @uids = grep {exists $_->{xsigners}} @{$KEYS{$keyid}->{uids}};
+		my @signers = map {keys %{$_->{xsigners}}} @uids;
+		# which of @LOCAL_USER has signed at least one UID in this key?
+		@signers = grep { my $u = $_; grep { $u eq $_ } @signers } @LOCAL_USER;
+		@signers = keys %{{ map { $_ => 1 } @signers }}; # remove duplicates to avoid double signing
 
-			foreach my $u (@signers) {
-				my @signeduids; # uids signed by $u
-				foreach my $uid (@uids) {
-					# we use UIDs hashes to distinguish and select UIDs; it's the only reliable way to identify them accross keyrings
-					push @signeduids, $uid if grep { $u eq $_ } (keys %{$uid->{signers}}) and
-											 !grep { $uid->{hash} eq $_->{hash} } @signeduids;
-				}
+		foreach my $u (@signers) {
+			my @signeduids; # uids signed by $u
+			foreach my $uid (@uids) {
+				# we use UIDs hashes to distinguish and select UIDs; it's the only reliable way to identify them accross keyrings
+				push @signeduids, $uid if grep { $u eq $_ } (keys %{$uid->{xsigners}}) and
+										 !grep { $uid->{hash} eq $_->{hash} } @signeduids;
+			}
 
-				my $gpg = mkGnuPG( extra_args => ['--local-user' => $u, '--ask-cert-level'] );
-				$gpg->options->push_extra_args('--secret-keyring', $CONFIG{'secret-keyring'}) if $GNUPG_VERSION < 2.1;
-				$gpg->options->push_extra_args('--use-agent') if $GNUPG_VERSION < 2.0; # we know there is a working agent
-				my $handles = mkGnuPG_fds( command => undef, stdout => undef, status => undef );
-				my $pid = $gpg->wrap_call(
-					commands     => [ '--edit-key' ],
-					command_args => [ $keyid ],
-					handles      => $handles );
+			my $gpg = mkGnuPG( extra_args => ['--local-user' => $u, '--ask-cert-level', '--with-colons', '--no-batch'] );
+			$gpg->options->push_extra_args('--secret-keyring', $CONFIG{'secret-keyring'}) if $GNUPG_VERSION < 2.1;
+			$gpg->options->push_extra_args('--use-agent') if $GNUPG_VERSION < 2.0; # we know there is a working agent
+			my $handles = mkGnuPG_fds( command => undef, stdout => undef, status => undef );
+			my $pid = $gpg->wrap_call(
+				commands     => [ '--edit-key' ],
+				command_args => [ $keyid ],
+				handles      => $handles );
 
-				debug("Starting edit session on $keyid, signer $u");
-				readwrite_gpg($handles, status => $KEYEDIT_PROMPT);
+			debug("Starting edit session on $keyid, signer $u");
+			readwrite_gpg($handles, status => $KEYEDIT_PROMPT);
 
-				foreach my $level (0..3) {
-					my @signeduids_with_level = grep {$_->{signers}->{$u} eq $level} @signeduids;
-					next unless @signeduids_with_level;
+			foreach my $level (0..3) {
+				my @signeduids_with_level = grep {$_->{xsigners}->{$u} eq $level} @signeduids;
+				next unless @signeduids_with_level;
 
-					notice("lsign-ing (by $u) with cert level $level uid(s) #".(join ',', sort (map {$_->{serial}} @signeduids_with_level))." of $longkeyid", 1);
-					readwrite_gpg($handles, command => "uid 0",          status => $KEYEDIT_PROMPT);
-					readwrite_gpg($handles, command => "uid $_->{hash}", status => $KEYEDIT_PROMPT) for @signeduids_with_level;
-					my %output = readwrite_gpg($handles, command => "lsign", statusmatches => qr/$KEYEDIT_SIGNUID_CLASS_PROMPT|$KEYEDIT_PROMPT/);
-					next if $output{status} =~ /^\[GNUPG:\] $KEYEDIT_PROMPT/m; # already signed
-					readwrite_gpg($handles, command => $level, status => $KEYEDIT_SIGNUID_PROMPT);
-					readwrite_gpg($handles, command => "yes",  status => $KEYEDIT_PROMPT);
-				}
+				notice("Key $longkeyid UID(s) #".(join ',', sort (map {$_->{serial}} @signeduids_with_level)).": lsign'ing with $u, cert level $level", 1);
+				readwrite_gpg($handles, command => "uid 0",          status => $KEYEDIT_PROMPT); # unselect UIDs
+				readwrite_gpg($handles, command => "uid $_->{hash}", status => $KEYEDIT_PROMPT) for @signeduids_with_level;
+				my %output = readwrite_gpg($handles, command => "lsign", status => qr/$KEYEDIT_SIGNUID_CLASS_PROMPT|$KEYEDIT_PROMPT/);
+				next if $output{status} =~ /^\[GNUPG:\] $KEYEDIT_PROMPT/m; # already signed
+				readwrite_gpg($handles, command => $level, status => $KEYEDIT_SIGNUID_PROMPT);
+				readwrite_gpg($handles, command => "yes",  status => $KEYEDIT_PROMPT);
+			}
 
-				readwrite_gpg($handles, command => "save");
-				done_gpg($pid, $handles);
-			}
+			readwrite_gpg($handles, command => "save");
+			done_gpg($pid, $handles);
+			debug("Done editing");
 		}
 	}
 }

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog	2015-02-20 19:37:09 UTC (rev 789)
+++ trunk/debian/changelog	2015-02-20 19:37:15 UTC (rev 790)
@@ -20,6 +20,10 @@
       attribute, for instance.
     + Use Term::ANSIColor to produce colored output.
     + Prune keys with import-{clean,minimal} not export-{clean,minimal}.
+    + Fix $CONFIG{'also-lsign-in-gnupghome'}: local signatures are directly
+      imported from caff's GNUPGHOME to our own; in auto-lsign'ing mode, lsign
+      UID for which we have an exportable signature (preserving the signer and
+      cert level).
   * gpgsigs:
     + Add a legend with the different signature types.
     + Mark local signatures as 'L' (formerly they were marked as 'S'), and




More information about the Pgp-tools-commit mailing list