* options.h, keydb.h, g10.c (main), getkey.c (parse_auto_key_locate):
authorDavid Shaw <dshaw@jabberwocky.com>
Wed, 22 Feb 2006 19:06:23 +0000 (19:06 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Wed, 22 Feb 2006 19:06:23 +0000 (19:06 +0000)
Parse a list of key access methods. (get_pubkey_byname): Walk the list
here to try and retrieve keys we don't have locally.

g10/ChangeLog
g10/getkey.c
g10/gpg.c
g10/keydb.h
g10/options.h

index 7ae181d..bd894fa 100644 (file)
@@ -1,3 +1,10 @@
+2006-02-22  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, keydb.h, g10.c (main), getkey.c
+       (parse_auto_key_locate): Parse a list of key access methods.
+       (get_pubkey_byname): Walk the list here to try and retrieve keys
+       we don't have locally.
+
 2006-02-21  David Shaw  <dshaw@jabberwocky.com>
 
        * getkey.c (get_pubkey_byname): Fix minor security problem with
index 8ec1e52..7d91cde 100644 (file)
@@ -905,91 +905,94 @@ get_pubkey_byname (PKT_public_key *pk,
                    KEYDB_HANDLE *ret_kdbhd, int include_unusable )
 {
   int rc;
-  int tried_cert=0, tried_pka=0, tried_ks=0;
   STRLIST namelist = NULL;
 
   add_to_strlist( &namelist, name );
- retry:
+
   rc = key_byname( NULL, namelist, pk, NULL, 0,
                    include_unusable, ret_keyblock, ret_kdbhd);
 
+  /* If the requested name resembles a valid mailbox and automatic
+     retrieval has been enabled, we try to import the key. */
+
   if (rc == G10ERR_NO_PUBKEY && is_valid_mailbox(name))
     {
       int res;
+      struct akl *akl;
 
-      if(!tried_cert
-        && (opt.keyserver_options.options&KEYSERVER_AUTO_CERT_RETRIEVE))
+      for(akl=opt.auto_key_locate;akl;akl=akl->next)
        {
-         tried_cert=1;
-
-         glo_ctrl.in_auto_key_retrieve++;
-         res=keyserver_import_cert(name);
-         glo_ctrl.in_auto_key_retrieve--;
-
-         if(res==0)
+         switch(akl->type)
            {
-             log_info(_("Automatically retrieved `%s' via %s\n"),
-                      name,"DNS CERT");
-             goto retry;
-           }
-       }
+           case AKL_CERT:
+             glo_ctrl.in_auto_key_retrieve++;
+             res=keyserver_import_cert(name);
+             glo_ctrl.in_auto_key_retrieve--;
 
-      if(!tried_pka
-        && opt.allow_pka_lookup
-        && (opt.keyserver_options.options&KEYSERVER_AUTO_PKA_RETRIEVE))
-       {
-         unsigned char fpr[MAX_FINGERPRINT_LEN];
-         /* If the requested name resembles a valid mailbox and
-            automatic retrieval via PKA records has been enabled, we
-            try to import the key via the URI and try again. */
+             if(res==0)
+               log_info(_("Automatically retrieved `%s' via %s\n"),
+                        name,"DNS CERT");
+             break;
 
-         tried_pka=1;
+           case AKL_PKA:
+             {
+               unsigned char fpr[MAX_FINGERPRINT_LEN];
 
-         glo_ctrl.in_auto_key_retrieve++;
-         res=keyserver_import_pka(name,fpr);
-         glo_ctrl.in_auto_key_retrieve--;
+               glo_ctrl.in_auto_key_retrieve++;
+               res=keyserver_import_pka(name,fpr);
+               glo_ctrl.in_auto_key_retrieve--;
 
-         if(res==0)
-           {
-             int i;
-             char fpr_string[2+(MAX_FINGERPRINT_LEN*2)+1];
+               if(res==0)
+                 {
+                   int i;
+                   char fpr_string[MAX_FINGERPRINT_LEN*2+1];
 
-             log_info(_("Automatically retrieved `%s' via %s\n"),
-                      name,"PKA");
+                   log_info(_("Automatically retrieved `%s' via %s\n"),
+                            name,"PKA");
 
-             free_strlist(namelist);
-             namelist=NULL;
+                   free_strlist(namelist);
+                   namelist=NULL;
 
-             for(i=0;i<MAX_FINGERPRINT_LEN;i++)
-               sprintf(fpr_string+2*i,"%02X",fpr[i]);
+                   for(i=0;i<MAX_FINGERPRINT_LEN;i++)
+                     sprintf(fpr_string+2*i,"%02X",fpr[i]);
 
-             add_to_strlist( &namelist, fpr_string );
+                   add_to_strlist( &namelist, fpr_string );
+                 }
+             }
+             break;
+
+           case AKL_LDAP:
+             glo_ctrl.in_auto_key_retrieve++;
+             res=keyserver_import_ldap(name);
+             glo_ctrl.in_auto_key_retrieve--;
+
+             if(res==0)
+               log_info(_("Automatically retrieved `%s' via %s\n"),
+                        name,"LDAP");
+             break;
+
+           case AKL_KEYSERVER:
+             /* Strictly speaking, we don't need to only use a valid
+                mailbox for the getname search, but it helps cut down
+                on the problem of searching for something like "john"
+                and getting a whole lot of keys back. */
+             if(opt.keyserver)
+               {
+                 glo_ctrl.in_auto_key_retrieve++;
+                 res=keyserver_import_name(name);
+                 glo_ctrl.in_auto_key_retrieve--;
 
-             goto retry;
+                 if(res==0)
+                   log_info(_("Automatically retrieved `%s' via %s\n"),
+                            name,opt.keyserver->uri);
+               }
+             break;
            }
-       }
-
-      /* Try keyserver last as it is likely to be the slowest.
-        Strictly speaking, we don't need to only use a valid mailbox
-        for the getname search, but it helps cut down on a problem
-        with searching for something like "john" and getting a lot of
-        keys back. */
-      if(!tried_ks
-        && opt.keyserver
-        && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE))
-       {
-         tried_ks=1;
-
-         glo_ctrl.in_auto_key_retrieve++;
-         res=keyserver_import_name(name);
-         glo_ctrl.in_auto_key_retrieve--;
 
-         if(res==0)
-           {
-             log_info(_("Automatically retrieved `%s' via %s\n"),
-                      name,opt.keyserver->uri);
-             goto retry;
-           }
+         rc = key_byname( NULL, namelist, pk, NULL, 0,
+                          include_unusable, ret_keyblock, ret_kdbhd);
+         if(rc!=G10ERR_NO_PUBKEY)
+           break;
        }
     }
 
@@ -2875,3 +2878,48 @@ get_ctx_handle(GETKEY_CTX ctx)
 {
   return ctx->kr_handle;
 }
+
+int
+parse_auto_key_locate(char *options)
+{
+  char *tok;
+
+  while((tok=optsep(&options)))
+    {
+      struct akl *akl,*last;
+
+      if(tok[0]=='\0')
+       continue;
+
+      akl=xmalloc_clear(sizeof(*akl));
+
+      if(ascii_strcasecmp(tok,"cert")==0)
+       akl->type=AKL_CERT;
+      else if(ascii_strcasecmp(tok,"pka")==0)
+       akl->type=AKL_PKA;
+      else if(ascii_strcasecmp(tok,"ldap")==0)
+       akl->type=AKL_LDAP;
+      else if(ascii_strcasecmp(tok,"keyserver")==0)
+       akl->type=AKL_KEYSERVER;
+      else
+       {
+         xfree(akl);
+         return 0;
+       }
+
+      /* We must maintain the order the user gave us */
+      for(last=opt.auto_key_locate;last && last->next;last=last->next)
+       {
+         /* Check for duplicates */
+         if(last && last->type==akl->type)
+           return 0;
+       }
+
+      if(last)
+       last->next=akl;
+      else
+       opt.auto_key_locate=akl;
+    }
+
+  return 1;
+}
index b2fb1a5..825fb7a 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -354,14 +354,13 @@ enum cmd_and_opt_values
     oKeyidFormat,
     oExitOnStatusWriteError,
     oLimitCardInsertTries,
-
     oReaderPort,
     octapiDriver,
     opcscDriver,
     oDisableCCID,
-
     oRequireBacksigs,
     oNoRequireBacksigs,
+    oAutoKeyLocate,
 
     oNoop
   };
@@ -707,6 +706,7 @@ static ARGPARSE_OPTS opts[] = {
     { oRecipient, "user", 2, "@" },
     { oRequireBacksigs, "require-backsigs", 0, "@"},
     { oNoRequireBacksigs, "no-require-backsigs", 0, "@"},
+    { oAutoKeyLocate, "auto-key-locate", 2, "@"},
     {0,NULL,0,NULL}
 };
 
@@ -2645,6 +2645,17 @@ main (int argc, char **argv )
          case oRequireBacksigs: opt.require_backsigs=1; break;
          case oNoRequireBacksigs: opt.require_backsigs=0; break;
 
+         case oAutoKeyLocate:
+           if(!parse_auto_key_locate(pargs.r.ret_str))
+             {
+               if(configname)
+                 log_error(_("%s:%d: invalid auto-key-locate list\n"),
+                           configname,configlineno);
+               else
+                 log_error(_("invalid auto-key-locate list\n"));
+             }
+           break;
+
          case oNoop: break;
 
          default : pargs.err = configfp? 1:2; break;
index bad6a2e..2c97b81 100644 (file)
@@ -258,6 +258,7 @@ char*get_long_user_id_string( u32 *keyid );
 char*get_user_id( u32 *keyid, size_t *rn );
 char*get_user_id_native( u32 *keyid );
 KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx);
+int parse_auto_key_locate(char *options);
 
 /*-- keyid.c --*/
 int pubkey_letter( int algo );
index af5c6f7..0b6f1c3 100644 (file)
@@ -220,6 +220,14 @@ struct
      error (but an invalid backsig still is). */
   int require_backsigs;
 
+  /* Linked list of ways to find a key if the key isn't on the local
+     keyring. */
+  struct akl
+  {
+    enum {AKL_CERT, AKL_PKA, AKL_LDAP, AKL_KEYSERVER} type;
+    struct akl *next;
+  } *auto_key_locate;
+
 } opt;
 
 /* CTRL is used to keep some global variables we currently can't