* keydb.h, getkey.c (classify_user_id, classify_user_id2): Make 'exact' a
authorDavid Shaw <dshaw@jabberwocky.com>
Wed, 12 Feb 2003 18:43:44 +0000 (18:43 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Wed, 12 Feb 2003 18:43:44 +0000 (18:43 +0000)
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.

g10/ChangeLog
g10/export.c
g10/getkey.c
g10/keydb.c
g10/keydb.h
g10/keyring.c
g10/keyring.h

index d83bc1b..8c7000a 100644 (file)
@@ -1,3 +1,22 @@
+2003-02-12  David Shaw  <dshaw@jabberwocky.com>
+
+       * 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  <dshaw@jabberwocky.com>
 
        * exec.c (set_exec_path): Add debugging line.
index 5f6eadc..c568882 100644 (file)
@@ -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) &&
index e729b97..9040d38 100644 (file)
@@ -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);
index d2b0cea..19b5c1a 100644 (file)
@@ -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)
 {
index 4afc0ed..b01a4f0 100644 (file)
@@ -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);
index caa8df8..898136b 100644 (file)
@@ -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);
index 1a6d1f9..528557a 100644 (file)
@@ -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*/