* options.h, getkey.c (merge_selfsigs_subkey), gpg.c (main), sig-check.c
[gnupg.git] / g10 / getkey.c
index 9cc0cbb..241f153 100644 (file)
@@ -1,6 +1,6 @@
 /* getkey.c -  Get a key from the database
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
- *               2004 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ *               2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
@@ -34,6 +35,7 @@
 #include "main.h"
 #include "trustdb.h"
 #include "i18n.h"
+#include "keyserver-internal.h"
 
 #define MAX_PK_CACHE_ENTRIES   PK_UID_CACHE_SIZE
 #define MAX_UID_CACHE_ENTRIES  PK_UID_CACHE_SIZE
@@ -151,7 +153,7 @@ cache_public_key( PKT_public_key *pk )
        return;
     }
     pk_cache_entries++;
-    ce = m_alloc( sizeof *ce );
+    ce = xmalloc( sizeof *ce );
     ce->next = pk_cache;
     pk_cache = ce;
     ce->pk = copy_public_key( NULL, pk );
@@ -194,7 +196,7 @@ release_keyid_list ( keyid_list_t k )
 {
     while (  k ) {
         keyid_list_t k2 = k->next;
-        m_free (k);
+        xfree (k);
         k = k2;
     }
 }
@@ -215,7 +217,7 @@ cache_user_id( KBNODE keyblock )
     for (k=keyblock; k; k = k->next ) {
         if ( k->pkt->pkttype == PKT_PUBLIC_KEY
              || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
-            keyid_list_t a = m_alloc_clear ( sizeof *a );
+            keyid_list_t a = xmalloc_clear ( sizeof *a );
             /* Hmmm: For a long list of keyids it might be an advantage
              * to append the keys */
             keyid_from_pk( k->pkt->pkt.public_key, a->keyid );
@@ -228,7 +230,7 @@ cache_user_id( KBNODE keyblock )
                         if( DBG_CACHE )
                             log_debug("cache_user_id: already in cache\n");
                         release_keyid_list ( keyids );
-                        m_free ( a );
+                        xfree ( a );
                         return;
                     }
                 }
@@ -249,10 +251,10 @@ cache_user_id( KBNODE keyblock )
        r = user_id_db;
        user_id_db = r->next;
         release_keyid_list ( r->keyids );
-       m_free(r);
+       xfree(r);
        uid_cache_entries--;
     }
-    r = m_alloc( sizeof *r + uidlen-1 );
+    r = xmalloc( sizeof *r + uidlen-1 );
     r->keyids = keyids;
     r->len = uidlen;
     memcpy(r->name, uid, r->len);
@@ -272,7 +274,7 @@ getkey_disable_caches()
        for( ce = pk_cache; ce; ce = ce2 ) {
            ce2 = ce->next;
            free_public_key( ce->pk );
-           m_free( ce );
+           xfree( ce );
        }
        pk_cache_disabled=1;
        pk_cache_entries = 0;
@@ -337,7 +339,7 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
 #endif
     /* more init stuff */
     if( !pk ) {
-       pk = m_alloc_clear( sizeof *pk );
+       pk = xmalloc_clear( sizeof *pk );
        internal++;
     }
 
@@ -588,11 +590,13 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc )
        case 0:    /* empty string is an error */
            return 0;
 
+#if 0
        case '.':  /* an email address, compare from end */
            mode = KEYDB_SEARCH_MODE_MAILEND;
            s++;
             desc->u.name = s;
            break;
+#endif
 
        case '<':  /* an email address */
            mode = KEYDB_SEARCH_MODE_MAIL;
@@ -617,11 +621,13 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc )
             desc->u.name = s;
            break;
 
+#if 0
        case '+':  /* compare individual words */
            mode = KEYDB_SEARCH_MODE_WORDS;
            s++;
             desc->u.name = s;
            break;
+#endif
 
        case '#':  /* local user id */
             return 0; /* This is now obsolete and van't not be used anymore*/
@@ -809,7 +815,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
 
     if(!namelist)
       {
-       ctx = m_alloc_clear (sizeof *ctx);
+       ctx = xmalloc_clear (sizeof *ctx);
        ctx->nitems = 1;
        ctx->items[0].mode=KEYDB_SEARCH_MODE_FIRST;
        if(!include_unusable)
@@ -821,7 +827,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
        for(n=0, r=namelist; r; r = r->next )
          n++;
 
-       ctx = m_alloc_clear (sizeof *ctx + (n-1)*sizeof ctx->items );
+       ctx = xmalloc_clear (sizeof *ctx + (n-1)*sizeof ctx->items );
        ctx->nitems = n;
 
        for(n=0, r=namelist; r; r = r->next, n++ )
@@ -832,7 +838,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
              ctx->exact = 1;
            if (!ctx->items[n].mode)
              {
-               m_free (ctx);
+               xfree (ctx);
                return G10ERR_INV_USER_ID;
              }
            if(!include_unusable
@@ -885,24 +891,59 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
     return rc;
 }
 
-/*
- * Find a public key from NAME and returh the keyblock or the key.
- * If ret_kdb is not NULL, the KEYDB handle used to locate this keyblock is
- * returned and the caller is responsible for closing it.
- */
+
+
+/* Find a public key from NAME and return the keyblock or the key.  If
+   ret_kdb is not NULL, the KEYDB handle used to locate this keyblock
+   is returned and the caller is responsible for closing it.  If a key
+   was not found and NAME is a valid RFC822 mailbox and PKA retrieval
+   has been enabled, we try to import the pkea via the PKA
+   mechanism. */
 int
 get_pubkey_byname (PKT_public_key *pk,
                   const char *name, KBNODE *ret_keyblock,
                    KEYDB_HANDLE *ret_kdbhd, int include_unusable )
 {
-    int rc;
-    STRLIST namelist = NULL;
+  int rc;
+  int again = 0;
+  STRLIST namelist = NULL;
 
-    add_to_strlist( &namelist, name );
-    rc = key_byname( NULL, namelist, pk, NULL, 0,
-                    include_unusable, ret_keyblock, ret_kdbhd);
-    free_strlist( namelist );
-    return rc;
+  add_to_strlist( &namelist, name );
+ retry:
+  rc = key_byname( NULL, namelist, pk, NULL, 0,
+                   include_unusable, ret_keyblock, ret_kdbhd);
+  if (rc == G10ERR_NO_PUBKEY
+      && !again
+      && (opt.keyserver_options.options&KEYSERVER_AUTO_PKA_RETRIEVE)
+      && is_valid_mailbox (name))
+    {
+      /* 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. */
+      unsigned char fpr[MAX_FINGERPRINT_LEN];
+      char *uri;
+      struct keyserver_spec *spec;
+      
+      uri = get_pka_info (name, fpr);
+      if (uri)
+        {
+          spec = parse_keyserver_uri (uri, 0, NULL, 0);
+          if (spec)
+            {
+              glo_ctrl.in_auto_key_retrieve++;
+              if (!keyserver_import_fprint (fpr, 20, spec))
+                again = 1;
+              glo_ctrl.in_auto_key_retrieve--;
+              free_keyserver_spec (spec);
+            }
+          xfree (uri);
+        }
+      if (again)
+        goto retry;
+    }
+
+  free_strlist( namelist );
+  return rc;
 }
 
 int
@@ -931,7 +972,7 @@ get_pubkey_end( GETKEY_CTX ctx )
         memset (&ctx->kbpos, 0, sizeof ctx->kbpos);
         keydb_release (ctx->kr_handle);
        if( !ctx->not_allocated )
-           m_free( ctx );
+           xfree( ctx );
     }
 }
 
@@ -1059,14 +1100,20 @@ get_seckey_byname2( GETKEY_CTX *retctx,
                    KBNODE *retblock )
 {
   STRLIST namelist = NULL;
-  int rc;
+  int rc,include_unusable=1;
+
+  /* If we have no name, try to use the default secret key.  If we
+     have no default, we'll use the first usable one. */
 
   if( !name && opt.def_secret_key && *opt.def_secret_key )
     add_to_strlist( &namelist, opt.def_secret_key );
   else if(name)
     add_to_strlist( &namelist, name );
+  else
+    include_unusable=0;
 
-  rc = key_byname( retctx, namelist, NULL, sk, 1, 1, retblock, NULL );
+  rc = key_byname( retctx, namelist, NULL, sk, 1, include_unusable,
+                  retblock, NULL );
 
   free_strlist( namelist );
 
@@ -1139,13 +1186,41 @@ get_seckey_byfprint( PKT_secret_key *sk,
         if (!rc && sk )
             sk_from_block ( &ctx, sk, kb );
         release_kbnode ( kb );
-       get_pubkey_end( &ctx );
+       get_seckey_end( &ctx );
     }
     else
        rc = G10ERR_GENERAL; /* Oops */
     return rc;
 }
 
+
+/* Search for a secret key with the given fingerprint and return the
+   complete keyblock which may have more than only this key. */
+int
+get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint,
+                          size_t fprint_len )
+{
+  int rc;
+  struct getkey_ctx_s ctx;
+  
+  if (fprint_len != 20 && fprint_len == 16)
+    return G10ERR_GENERAL; /* Oops */
+    
+  memset (&ctx, 0, sizeof ctx);
+  ctx.not_allocated = 1;
+  ctx.kr_handle = keydb_new (1);
+  ctx.nitems = 1;
+  ctx.items[0].mode = (fprint_len==16
+                       ? KEYDB_SEARCH_MODE_FPR16
+                       : KEYDB_SEARCH_MODE_FPR20);
+  memcpy (ctx.items[0].u.fpr, fprint, fprint_len);
+  rc = lookup (&ctx, ret_keyblock, 1);
+  get_seckey_end (&ctx);
+  
+  return rc;
+}
+
+
 \f
 /************************************************
  ************* Merging stuff ********************
@@ -1256,16 +1331,24 @@ parse_key_usage(PKT_signature *sig)
       /* first octet of the keyflags */
       flags=*p;
 
-      if(flags & 3)
+      if(flags & 1)
+       {
+         key_usage |= PUBKEY_USAGE_CERT;
+         flags&=~1;
+       }
+
+      if(flags & 2)
        {
          key_usage |= PUBKEY_USAGE_SIG;
-         flags&=~3;
+         flags&=~2;
        }
 
-      if(flags & 12)
+      /* We do not distinguish between encrypting communications and
+        encrypting storage. */
+      if(flags & (0x04|0x08))
        {
          key_usage |= PUBKEY_USAGE_ENC;
-         flags&=~12;
+         flags&=~(0x04|0x08);
        }
 
       if(flags & 0x20)
@@ -1312,11 +1395,18 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
         return; /* has been revoked */
     }
 
+    uid->expiredate = sig->expiredate;
+
+    if(sig->flags.expired)
+      {
+       uid->is_expired = 1;
+       return; /* has expired */
+      }
+
     uid->created = sig->timestamp; /* this one is okay */
     uid->selfsigversion = sig->version;
     /* If we got this far, it's not expired :) */
     uid->is_expired = 0;
-    uid->expiredate = sig->expiredate;
 
     /* store the key flags in the helper variable for later processing */
     uid->help_key_usage=parse_key_usage(sig);
@@ -1350,12 +1440,12 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
     p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_COMPR, &n );
     zip = p; nzip = p?n:0;
     if (uid->prefs) 
-        m_free (uid->prefs);
+        xfree (uid->prefs);
     n = nsym + nhash + nzip;
     if (!n)
         uid->prefs = NULL;
     else {
-        uid->prefs = m_alloc (sizeof (*uid->prefs) * (n+1));
+        uid->prefs = xmalloc (sizeof (*uid->prefs) * (n+1));
         n = 0;
         for (; nsym; nsym--, n++) {
             uid->prefs[n].type = PREFTYPE_SYM;
@@ -1435,7 +1525,7 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
      */
 
     /* In case this key was already merged */
-    m_free(pk->revkey);
+    xfree(pk->revkey);
     pk->revkey=NULL;
     pk->numrevkeys=0;
 
@@ -1472,7 +1562,7 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
                    int i;
 
                    pk->revkey=
-                     m_realloc(pk->revkey,sizeof(struct revocation_key)*
+                     xrealloc(pk->revkey,sizeof(struct revocation_key)*
                                (pk->numrevkeys+sig->numrevkeys));
 
                    for(i=0;i<sig->numrevkeys;i++)
@@ -1523,7 +1613,7 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
          }
 
        if(changed)
-         pk->revkey=m_realloc(pk->revkey,
+         pk->revkey=xrealloc(pk->revkey,
                               pk->numrevkeys*sizeof(struct revocation_key));
       }
 
@@ -1608,7 +1698,8 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
                 if ( check_key_signature( keyblock, k, NULL ) )
                     ; /* signature did not verify */
                 else if ( (IS_UID_SIG (sig) || IS_UID_REV (sig))
-                          && sig->timestamp >= sigdate ) {
+                          && sig->timestamp >= sigdate )
+                 {
                     /* Note: we allow to invalidate cert revocations
                      * by a newer signature.  An attacker can't use this
                      * because a key should be revoced with a key revocation.
@@ -1617,22 +1708,13 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
                      * the same email address may become valid again (hired,
                      * fired, hired again).
                      */
-                   if(sig->flags.expired)
-                     {
-                       uidnode->pkt->pkt.user_id->is_expired=1;
-                       signode = NULL;
-                     }
-                    else
-                     {
-                       uidnode->pkt->pkt.user_id->is_expired=0;
-                       signode = k;
-                     }
 
                    sigdate = sig->timestamp;
-                   uidnode->pkt->pkt.user_id->expiredate=sig->expiredate;
+                   signode = k;
+                   signode->pkt->pkt.signature->flags.chosen_selfsig=0;
                    if( sig->version > sigversion )
                      sigversion = sig->version;
-                }
+                 }
             }
         }
     }
@@ -1669,7 +1751,7 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
                  {
                    PKT_public_key *ultimate_pk;
 
-                   ultimate_pk=m_alloc_clear(sizeof(*ultimate_pk));
+                   ultimate_pk=xmalloc_clear(sizeof(*ultimate_pk));
 
                     /* We don't want to use the full get_pubkey to
                        avoid infinite recursion in certain cases.
@@ -1909,14 +1991,17 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
                      * figure out other information like the old expiration
                      * time */
                 }
-                else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate ) {
+                else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate )
+                 {
                    if(sig->flags.expired)
-                        ; /* signature has expired - ignore it */
-                    else {
+                     ; /* signature has expired - ignore it */
+                    else
+                     {
                         sigdate = sig->timestamp;
                         signode = k;
-                    }
-                }
+                       signode->pkt->pkt.signature->flags.chosen_selfsig=0;
+                     }
+                 }
             }
         }
     }
@@ -1958,14 +2043,11 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
 
     subpk->is_valid = 1;
 
-#ifndef DO_BACKSIGS
-    /* Pretend the backsig is present and accounted for. */
-    subpk->backsig=2;
-#else
     /* Find the first 0x19 embedded signature on our self-sig. */
     if(subpk->backsig==0)
       {
        int seq=0;
+       size_t n;
 
        while((p=enum_sig_subpkt(sig->hashed,
                                 SIGSUBPKT_SIGNATURE,&n,&seq,NULL)))
@@ -1985,7 +2067,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
 
        if(p)
          {
-           PKT_signature *backsig=m_alloc_clear(sizeof(PKT_signature));
+           PKT_signature *backsig=xmalloc_clear(sizeof(PKT_signature));
            IOBUF backsig_buf=iobuf_temp_with_content(p,n);
 
            if(parse_signature(backsig_buf,PKT_SIGNATURE,n,backsig)==0)
@@ -2000,7 +2082,6 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
            free_seckey_enc(backsig);
          }
       }
-#endif
 }
 
 
@@ -2095,7 +2176,7 @@ merge_selfsigs( KBNODE keyblock )
              || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
             PKT_public_key *pk = k->pkt->pkt.public_key;
             if (pk->prefs)
-                m_free (pk->prefs);
+                xfree (pk->prefs);
             pk->prefs = copy_prefs (prefs);
             pk->mdc_feature = mdc_feature;
         }
@@ -2426,10 +2507,10 @@ finish_lookup (GETKEY_CTX ctx)
     if (latest_key != keyblock && opt.verbose)
       {
        char *tempkeystr=
-         m_strdup(keystr_from_pk(latest_key->pkt->pkt.public_key));
+         xstrdup(keystr_from_pk(latest_key->pkt->pkt.public_key));
         log_info(_("using subkey %s instead of primary key %s\n"),
                  tempkeystr, keystr_from_pk(keyblock->pkt->pkt.public_key));
-       m_free(tempkeystr);
+       xfree(tempkeystr);
       }
 
     cache_user_id( keyblock );
@@ -2572,7 +2653,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk,
 
 
     if( !c ) { /* make a new context */
-       c = m_alloc_clear( sizeof *c );
+       c = xmalloc_clear( sizeof *c );
        *context = c;
        c->hd = keydb_new (1);
         c->first = 1;
@@ -2583,7 +2664,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk,
     if( !sk ) { /* free the context */
         keydb_release (c->hd);
         release_kbnode (c->keyblock);
-       m_free( c );
+       xfree( c );
        *context = NULL;
        return 0;
     }
@@ -2630,7 +2711,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk,
 
 /****************
  * Return a string with a printable representation of the user_id.
- * this string must be freed by m_free.
+ * this string must be freed by xfree.
  */
 char*
 get_user_id_string( u32 *keyid )
@@ -2648,14 +2729,14 @@ get_user_id_string( u32 *keyid )
            {
              if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] )
                {
-                 p = m_alloc( keystrlen() + 1 + r->len + 1 );
+                 p = xmalloc( keystrlen() + 1 + r->len + 1 );
                  sprintf(p, "%s %.*s", keystr(keyid), r->len, r->name );
                  return p;
                }
            }
         }
     } while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
-  p = m_alloc( keystrlen() + 5 );
+  p = xmalloc( keystrlen() + 5 );
   sprintf(p, "%s [?]", keystr(keyid));
   return p;
 }
@@ -2666,7 +2747,7 @@ get_user_id_string_native ( u32 *keyid )
 {
   char *p = get_user_id_string( keyid );
   char *p2 = utf8_to_native( p, strlen(p), 0 );
-  m_free(p);
+  xfree(p);
   return p2;
 }
 
@@ -2683,7 +2764,7 @@ get_long_user_id_string( u32 *keyid )
             keyid_list_t a;
             for (a=r->keyids; a; a= a->next ) {
                 if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) {
-                    p = m_alloc( r->len + 20 );
+                    p = xmalloc( r->len + 20 );
                     sprintf(p, "%08lX%08lX %.*s",
                             (ulong)keyid[0], (ulong)keyid[1],
                             r->len, r->name );
@@ -2692,7 +2773,7 @@ get_long_user_id_string( u32 *keyid )
             }
         }
     } while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
-    p = m_alloc( 25 );
+    p = xmalloc( 25 );
     sprintf(p, "%08lX%08lX [?]", (ulong)keyid[0], (ulong)keyid[1] );
     return p;
 }
@@ -2710,7 +2791,7 @@ get_user_id( u32 *keyid, size_t *rn )
             keyid_list_t a;
             for (a=r->keyids; a; a= a->next ) {
                 if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) {
-                    p = m_alloc( r->len );
+                    p = xmalloc( r->len );
                     memcpy(p, r->name, r->len );
                     *rn = r->len;
                     return p;
@@ -2718,7 +2799,7 @@ get_user_id( u32 *keyid, size_t *rn )
             }
         }
     } while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
-    p = m_strdup( _("[User ID not found]") );
+    p = xstrdup( _("[User ID not found]") );
     *rn = strlen(p);
     return p;
 }
@@ -2729,7 +2810,7 @@ get_user_id_native( u32 *keyid )
   size_t rn;
   char *p = get_user_id( keyid, &rn );
   char *p2 = utf8_to_native( p, rn, 0 );
-  m_free(p);
+  xfree(p);
   return p2;
 }