exported subkeys are now merged into one output keyblock

This commit is contained in:
Werner Koch 2005-10-17 17:21:15 +00:00
parent 21eea5be5e
commit 9b7f1f6976
8 changed files with 272 additions and 125 deletions

3
NEWS
View File

@ -17,6 +17,9 @@ Noteworthy changes in version 1.4.3
associate a mail address with an OpenPGP key. See: XXXX for a
description.
* When exporting subkeys, those specified with a key ID or
fingerpint and the '!' suffix are now merged into one keyblock.
* Added "gpg-zip", a program to create encrypted archives that can
interoperate with PGP Zip.

1
THANKS
View File

@ -145,6 +145,7 @@ Michael Roth mroth@nessie.de
Michael Sobolev mss@despair.transas.com
Michael Tokarev mjt@tls.msk.ru
Nicolas Graner Nicolas.Graner@cri.u-psud.fr
Mike Dowling ML.Dowling at tu-bs.de
Mike McEwan mike@lotusland.demon.co.uk
Neal H Walfield neal@cs.uml.edu
Nelson H. F. Beebe beebe@math.utah.edu

View File

@ -1,3 +1,7 @@
2005-10-07 Werner Koch <wk@g10code.com>
* gpgv.sgml: Small spelling corrections by Mike Dowling.
2005-09-21 David Shaw <dshaw@jabberwocky.com>
* gpg.sgml: Note that --display-charset is just for display and

View File

@ -322,21 +322,15 @@ the preferences in effect by including the implied preferences of
are not already included in the preference list.
@item setpref @code{string}
Set the list of user ID preferences to @code{string}, this should be a
string similar to the one printed by "pref". Using an empty string
will set the default preference string, using "none" will remove the
preferences. Use "gpg --version" to get a list of available
algorithms. This command just initializes an internal list and does
not change anything unless another command (such as "updpref") which
changes the self-signatures is used.
@item updpref
Change the preferences of all user IDs (or just of the selected ones
to the current list of preferences. The timestamp of all affected
self-signatures will be advanced by one second. Note that while you
can change the preferences on an attribute user ID (aka "photo ID"),
GnuPG does not select keys via attribute user IDs so these preferences
will not be used by GnuPG.
Set the list of user ID preferences to @code{string} for all (or just
the selected) user IDs. Calling setpref with no arguments sets the
preference list to the default (either built-in or set via
--default-preference-list), and calling setpref with "none" as the
argument sets an empty preference list. Use "gpg --version" to get a
list of available algorithms. Note that while you can change the
preferences on an attribute user ID (aka "photo ID"), GnuPG does not
select keys via attribute user IDs so these preferences will not be
used by GnuPG.
@item keyserver
Set a preferred keyserver for the specified user ID(s). This allows
@ -506,6 +500,10 @@ keyservers set (see --keyserver-option honor-keyserver-url).
Search the keyserver for the given names. Multiple names given here
will be joined together to create the search string for the keyserver.
Option --keyserver must be used to give the name of this keyserver.
Keyservers that support different search methods allow using the
syntax specified in "How to specify a user ID" below. Note that
different keyserver types support different search methods. Currently
only LDAP supports them all.
@item --update-trustdb
Do trust database maintenance. This command iterates over all keys
@ -935,6 +933,9 @@ sigs" after import. Defaults to no.
After import, compact (remove all signatures from) any user IDs from
the new key that are not usable. This is the same as running the
--edit-key command "clean uids" after import. Defaults to no.
@item import-clean
Identical to "import-clean-sigs import-clean-uids".
@end table
@item --export-options @code{parameters}
@ -975,8 +976,8 @@ the --edit-key command "clean uids" before export. Defaults to no.
@item export-reset-subkey-passwd
When using the "--export-secret-subkeys" command, this option resets
the passphrases for all exported subkeys to empty. This is useful
when the exported subkey is to be used on an unattended amchine where
a passphrase won't make sense. Defaults to no.
when the exported subkey is to be used on an unattended machine where
a passphrase doesn't necessarily make sense. Defaults to no.
@end table
@item --list-options @code{parameters}
@ -1160,10 +1161,12 @@ found.
@item --display-charset @code{name}
Set the name of the native character set. This is used to convert
some informational strings like user IDs to the proper UTF-8
encoding. If this option is not used, the default character set is
determined from the current locale. A verbosity level of 3 shows the
chosen set. Valid values for @code{name} are:
some informational strings like user IDs to the proper UTF-8 encoding.
Note that this has nothing to do with the character set of data to be
encrypted or signed; GnuPG does not recode user supplied data. If
this option is not used, the default character set is determined from
the current locale. A verbosity level of 3 shows the chosen set.
Valid values for @code{name} are:
@table @asis
@ -1231,15 +1234,27 @@ There is a slight performance overhead using it.
Write special status strings to the file descriptor @code{n}.
See the file DETAILS in the documentation for a listing of them.
@item --status-file @code{file}
Same as --status-fd, except the status data is written to file
@code{file}.
@item --logger-fd @code{n}
Write log output to file descriptor @code{n} and not to stderr.
@item --logger-file @code{file}
Same as --logger-fd, except the logger data is written to file
@code{file}.
@item --attribute-fd @code{n}
Write attribute subpackets to the file descriptor @code{n}. This is
most useful for use with --status-fd, since the status messages are
needed to separate out the various subpackets from the stream
delivered to the file descriptor.
@item --attribute-file @code{file}
Same as --attribute-fd, except the attribute data is written to file
@code{file}.
@item --comment @code{string}
@itemx --no-comments
Use @code{string} as a comment string in clear text signatures and
@ -1475,6 +1490,17 @@ Read the passphrase from file descriptor @code{n}. If you use
can only be used if only one passphrase is supplied.
Don't use this option if you can avoid it.
@item --passphrase-file @code{file}
Read the passphrase from file @code{file}. This can only be used if
only one passphrase is supplied. Obviously, a passphrase stored in a
file is of questionable security. Don't use this option if you can
avoid it.
@item --passphrase @code{string}
Use @code{string} as the passphrase. This can only be used if only one
passphrase is supplied. Obviously, this is of very questionable
security. Don't use this option if you can avoid it.
@item --command-fd @code{n}
This is a replacement for the deprecated shared-memory IPC mode.
If this option is enabled, user input on questions is not expected
@ -1482,6 +1508,10 @@ from the TTY but from the given file descriptor. It should be used
together with --status-fd. See the file doc/DETAILS in the source
distribution for details on how to use it.
@item --command-file @code{file}
Same as --command-fd, except the commands are read out of file
@code{file}
@item --use-agent
@itemx --no-use-agent
Try to use the GnuPG-Agent. Please note that this agent is still under
@ -1871,10 +1901,9 @@ preferences. The most highly ranked algorithm in this list is also
used when there are no recipient keys to consider (e.g. --symmetric).
@item --default-preference-list @code{string}
Set the list of default preferences to @code{string}, this list should
be a string similar to the one printed by the command "pref" in the
edit menu. This affects both key generation and "updpref" in the edit
menu.
Set the list of default preferences to @code{string}. This preference
list is used for new keys and becomes the default for "setpref" in the
edit menu.
@item --list-config
Display various internal configuration parameters of GnuPG. This
@ -1921,10 +1950,9 @@ Using an exact to match string. The equal sign indicates this.
Using the email address part which must match exactly. The left angle bracket
indicates this email address mode.
@item +Heinrich Heine duesseldorf
All words must match exactly (not case sensitive) but can appear in
any order in the user ID. Words are any sequences of letters,
digits, the underscore and all characters with bit 7 set.
@item @@heinrichh
Match within the <email.address> part of a user ID. The at sign
indicates this email address mode.
@item Heine
@itemx *Heine

View File

@ -70,16 +70,16 @@
<command/gpgv/ is the OpenPGP signature checking tool.
</para>
<para>
This program is a stripped down version of <command/gpg/ which is only
able
to check signatures. It is somewhat smaller than the full blown
<command/gpg/ and uses a different (and more simple way) to check that
the public keys used to made the signature are trustworth. There is
This program is a stripped down version of <command/gpg/ which is able
only
to check signatures. It is somewhat smaller than the fully blown
<command/gpg/ and uses a different (and simpler) way to check that
the public keys used to make the signature are trustworthy. There are
no options files and only very few options are implemented.
</para>
<para>
<command/gpgv/ assumes that all keys in the keyring are trustworty.
It uses by default a keyring named <filename/trustedkeys.gpg/ which is
<command/gpgv/ assumes that all keys in the keyring are trustworthy.
By default it uses a keyring named <filename/trustedkeys.gpg/ which is
assumed to be in the home directory as defined by GnuPG or set by an
option or an environment variable. An option may be used to specify
another keyring or even multiple keyrings.
@ -98,7 +98,7 @@ another keyring or even multiple keyrings.
<varlistentry>
<term>-v, --verbose</term>
<listitem><para>
Give more information during processing. If used
Gives more information during processing. If used
twice, the input data is listed in detail.
</para></listitem></varlistentry>
@ -127,8 +127,8 @@ The filename may be prefixed with a scheme:</para>
<term>--homedir &ParmDir;</term>
<listitem><para>
Set the name of the home directory to &ParmDir; If this
option is not used it defaults to "~/.gnupg". It does
not make sense to use this in a options file. This
option is not used, it defaults to "~/.gnupg". It does
not make sense to use this in an options file. This
also overrides the environment variable "GNUPGHOME".
</para></listitem></varlistentry>
@ -154,7 +154,7 @@ Write log output to file descriptor &ParmN; and not to stderr.
GnuPG normally checks that the timestamps associated with keys and
signatures have plausible values. However, sometimes a signature seems to
be older than the key due to clock problems. This option makes these
checks just a warning.
checks just warnings.
</para></listitem></varlistentry>

View File

@ -22,15 +22,15 @@ gpgv
@code{gpgv} is the OpenPGP signature checking tool.
This program is a stripped down version of @code{gpg} which is only
able
to check signatures. It is somewhat smaller than the full blown
@code{gpg} and uses a different (and more simple way) to check that
the public keys used to made the signature are trustworth. There is
This program is a stripped down version of @code{gpg} which is able
only
to check signatures. It is somewhat smaller than the fully blown
@code{gpg} and uses a different (and simpler) way to check that
the public keys used to make the signature are trustworthy. There are
no options files and only very few options are implemented.
@code{gpgv} assumes that all keys in the keyring are trustworty.
It uses by default a keyring named @file{trustedkeys.gpg} which is
@code{gpgv} assumes that all keys in the keyring are trustworthy.
By default it uses a keyring named @file{trustedkeys.gpg} which is
assumed to be in the home directory as defined by GnuPG or set by an
option or an environment variable. An option may be used to specify
another keyring or even multiple keyrings.
@ -41,7 +41,7 @@ another keyring or even multiple keyrings.
@table @asis
@item -v, --verbose
Give more information during processing. If used
Gives more information during processing. If used
twice, the input data is listed in detail.
@item -q, --quiet
@ -59,8 +59,8 @@ The filename may be prefixed with a scheme:
@item --homedir @code{directory}
Set the name of the home directory to @code{directory} If this
option is not used it defaults to "~/.gnupg". It does
not make sense to use this in a options file. This
option is not used, it defaults to "~/.gnupg". It does
not make sense to use this in an options file. This
also overrides the environment variable "GNUPGHOME".
@item --status-fd @code{n}
@ -74,7 +74,7 @@ Write log output to file descriptor @code{n} and not to stderr.
GnuPG normally checks that the timestamps associated with keys and
signatures have plausible values. However, sometimes a signature seems to
be older than the key due to clock problems. This option makes these
checks just a warning.
checks just warnings.
@end table
@chapheading RETURN VALUE

View File

@ -1,3 +1,12 @@
2005-10-17 Werner Koch <wk@g10code.com>
* export.c (do_export_stream): Factored some code out to ...
(skip_subkey_p): .. new.
(subkey_in_list_p, release_subkey_list): New.
(new_subkey_list_item): New.
(do_export_stream): Export exactly specified subkeys into one
keyblock.
2005-10-13 David Shaw <dshaw@jabberwocky.com>
* keyedit.c (keyedit_menu, menu_backsign): New "backsign" command

View File

@ -37,6 +37,17 @@
#include "i18n.h"
#include "trustdb.h"
/* An object to keep track of subkeys. */
struct subkey_list_s
{
struct subkey_list_s *next;
u32 kid[2];
};
typedef struct subkey_list_s *subkey_list_t;
static int do_export( STRLIST users, int secret, unsigned int options );
static int do_export_stream( IOBUF out, STRLIST users, int secret,
KBNODE *keyblock_out, unsigned int options,
@ -77,6 +88,7 @@ parse_export_options(char *str,unsigned int *options,int noisy)
return parse_options(str,options,export_opts,noisy);
}
/****************
* Export the public keys (to standard out or --output).
* Depending on opt.armor the output is armored.
@ -147,6 +159,124 @@ do_export( STRLIST users, int secret, unsigned int options )
}
/* Release an entire subkey list. */
static void
release_subkey_list (subkey_list_t list)
{
while (list)
{
subkey_list_t tmp = list->next;;
xfree (list);
list = tmp;
}
}
/* Returns true if NODE is a subkey and contained in LIST. */
static int
subkey_in_list_p (subkey_list_t list, KBNODE node)
{
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY )
{
u32 kid[2];
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, kid);
else
keyid_from_sk (node->pkt->pkt.secret_key, kid);
for (; list; list = list->next)
if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
return 1;
}
return 0;
}
/* Allocate a new subkey list item from NODE. */
static subkey_list_t
new_subkey_list_item (KBNODE node)
{
subkey_list_t list = xcalloc (1, sizeof *list);
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, list->kid);
else if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
keyid_from_sk (node->pkt->pkt.secret_key, list->kid);
return list;
}
/* Helper function to check whether the subkey at NODE actually
matches the description at DESC. The function returns true if the
key under question has been specified by an exact specification
(keyID or fingerprint) and does match the one at NODE. It is
assumed that the packet at NODE is either a public or secret
subkey. */
static int
exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
{
u32 kid[2];
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
int result = 0;
switch(desc->mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
case KEYDB_SEARCH_MODE_LONG_KID:
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, kid);
else
keyid_from_sk (node->pkt->pkt.secret_key, kid);
break;
case KEYDB_SEARCH_MODE_FPR16:
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
else
fingerprint_from_sk (node->pkt->pkt.secret_key, fpr,&fprlen);
break;
default:
break;
}
switch(desc->mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
if (desc->u.kid[1] == kid[1])
result = 1;
break;
case KEYDB_SEARCH_MODE_LONG_KID:
if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1])
result = 1;
break;
case KEYDB_SEARCH_MODE_FPR16:
if (!memcmp (desc->u.fpr, fpr, 16))
result = 1;
break;
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if (!memcmp (desc->u.fpr, fpr, 20))
result = 1;
break;
default:
break;
}
return result;
}
/* If keyblock_out is non-NULL, AND the exit code is zero, then it
contains a pointer to the first keyblock found and exported. No
other keyblocks are exported. The caller must free it. */
@ -160,6 +290,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
KBNODE kbctx, node;
size_t ndesc, descindex;
KEYDB_SEARCH_DESC *desc = NULL;
subkey_list_t subkey_list = NULL; /* Track alreay processed subkeys. */
KEYDB_HANDLE kdbhd;
STRLIST sl;
u32 keyid[2];
@ -170,7 +301,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
if (!users) {
ndesc = 1;
desc = xmalloc_clear ( ndesc * sizeof *desc);
desc = xcalloc ( ndesc, sizeof *desc );
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
}
else {
@ -186,7 +317,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
sl->d, g10_errstr (G10ERR_INV_USER_ID));
}
/* it would be nice to see which of the given users did
/* It would be nice to see which of the given users did
actually match one in the keyring. To implement this we
need to have a found flag for each entry in desc and to set
this we must check all those entries after a match to mark
@ -209,7 +340,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
if (!users)
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
/* read the keyblock */
/* Read the keyblock. */
rc = keydb_get_keyblock (kdbhd, &keyblock );
if( rc ) {
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
@ -222,7 +353,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
keyid_from_sk(sk,sk_keyid);
/* we can't apply GNU mode 1001 on an unprotected key */
/* We can't apply GNU mode 1001 on an unprotected key. */
if( secret == 2 && !sk->is_protected )
{
log_info(_("key %s: not protected - skipped\n"),
@ -230,7 +361,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
continue;
}
/* no v3 keys with GNU mode 1001 */
/* No v3 keys with GNU mode 1001. */
if( secret == 2 && sk->version == 3 )
{
log_info(_("key %s: PGP 2.x style key - skipped\n"),
@ -251,7 +382,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
}
else
{
/* It's a public key export */
/* It's a public key export. */
if((options&EXPORT_MINIMAL)
&& (node=find_kbnode(keyblock,PKT_PUBLIC_KEY)))
keyid_from_pk(node->pkt->pkt.public_key,keyid);
@ -260,7 +391,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
clean_uids_from_key(keyblock,opt.verbose);
}
/* and write it */
/* And write it. */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
if( skip_until_subkey )
{
@ -277,89 +408,59 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
if( node->pkt->pkttype == PKT_COMMENT )
continue;
/* make sure that ring_trust packets never get exported */
/* Make sure that ring_trust packets never get exported. */
if (node->pkt->pkttype == PKT_RING_TRUST)
continue;
/* If exact is set, then we only export what was requested
(plus the primary key, if the user didn't specifically
request it) */
request it). */
if(desc[descindex].exact
&& (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype==PKT_SECRET_SUBKEY))
{
u32 kid[2];
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
switch(desc[descindex].mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
case KEYDB_SEARCH_MODE_LONG_KID:
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
keyid_from_pk(node->pkt->pkt.public_key,kid);
else
keyid_from_sk(node->pkt->pkt.secret_key,kid);
break;
case KEYDB_SEARCH_MODE_FPR16:
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
fingerprint_from_pk(node->pkt->pkt.public_key,
fpr,&fprlen);
else
fingerprint_from_sk(node->pkt->pkt.secret_key,
fpr,&fprlen);
break;
default:
break;
}
switch(desc[descindex].mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
if (desc[descindex].u.kid[1] != kid[1])
skip_until_subkey=1;
break;
case KEYDB_SEARCH_MODE_LONG_KID:
if (desc[descindex].u.kid[0] != kid[0]
|| desc[descindex].u.kid[1] != kid[1])
skip_until_subkey=1;
break;
case KEYDB_SEARCH_MODE_FPR16:
if (memcmp (desc[descindex].u.fpr, fpr, 16))
skip_until_subkey=1;
break;
case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR:
if (memcmp (desc[descindex].u.fpr, fpr, 20))
skip_until_subkey=1;
break;
default:
break;
}
/* XXX: before skipping a subkey, check whether any
other description wants an exact macth on a subkey
and include that subkey into the output too. Need
to add this subkey to a list so that it won't get
processed a second time.
if (!exact_subkey_match_p (desc+descindex, node))
{
/* Before skipping this subkey, check whether any
other description wants an exact match on a
subkey and include that subkey into the output
too. Need to add this subkey to a list so that
it won't get processed a second time.
So the first step here is to check that list and
skip in any case if the key is in that list.
So the first step here is to check that list and
skip in any case if the key is in that list.
We need this whole mess becuase the import fnction
is not able to merge secret key and thus it is not
possible to output them as two keys and have import
merge them.
*/
We need this whole mess because the import
function is not able to merge secret keys and
thus it is useless to output them as two
separate keys and have import merge them. */
if (subkey_in_list_p (subkey_list, node))
skip_until_subkey = 1; /* Already processed this one. */
else
{
size_t j;
for (j=0; j < ndesc; j++)
if (j != descindex && desc[j].exact
&& exact_subkey_match_p (desc+j, node))
break;
if (!(j < ndesc))
skip_until_subkey = 1; /* No other one matching. */
}
}
if(skip_until_subkey)
continue;
/* Mark this one as processed. */
{
subkey_list_t tmp = new_subkey_list_item (node);
tmp->next = subkey_list;
subkey_list = tmp;
}
}
if(node->pkt->pkttype==PKT_USER_ID)
{
/* Run clean_sigs_from_uid against each uid if
@ -510,6 +611,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret,
rc = 0;
leave:
release_subkey_list (subkey_list);
xfree(desc);
keydb_release (kdbhd);
if(rc || keyblock_out==NULL)