--locate-key now returns several keys if they all match.
authorWerner Koch <wk@gnupg.org>
Wed, 7 May 2008 18:19:41 +0000 (18:19 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 7 May 2008 18:19:41 +0000 (18:19 +0000)
g10/ChangeLog
g10/getkey.c
g10/keydb.h
g10/keyedit.c
g10/keylist.c
g10/pkclist.c

index 52efafd..38b2b87 100644 (file)
@@ -1,11 +1,13 @@
 2008-05-07  Werner Koch  <wk@g10code.com>
 
-       * getkey.c (get_pubkey_byname): Fix nodefault case.
-
        * gpg.c: New command --locate-keys.  New options --with-sig-list
        and --with-sig-check.
        * keylist.c (locate_one): New.
        (public_key_list): Add arg LOCATE_MODE and use locate_one.
+       * getkey.c (get_pubkey_byname): Fix nodefault case.  Add option
+       RETCTX, change all callers.
+       (struct getkey_ctx_s): Add field extra_ptr;
+       (get_pubkey_end): Free it.
 
 2008-04-18  Werner Koch  <wk@g10code.com>
 
index 93f8f14..5b0cafa 100644 (file)
@@ -47,7 +47,8 @@ struct getkey_ctx_s {
     int exact;
     KBNODE keyblock;
     KBPOS  kbpos;
-    KBNODE found_key; /* pointer into some keyblock */
+    KBNODE found_key; /* Pointer into some keyblock. */
+    strlist_t *extra_list;  /* Will be freed when releasing the context.  */
     int last_rc;
     int req_usage;
     int req_algo;
@@ -917,7 +918,7 @@ key_byname( GETKEY_CTX *retctx, strlist_t namelist,
    to import the key via the online mechanisms defined by
    --auto-key-locate.  */
 int
-get_pubkey_byname (PKT_public_key *pk,
+get_pubkey_byname (GETKEY_CTX *retctx, PKT_public_key *pk,
                   const char *name, KBNODE *ret_keyblock,
                    KEYDB_HANDLE *ret_kdbhd, int include_unusable, 
                    int no_akl)
@@ -927,12 +928,22 @@ get_pubkey_byname (PKT_public_key *pk,
   struct akl *akl;
   int is_mbox;
   int nodefault = 0;
+  int anylocalfirst = 0;
+
+  if (retctx)
+    *retctx = NULL;
 
   is_mbox = is_valid_mailbox (name);
 
   /* Check whether we the default local search has been disabled.
      This is the case if either the "nodefault" or the "local" keyword
-     are in the list of auto key locate mechanisms.  */
+     are in the list of auto key locate mechanisms. 
+
+     ANYLOCALFIRST is set if the search order has the local method
+     before any other or if "local" is used first by default.  This
+     makes sure that if a RETCTX is used it gets only set if a local
+     search has precedence over the other search methods and only then
+     a followup call to get_pubkey_next shall succeed.  */
   if (!no_akl)
     {
       for (akl=opt.auto_key_locate; akl; akl=akl->next)
@@ -941,8 +952,18 @@ get_pubkey_byname (PKT_public_key *pk,
             nodefault = 1;
             break;
           }
+      for (akl=opt.auto_key_locate; akl; akl=akl->next)
+        if (akl->type != AKL_NODEFAULT)
+          {
+            if (akl->type == AKL_LOCAL)
+              anylocalfirst = 1;
+            break;
+          }
     }
 
+  if (!nodefault)
+    anylocalfirst = 1;
+
   if (nodefault && is_mbox)
     {
       /* Nodefault but a mailbox - let the AKL locate the key.  */
@@ -951,7 +972,7 @@ get_pubkey_byname (PKT_public_key *pk,
   else
     {
       add_to_strlist (&namelist, name);
-      rc = key_byname (NULL, namelist, pk, NULL, 0,
+      rc = key_byname (retctx, namelist, pk, NULL, 0,
                        include_unusable, ret_keyblock, ret_kdbhd);
     }
 
@@ -967,7 +988,7 @@ get_pubkey_byname (PKT_public_key *pk,
           int no_fingerprint = 0;
           const char *mechanism = "?";
           
-         switch(akl->type)
+          switch(akl->type)
            {
             case AKL_NODEFAULT:
               /* This is a dummy mechanism.  */
@@ -978,8 +999,14 @@ get_pubkey_byname (PKT_public_key *pk,
             case AKL_LOCAL:
               mechanism = "Local";
               did_key_byname = 1;
+              if (retctx)
+                {
+                  get_pubkey_end (*retctx);
+                  *retctx = NULL;
+                }
               add_to_strlist (&namelist, name);
-              rc = key_byname (NULL, namelist, pk, NULL, 0,
+              rc = key_byname (anylocalfirst? retctx:NULL,
+                               namelist, pk, NULL, 0,
                                include_unusable, ret_keyblock, ret_kdbhd);
               break;
 
@@ -1068,8 +1095,16 @@ get_pubkey_byname (PKT_public_key *pk,
           fpr = NULL;
 
           if (!rc && !did_key_byname)
-            rc = key_byname (NULL, namelist, pk, NULL, 0,
-                             include_unusable, ret_keyblock, ret_kdbhd);
+            {
+              if (retctx)
+                {
+                  get_pubkey_end (*retctx);
+                  *retctx = NULL;
+                }
+              rc = key_byname (anylocalfirst?retctx:NULL,
+                               namelist, pk, NULL, 0,
+                               include_unusable, ret_keyblock, ret_kdbhd);
+            }
          if (!rc)
             {
               /* Key found.  */
@@ -1084,10 +1119,24 @@ get_pubkey_byname (PKT_public_key *pk,
        }
     }
 
-  free_strlist( namelist );
+  
+  if (rc && retctx)
+    {
+      get_pubkey_end (*retctx);
+      *retctx = NULL;
+    }
+
+  if (retctx && *retctx)
+    {
+      assert (!(*retctx)->extra_list);
+      (*retctx)->extra_list = namelist;
+    }
+  else
+    free_strlist (namelist);
   return rc;
 }
 
+
 int
 get_pubkey_bynames( GETKEY_CTX *retctx, PKT_public_key *pk,
                    strlist_t names, KBNODE *ret_keyblock )
@@ -1113,6 +1162,7 @@ get_pubkey_end( GETKEY_CTX ctx )
     if( ctx ) {
         memset (&ctx->kbpos, 0, sizeof ctx->kbpos);
         keydb_release (ctx->kr_handle);
+        free_strlist (ctx->extra_list);
        if( !ctx->not_allocated )
            xfree( ctx );
     }
index aa6885c..4e82458 100644 (file)
@@ -221,7 +221,7 @@ void getkey_disable_caches(void);
 int get_pubkey( PKT_public_key *pk, u32 *keyid );
 int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid );
 KBNODE get_pubkeyblock( u32 *keyid );
-int get_pubkey_byname( PKT_public_key *pk,  const char *name,
+int get_pubkey_byname (GETKEY_CTX *rx, PKT_public_key *pk,  const char *name,
                        KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
                       int include_unusable, int no_akl );
 int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk,
index d4c8155..03d8651 100644 (file)
@@ -1544,7 +1544,7 @@ keyedit_menu( const char *username, strlist_t locusr,
 #endif
 
     /* Get the public key */
-    rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd, 1, 1);
+    rc = get_pubkey_byname (NULL, NULL, username, &keyblock, &kdbhd, 1, 1);
     if( rc )
        goto leave;
     if( fix_keyblock( keyblock ) )
@@ -3396,7 +3396,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
         GnuPG both can handle a designated revokation from a
         subkey. */
       revoker_pk->req_usage=PUBKEY_USAGE_CERT;
-      rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1, 1);
+      rc=get_pubkey_byname (NULL, revoker_pk,answer,NULL,NULL,1, 1);
       if(rc)
        {
          log_error (_("key \"%s\" not found: %s\n"),answer,g10_errstr(rc));
index a98a4f9..0c6e267 100644 (file)
@@ -537,14 +537,15 @@ locate_one (strlist_t names)
 {
   int rc = 0;
   strlist_t sl;
+  GETKEY_CTX ctx = NULL;
   KBNODE keyblock = NULL;
   struct sig_stats stats;
 
-  memset(&stats,0,sizeof(stats));
+  memset (&stats,0,sizeof(stats));
     
   for (sl=names; sl; sl = sl->next)
     {
-      rc = get_pubkey_byname (NULL, sl->d, &keyblock, NULL, 1, 0);
+      rc = get_pubkey_byname (&ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
       if (rc)
         {
           if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
@@ -552,9 +553,15 @@ locate_one (strlist_t names)
        }
       else
         {
-          list_keyblock (keyblock, 0, opt.fingerprint,
-                         opt.check_sigs? &stats : NULL );
-          release_kbnode (keyblock);
+          do 
+            {
+              list_keyblock (keyblock, 0, opt.fingerprint,
+                             opt.check_sigs? &stats : NULL );
+              release_kbnode (keyblock);
+            } 
+          while ( ctx && !get_pubkey_next (ctx, NULL, &keyblock));
+          get_pubkey_end (ctx);
+          ctx = NULL;
        } 
     }
   
index dbabdab..2c56c78 100644 (file)
@@ -826,7 +826,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
           /* We explicitly allow encrypt-to to an disabled key; thus
              we pass 1for the second last argument and 1 as the last
              argument to disable AKL. */
-          if ( (rc = get_pubkey_byname (pk, rov->d, NULL, NULL, 1, 1)) ) 
+          if ( (rc = get_pubkey_byname (NULL, pk, rov->d, NULL, NULL, 1, 1)) ) 
             {
               free_public_key ( pk ); pk = NULL;
               log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
@@ -965,7 +965,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
             free_public_key (pk);
           pk = xmalloc_clear( sizeof *pk );
           pk->req_usage = use;
-          rc = get_pubkey_byname( pk, answer, NULL, NULL, 0, 0 );
+          rc = get_pubkey_byname (NULL, pk, answer, NULL, NULL, 0, 0 );
           if (rc)
             tty_printf(_("No such user ID.\n"));
           else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) ) 
@@ -1039,7 +1039,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
 
       /* The default recipient is allowed to be disabled; thus pass 1
          as second last argument.  We also don't want an AKL. */
-      rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 1, 1);
+      rc = get_pubkey_byname (NULL, pk, def_rec, NULL, NULL, 1, 1);
       if (rc)
         log_error(_("unknown default recipient \"%s\"\n"), def_rec );
       else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use)) ) 
@@ -1079,7 +1079,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
 
           pk = xmalloc_clear( sizeof *pk );
           pk->req_usage = use;
-          if ( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0, 0 )) ) 
+          if ((rc = get_pubkey_byname (NULL, pk, remusr->d, NULL, NULL, 0, 0)))
             {
               /* Key not found or other error. */
               free_public_key( pk ); pk = NULL;