diff --git a/g10/ChangeLog b/g10/ChangeLog index d83bc1b31..8c7000ae2 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,22 @@ +2003-02-12 David Shaw + + * keydb.h, getkey.c (classify_user_id, classify_user_id2): Make + 'exact' a per-desc item. Merge into one function since + 'force_exact' is no longer needed. + (key_byname): Use new classify_user_id function, and new exact + flag in KEYDB_SEARCH_DESC. + + * keyring.h, keyring.c (keyring_search): Return an optional index + to show which KEYDB_SEARCH_DESC was the matching one. + + * keydb.h, keydb.c (keydb_search): Rename to keydb_search2, and + pass the optional index to keyring_search. Add a macro version of + keydb_search that calls this new function. + + * export.c (do_export_stream): If the keyid! syntax is used, + export only that specified key. If the key in question is a + subkey, export the primary plus that subkey only. + 2003-02-11 David Shaw * exec.c (set_exec_path): Add debugging line. diff --git a/g10/export.c b/g10/export.c index 5f6eadcd5..c56888265 100644 --- a/g10/export.c +++ b/g10/export.c @@ -164,7 +164,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret, PACKET pkt; KBNODE keyblock = NULL; KBNODE kbctx, node; - int ndesc; + size_t ndesc, descindex; KEYDB_SEARCH_DESC *desc = NULL; KEYDB_HANDLE kdbhd; STRLIST sl; @@ -199,9 +199,8 @@ do_export_stream( IOBUF out, STRLIST users, int secret, do this we need an extra flag to enable this feature so */ } - - while (!(rc = keydb_search (kdbhd, desc, ndesc))) { - int sha1_warned=0; + while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) { + int sha1_warned=0,skip_until_subkey=0; u32 sk_keyid[2]; if (!users) @@ -251,14 +250,88 @@ do_export_stream( IOBUF out, STRLIST users, int secret, /* and write it */ for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) { + if( skip_until_subkey ) + { + if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY + || node->pkt->pkttype==PKT_SECRET_SUBKEY) + skip_until_subkey=0; + else + continue; + } + /* don't export any comment packets but those in the * secret keyring */ if( !secret && node->pkt->pkttype == PKT_COMMENT ) continue; + /* 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) */ + 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; + } + + if(skip_until_subkey) + continue; + } + if( node->pkt->pkttype == PKT_SIGNATURE ) { /* do not export packets which are marked as not exportable */ if( !(options&EXPORT_INCLUDE_LOCAL_SIGS) && diff --git a/g10/getkey.c b/g10/getkey.c index e729b97c2..9040d386c 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -552,20 +552,22 @@ seckey_available( u32 *keyid ) * is not case sensitive. */ -static int -classify_user_id2( const char *name, - KEYDB_SEARCH_DESC *desc, - int *force_exact ) +int +classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) { const char *s; int hexprefix = 0; int hexlength; int mode = 0; - + KEYDB_SEARCH_DESC dummy_desc; + + if (!desc) + desc = &dummy_desc; + /* clear the structure so that the mode field is set to zero unless * we set it to the correct value right at the end of this function */ memset (desc, 0, sizeof *desc); - *force_exact = 0; + /* skip leading spaces. Fixme: what is with trailing spaces? */ for(s = name; *s && isspace(*s); s++ ) ; @@ -643,7 +645,7 @@ classify_user_id2( const char *name, hexlength = strspn(s, "0123456789abcdefABCDEF"); if (hexlength >= 8 && s[hexlength] =='!') { - *force_exact = 1; + desc->exact = 1; hexlength++; /* just for the following check */ } @@ -655,7 +657,7 @@ classify_user_id2( const char *name, hexlength = 0; /* a hex number, but really were not. */ } - if (*force_exact) + if (desc->exact) hexlength--; if (hexlength == 8 @@ -711,7 +713,7 @@ classify_user_id2( const char *name, if (hexprefix) /* This was a hex number with a prefix */ return 0; /* and a wrong length */ - *force_exact = 0; + desc->exact = 0; desc->u.name = s; mode = KEYDB_SEARCH_MODE_SUBSTR; /* default mode */ } @@ -721,16 +723,6 @@ classify_user_id2( const char *name, return mode; } -int -classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc) -{ - int dummy; - KEYDB_SEARCH_DESC dummy_desc; - - if (!desc) - desc = &dummy_desc; - return classify_user_id2 (name, desc, &dummy); -} /**************** * Try to get the pubkey by the userid. This function looks for the @@ -752,7 +744,6 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, STRLIST r; GETKEY_CTX ctx; KBNODE help_kb = NULL; - int exact; if( retctx ) {/* reset the returned context in case of error */ assert (!ret_kdbhd); /* not allowed because the handle is @@ -769,9 +760,9 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, ctx->nitems = n; for(n=0, r=namelist; r; r = r->next, n++ ) { - classify_user_id2 (r->d, &ctx->items[n], &exact); + classify_user_id (r->d, &ctx->items[n]); - if (exact) + if (ctx->items[n].exact) ctx->exact = 1; if (!ctx->items[n].mode) { m_free (ctx); diff --git a/g10/keydb.c b/g10/keydb.c index d2b0cea9c..19b5c1ab8 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -653,7 +653,8 @@ keydb_search_reset (KEYDB_HANDLE hd) * for a keyblock which contains one of the keys described in the DESC array. */ int -keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) +keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, + size_t ndesc, size_t *descindex) { int rc = -1; @@ -666,7 +667,8 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) BUG(); /* we should never see it here */ break; case KEYDB_RESOURCE_TYPE_KEYRING: - rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc); + rc = keyring_search (hd->active[hd->current].u.kr, desc, + ndesc, descindex); break; } if (rc == -1) /* EOF -> switch to next resource */ @@ -678,7 +680,6 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) return rc; } - int keydb_search_first (KEYDB_HANDLE hd) { diff --git a/g10/keydb.h b/g10/keydb.h index 4afc0ed70..b01a4f0dd 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -140,6 +140,7 @@ struct keydb_search_desc { char fpr[MAX_FINGERPRINT_LEN]; u32 kid[2]; } u; + int exact; }; /*-- keydb.c --*/ @@ -159,7 +160,9 @@ int keydb_delete_keyblock (KEYDB_HANDLE hd); int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved); void keydb_rebuild_caches (void); int keydb_search_reset (KEYDB_HANDLE hd); -int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); +#define keydb_search(a,b,c) keydb_search2((a),(b),(c),NULL) +int keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, + size_t ndesc, size_t *descindex); int keydb_search_first (KEYDB_HANDLE hd); int keydb_search_next (KEYDB_HANDLE hd); int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid); diff --git a/g10/keyring.c b/g10/keyring.c index caa8df8b5..898136b05 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -852,7 +852,8 @@ compare_name (int mode, const char *name, const char *uid, size_t uidlen) * for a keyblock which contains one of the keys described in the DESC array. */ int -keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) +keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, + size_t ndesc, size_t *descindex) { int rc; PACKET pkt; @@ -1074,7 +1075,11 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) } free_packet (&pkt); continue; - found: + found: + /* Record which desc we matched on. Note this value is only + meaningful if this function returns with no errors. */ + if(descindex) + *descindex=n; for (n=any_skip?0:ndesc; n < ndesc; n++) { if (desc[n].skipfnc @@ -1321,7 +1326,7 @@ keyring_rebuild_cache (void *token) memset (&desc, 0, sizeof desc); desc.mode = KEYDB_SEARCH_MODE_FIRST; - while ( !(rc = keyring_search (hd, &desc, 1)) ) + while ( !(rc = keyring_search (hd, &desc, 1, NULL)) ) { desc.mode = KEYDB_SEARCH_MODE_NEXT; resname = keyring_get_resource_name (hd); diff --git a/g10/keyring.h b/g10/keyring.h index 1a6d1f976..528557a70 100644 --- a/g10/keyring.h +++ b/g10/keyring.h @@ -39,7 +39,8 @@ int keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb); int keyring_locate_writable (KEYRING_HANDLE hd); int keyring_delete_keyblock (KEYRING_HANDLE hd); int keyring_search_reset (KEYRING_HANDLE hd); -int keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); +int keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, + size_t ndesc, size_t *descindex); int keyring_rebuild_cache (void *); #endif /*GPG_KEYRING_H*/