mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
exported subkeys are now merged into one output keyblock
This commit is contained in:
parent
21eea5be5e
commit
9b7f1f6976
8 changed files with 272 additions and 125 deletions
|
@ -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
|
||||
|
|
250
g10/export.c
250
g10/export.c
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue