aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/ChangeLog19
-rw-r--r--g10/export.c81
-rw-r--r--g10/getkey.c35
-rw-r--r--g10/keydb.c7
-rw-r--r--g10/keydb.h5
-rw-r--r--g10/keyring.c11
-rw-r--r--g10/keyring.h3
7 files changed, 127 insertions, 34 deletions
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 <[email protected]>
+
+ * 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 <[email protected]>
* 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*/