* main.h, seskey.c (encode_md_value): Modify to allow a q size greater
[gnupg.git] / g10 / getkey.c
index 7d91cde..1c85fb4 100644 (file)
@@ -1,6 +1,6 @@
 /* getkey.c -  Get a key from the database
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- *               2005 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ *               2006 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -917,56 +917,40 @@ get_pubkey_byname (PKT_public_key *pk,
 
   if (rc == G10ERR_NO_PUBKEY && is_valid_mailbox(name))
     {
-      int res;
       struct akl *akl;
 
       for(akl=opt.auto_key_locate;akl;akl=akl->next)
        {
+         unsigned char *fpr;
+         size_t fpr_len;
+
          switch(akl->type)
            {
            case AKL_CERT:
              glo_ctrl.in_auto_key_retrieve++;
-             res=keyserver_import_cert(name);
+             rc=keyserver_import_cert(name,&fpr,&fpr_len);
              glo_ctrl.in_auto_key_retrieve--;
 
-             if(res==0)
+             if(rc==0)
                log_info(_("Automatically retrieved `%s' via %s\n"),
                         name,"DNS CERT");
              break;
 
            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--;
-
-               if(res==0)
-                 {
-                   int i;
-                   char fpr_string[MAX_FINGERPRINT_LEN*2+1];
-
-                   log_info(_("Automatically retrieved `%s' via %s\n"),
-                            name,"PKA");
-
-                   free_strlist(namelist);
-                   namelist=NULL;
-
-                   for(i=0;i<MAX_FINGERPRINT_LEN;i++)
-                     sprintf(fpr_string+2*i,"%02X",fpr[i]);
+             glo_ctrl.in_auto_key_retrieve++;
+             rc=keyserver_import_pka(name,&fpr,&fpr_len);
 
-                   add_to_strlist( &namelist, fpr_string );
-                 }
-             }
+             if(rc==0)
+               log_info(_("Automatically retrieved `%s' via %s\n"),
+                        name,"PKA");
              break;
 
            case AKL_LDAP:
              glo_ctrl.in_auto_key_retrieve++;
-             res=keyserver_import_ldap(name);
+             rc=keyserver_import_ldap(name,&fpr,&fpr_len);
              glo_ctrl.in_auto_key_retrieve--;
 
-             if(res==0)
+             if(rc==0)
                log_info(_("Automatically retrieved `%s' via %s\n"),
                         name,"LDAP");
              break;
@@ -979,14 +963,57 @@ get_pubkey_byname (PKT_public_key *pk,
              if(opt.keyserver)
                {
                  glo_ctrl.in_auto_key_retrieve++;
-                 res=keyserver_import_name(name);
+                 rc=keyserver_import_name(name,&fpr,&fpr_len,opt.keyserver);
                  glo_ctrl.in_auto_key_retrieve--;
 
-                 if(res==0)
+                 if(rc==0)
                    log_info(_("Automatically retrieved `%s' via %s\n"),
                             name,opt.keyserver->uri);
                }
              break;
+
+           case AKL_SPEC:
+             {
+               struct keyserver_spec *keyserver;
+
+               keyserver=keyserver_match(akl->spec);
+               glo_ctrl.in_auto_key_retrieve++;
+               rc=keyserver_import_name(name,&fpr,&fpr_len,keyserver);
+               glo_ctrl.in_auto_key_retrieve--;
+
+               if(rc==0)
+                 log_info(_("Automatically retrieved `%s' via %s\n"),
+                          name,akl->spec->uri);
+             }
+             break;
+           }
+
+         /* Use the fingerprint of the key that we actually fetched.
+            This helps prevent problems where the key that we fetched
+            doesn't have the same name that we used to fetch it.  In
+            the case of CERT and PKA, this is an actual security
+            requirement as the URL might point to a key put in by an
+            attacker.  By forcing the use of the fingerprint, we
+            won't use the attacker's key here. */
+         if(rc==0 && fpr)
+           {
+             int i;
+             char fpr_string[MAX_FINGERPRINT_LEN*2+1];
+
+             assert(fpr_len<=MAX_FINGERPRINT_LEN);
+
+             free_strlist(namelist);
+             namelist=NULL;
+
+             for(i=0;i<fpr_len;i++)
+               sprintf(fpr_string+2*i,"%02X",fpr[i]);
+
+             if(opt.verbose)
+               log_info("auto-key-locate found fingerprint %s\n",fpr_string);
+
+             add_to_strlist( &namelist, fpr_string );
+
+             xfree(fpr);
            }
 
          rc = key_byname( NULL, namelist, pk, NULL, 0,
@@ -2879,6 +2906,26 @@ get_ctx_handle(GETKEY_CTX ctx)
   return ctx->kr_handle;
 }
 
+static void
+free_akl(struct akl *akl)
+{
+  if(akl->spec)
+    free_keyserver_spec(akl->spec);
+
+  xfree(akl);
+}
+
+void
+release_akl(void)
+{
+  while(opt.auto_key_locate)
+    {
+      struct akl *akl2=opt.auto_key_locate;
+      opt.auto_key_locate=opt.auto_key_locate->next;
+      free_akl(akl2);
+    }
+}
+
 int
 parse_auto_key_locate(char *options)
 {
@@ -2887,23 +2934,30 @@ parse_auto_key_locate(char *options)
   while((tok=optsep(&options)))
     {
       struct akl *akl,*last;
+      int dupe=0;
 
       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)
+      if(ascii_strcasecmp(tok,"ldap")==0)
        akl->type=AKL_LDAP;
       else if(ascii_strcasecmp(tok,"keyserver")==0)
        akl->type=AKL_KEYSERVER;
+#ifdef USE_DNS_CERT
+      else if(ascii_strcasecmp(tok,"cert")==0)
+       akl->type=AKL_CERT;
+#endif
+#ifdef USE_DNS_PKA
+      else if(ascii_strcasecmp(tok,"pka")==0)
+       akl->type=AKL_PKA;
+#endif
+      else if((akl->spec=parse_keyserver_uri(tok,1,NULL,0)))
+       akl->type=AKL_SPEC;
       else
        {
-         xfree(akl);
+         free_akl(akl);
          return 0;
        }
 
@@ -2911,14 +2965,24 @@ parse_auto_key_locate(char *options)
       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->type==akl->type
+            && (akl->type!=AKL_SPEC
+                || (akl->type==AKL_SPEC
+                    && strcmp(last->spec->uri,akl->spec->uri)==0)))
+           {
+             dupe=1;
+             free_akl(akl);
+             break;
+           }
        }
 
-      if(last)
-       last->next=akl;
-      else
-       opt.auto_key_locate=akl;
+      if(!dupe)
+       {
+         if(last)
+           last->next=akl;
+         else
+           opt.auto_key_locate=akl;
+       }
     }
 
   return 1;