Ported patches from 1.4.x
authorWerner Koch <wk@gnupg.org>
Tue, 27 Jun 2006 14:30:59 +0000 (14:30 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 27 Jun 2006 14:30:59 +0000 (14:30 +0000)
g10/ChangeLog
g10/build-packet.c
g10/exec.c
g10/getkey.c
g10/gpg.c
g10/import.c
g10/keygen.c
g10/options.h
g10/parse-packet.c
g10/sign.c

index 47e9a73..4a83825 100644 (file)
@@ -1,3 +1,63 @@
+2006-06-27  Werner Koch  <wk@g10code.com>
+
+       Applied patches from 1.4.x (2006-05-22 to 2006-06-23) from David:
+
+       * keygen.c (keygen_upd_std_prefs, keygen_add_std_prefs)
+       (proc_parameter_file): Add --default-keyserver-url to specify a
+       keyserver URL at key generation time, and "Keyserver:" keyword for
+       doing the same through a batch file.
+       * options.h, gpg.c (main): Ditto.
+
+       * sign.c (do_sign): For now don't accept a truncated hash even
+       for DSA1 keys (be liberal in what you accept, etc).
+
+       * import.c (import_one): Add a flag (from_sk) so we don't check
+       prefs on an autoconverted public key.  The check should only
+       happen on the sk side.  Noted by Dirk Traulsen.
+
+       * keygen.c (gen_card_key): Add optional argument to return a
+       pointer (not a copy) of the stub secret key for the secret key we
+       just generated on the card.
+       (generate_card_subkeypair): Use it here so that the signing key on
+       the card can use the card to generate the 0x19 backsig on the
+       primary key.  Noted by Janko Heilgeist and Jonas Oberg.
+
+       * parse-packet.c (parse_user_id): Cap the user ID size at 2048
+       bytes.  This prevents a memory allocation attack with a very large
+       user ID.  A very large packet length could even cause the
+       allocation (a u32) to wrap around to a small number.  Noted by
+       Evgeny Legerov on full-disclosure.
+
+       * keygen.c (gen_dsa): Allow generating DSA2 keys.  Allow
+       specifying sizes > 1024 when --enable-dsa2 is set.  The size of q
+       is set automatically based on the key size.
+       (ask_keysize, generate_keypair): Ask for DSA size when
+       --enable-dsa2 is set.
+
+       * exec.c (make_tempdir) [W32]: Fix bug with a temporary directory
+       on W32 that is over 256 bytes long.  Noted by Israel G. Lugo.
+
+       * gpg.c (reopen_std): New function to reopen fd 0, 1, or 2 if we
+       are called with them closed.  This is to protect our
+       keyring/trustdb files from corruption if they get attached to one
+       of the standard fds.  Print a warning if possible that this has
+       happened, and fail completely if we cannot reopen (should never
+       happen).
+       (main): Call it here.
+       
+       * parse-packet.c (dump_sig_subpkt, parse_signature): Fix meaning
+       of key expiration and sig expiration subpackets - zero means
+       "never expire" according to 2440, not "expire instantly".
+       * build-packet.c (build_sig_subpkt_from_sig): Ditto.
+       * getkey.c (fixup_uidnode, merge_selfsigs_main)
+       (merge_selfsigs_subkey): Ditto.
+       * keygen.c (keygen_add_key_expire): Ditto.
+
+       * getkey.c (get_pubkey_byname)
+       * import.c (import_one): Fix key selection problem when
+       auto-key-locate returns a list of keys, not all of which are
+       usable (revoked, expired, etc).  Noted by Simon Josefsson.
+
 2006-05-24  Werner Koch  <wk@g10code.com>
 
        * keyid.c (hash_public_key): Do not double hash the length bytes,
 2006-05-24  Werner Koch  <wk@g10code.com>
 
        * keyid.c (hash_public_key): Do not double hash the length bytes,
index cbf0374..8784819 100644 (file)
@@ -841,7 +841,8 @@ build_sig_subpkt_from_sig( PKT_signature *sig )
        if(sig->expiredate>sig->timestamp)
          u=sig->expiredate-sig->timestamp;
        else
        if(sig->expiredate>sig->timestamp)
          u=sig->expiredate-sig->timestamp;
        else
-         u=0;
+         u=1; /* A 1-second expiration time is the shortest one
+                 OpenPGP has */
 
        buf[0] = (u >> 24) & 0xff;
        buf[1] = (u >> 16) & 0xff;
 
        buf[0] = (u >> 24) & 0xff;
        buf[1] = (u >> 16) & 0xff;
index 6938a40..203c4c7 100644 (file)
@@ -127,8 +127,11 @@ static int make_tempdir(struct exec_info *info)
   if(tmp==NULL)
     {
 #if defined (_WIN32)
   if(tmp==NULL)
     {
 #if defined (_WIN32)
-      tmp=xmalloc(256);
-      if(GetTempPath(256,tmp)==0)
+      int err;
+
+      tmp=xmalloc(MAX_PATH+2);
+      err=GetTempPath(MAX_PATH+1,tmp);
+      if(err==0 || err>MAX_PATH+1)
        strcpy(tmp,"c:\\windows\\temp");
       else
        {
        strcpy(tmp,"c:\\windows\\temp");
       else
        {
index bff2a0d..c0088c3 100644 (file)
@@ -935,7 +935,7 @@ get_pubkey_byname (PKT_public_key *pk,
 
       for(akl=opt.auto_key_locate;akl;akl=akl->next)
        {
 
       for(akl=opt.auto_key_locate;akl;akl=akl->next)
        {
-         unsigned char *fpr;
+         unsigned char *fpr=NULL;
          size_t fpr_len;
 
          switch(akl->type)
          size_t fpr_len;
 
          switch(akl->type)
@@ -1507,12 +1507,12 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
     /* store the key flags in the helper variable for later processing */
     uid->help_key_usage=parse_key_usage(sig);
 
     /* store the key flags in the helper variable for later processing */
     uid->help_key_usage=parse_key_usage(sig);
 
-    /* ditto or the key expiration */
-    uid->help_key_expire = 0;
+    /* ditto for the key expiration */
     p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
     p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
-    if ( p ) { 
-        uid->help_key_expire = keycreated + buffer_to_u32(p);
-    }
+    if( p && buffer_to_u32(p) )
+      uid->help_key_expire = keycreated + buffer_to_u32(p);
+    else
+      uid->help_key_expire = 0;
 
     /* Set the primary user ID flag - we will later wipe out some
      * of them to only have one in our keyblock */
 
     /* Set the primary user ID flag - we will later wipe out some
      * of them to only have one in our keyblock */
@@ -1724,7 +1724,7 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
        key_usage=parse_key_usage(sig);
 
        p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
        key_usage=parse_key_usage(sig);
 
        p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
-       if ( p )
+       if( p && buffer_to_u32(p) )
          {
            key_expire = keytimestamp + buffer_to_u32(p);
            key_expire_seen = 1;
          {
            key_expire = keytimestamp + buffer_to_u32(p);
            key_expire_seen = 1;
@@ -2128,7 +2128,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
     subpk->pubkey_usage = key_usage;
     
     p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
     subpk->pubkey_usage = key_usage;
     
     p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
-    if ( p 
+    if ( p && buffer_to_u32(p) )
         key_expire = keytimestamp + buffer_to_u32(p);
     else
         key_expire = 0;
         key_expire = keytimestamp + buffer_to_u32(p);
     else
         key_expire = 0;
index 4235f3f..c1a0be5 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -328,6 +328,7 @@ enum cmd_and_opt_values
     oNoAutoCheckTrustDB,
     oPreservePermissions,
     oDefaultPreferenceList,
     oNoAutoCheckTrustDB,
     oPreservePermissions,
     oDefaultPreferenceList,
+    oDefaultKeyserverURL,
     oPersonalCipherPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
     oPersonalCipherPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
@@ -659,6 +660,7 @@ static ARGPARSE_OPTS opts[] = {
     { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"},
     { oPreservePermissions, "preserve-permissions", 0, "@"},
     { oDefaultPreferenceList,  "default-preference-list", 2, "@"},
     { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"},
     { oPreservePermissions, "preserve-permissions", 0, "@"},
     { oDefaultPreferenceList,  "default-preference-list", 2, "@"},
+    { oDefaultKeyserverURL,  "default-keyserver-url", 2, "@"},
     { oPersonalCipherPreferences,  "personal-cipher-preferences", 2, "@"},
     { oPersonalDigestPreferences,  "personal-digest-preferences", 2, "@"},
     { oPersonalCompressPreferences,  "personal-compress-preferences", 2, "@"},
     { oPersonalCipherPreferences,  "personal-cipher-preferences", 2, "@"},
     { oPersonalDigestPreferences,  "personal-digest-preferences", 2, "@"},
     { oPersonalCompressPreferences,  "personal-compress-preferences", 2, "@"},
@@ -1643,6 +1645,78 @@ parse_trust_model(const char *model)
     log_error("unknown trust model `%s'\n",model);
 }
 
     log_error("unknown trust model `%s'\n",model);
 }
 
+
+
+/* Make sure that the standard file descriptors are opened. Obviously
+   some folks close them before an exec and the next file we open will
+   get one of them assigned and thus any output (i.e. diagnostics) end
+   up in that file (e.g. the trustdb).  Not actually a gpg problem as
+   this will hapenn with almost all utilities when called in a wrong
+   way.  However we try to minimize the damage here and raise
+   awareness of the problem.
+
+   Must be called before we open any files! */
+static void
+reopen_std(void)
+{  
+#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
+  struct stat statbuf;
+  int did_stdin=0,did_stdout=0,did_stderr=0;
+  FILE *complain;
+
+  if(fstat(STDIN_FILENO,&statbuf)==-1 && errno==EBADF)
+    {
+      if(open("/dev/null",O_RDONLY)==STDIN_FILENO)
+       did_stdin=1;
+      else
+       did_stdin=2;
+    }
+
+  if(fstat(STDOUT_FILENO,&statbuf)==-1 && errno==EBADF)
+    {
+      if(open("/dev/null",O_WRONLY)==STDOUT_FILENO)
+       did_stdout=1;
+      else
+       did_stdout=2;
+    }
+
+  if(fstat(STDERR_FILENO,&statbuf)==-1 && errno==EBADF)
+    {
+      if(open("/dev/null",O_WRONLY)==STDERR_FILENO)
+       did_stderr=1;
+      else
+       did_stderr=2;
+    }
+
+  /* It's hard to log this sort of thing since the filehandle we would
+     complain to may be closed... */
+  if(did_stderr==0)
+    complain=stderr;
+  else if(did_stdout==0)
+    complain=stdout;
+  else
+    complain=NULL;
+
+  if(complain)
+    {
+      if(did_stdin==1)
+       fprintf(complain,"gpg: WARNING: standard input reopened\n");
+      if(did_stdout==1)
+       fprintf(complain,"gpg: WARNING: standard output reopened\n");
+      if(did_stderr==1)
+       fprintf(complain,"gpg: WARNING: standard error reopened\n");
+
+      if(did_stdin==2 || did_stdout==2 || did_stderr==2)
+       fprintf(complain,"gpg: fatal: unable to reopen standard input,"
+               " output, or error\n");
+    }
+
+  if(did_stdin==2 || did_stdout==2 || did_stderr==2)
+    exit(3);
+#endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
+}
+
+
 int
 main (int argc, char **argv )
 {
 int
 main (int argc, char **argv )
 {
@@ -1697,7 +1771,7 @@ main (int argc, char **argv )
     /* Please note that we may running SUID(ROOT), so be very CAREFUL
        when adding any stuff between here and the call to
        secmem_init() somewhere after the option parsing. */
     /* Please note that we may running SUID(ROOT), so be very CAREFUL
        when adding any stuff between here and the call to
        secmem_init() somewhere after the option parsing. */
-
+    reopen_std ();
     trap_unaligned();
     set_strusage (my_strusage);
     gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
     trap_unaligned();
     set_strusage (my_strusage);
     gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
@@ -2586,6 +2660,19 @@ main (int argc, char **argv )
           case oDefaultPreferenceList:
            opt.def_preference_list = pargs.r.ret_str;
            break;
           case oDefaultPreferenceList:
            opt.def_preference_list = pargs.r.ret_str;
            break;
+         case oDefaultKeyserverURL:
+           {
+             struct keyserver_spec *keyserver;
+             keyserver=parse_keyserver_uri(pargs.r.ret_str,1,
+                                           configname,configlineno);
+             if(!keyserver)
+               log_error(_("could not parse keyserver URL\n"));
+             else
+               free_keyserver_spec(keyserver);
+
+             opt.def_keyserver_url = pargs.r.ret_str;
+           }
+           break;
           case oPersonalCipherPreferences:
            pers_cipher_list=pargs.r.ret_str;
            break;
           case oPersonalCipherPreferences:
            pers_cipher_list=pargs.r.ret_str;
            break;
index 4526d84..3b41e08 100644 (file)
@@ -66,7 +66,7 @@ static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
 static void revocation_present(KBNODE keyblock);
 static int import_one(const char *fname, KBNODE keyblock,struct stats_s *stats,
                      unsigned char **fpr,size_t *fpr_len,
 static void revocation_present(KBNODE keyblock);
 static int import_one(const char *fname, KBNODE keyblock,struct stats_s *stats,
                      unsigned char **fpr,size_t *fpr_len,
-                     unsigned int options);
+                     unsigned int options,int from_sk);
 static int import_secret_one( const char *fname, KBNODE keyblock,
                               struct stats_s *stats, unsigned int options);
 static int import_revoke_cert( const char *fname, KBNODE node,
 static int import_secret_one( const char *fname, KBNODE keyblock,
                               struct stats_s *stats, unsigned int options);
 static int import_revoke_cert( const char *fname, KBNODE node,
@@ -258,7 +258,7 @@ import( IOBUF inp, const char* fname,struct stats_s *stats,
 
     while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
        if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
 
     while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
        if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
-           rc = import_one( fname, keyblock, stats, fpr, fpr_len, options );
+           rc = import_one( fname, keyblock, stats, fpr, fpr_len, options, 0);
        else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) 
                 rc = import_secret_one( fname, keyblock, stats, options );
        else if( keyblock->pkt->pkttype == PKT_SIGNATURE
        else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) 
                 rc = import_secret_one( fname, keyblock, stats, options );
        else if( keyblock->pkt->pkttype == PKT_SIGNATURE
@@ -679,7 +679,8 @@ check_prefs(KBNODE keyblock)
  */
 static int
 import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
  */
 static int
 import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
-           unsigned char **fpr,size_t *fpr_len,unsigned int options )
+           unsigned char **fpr,size_t *fpr_len,unsigned int options,
+           int from_sk )
 {
     PKT_public_key *pk;
     PKT_public_key *pk_orig;
 {
     PKT_public_key *pk;
     PKT_public_key *pk_orig;
@@ -698,9 +699,6 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
 
     pk = node->pkt->pkt.public_key;
 
 
     pk = node->pkt->pkt.public_key;
 
-    if(fpr)
-      *fpr=fingerprint_from_pk(pk,NULL,fpr_len);
-
     keyid_from_pk( pk, keyid );
     uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
 
     keyid_from_pk( pk, keyid );
     uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
 
@@ -978,13 +976,31 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
     if(mod_key)
       {
        revocation_present(keyblock_orig);
     if(mod_key)
       {
        revocation_present(keyblock_orig);
-       if(seckey_available(keyid)==0)
+       if(!from_sk && seckey_available(keyid)==0)
          check_prefs(keyblock_orig);
       }
     else if(new_key)
       {
          check_prefs(keyblock_orig);
       }
     else if(new_key)
       {
+       /* A little explanation for this: we fill in the fingerprint
+          when importing keys as it can be useful to know the
+          fingerprint in certain keyserver-related cases (a keyserver
+          asked for a particular name, but the key doesn't have that
+          name).  However, in cases where we're importing more than
+          one key at a time, we cannot know which key to fingerprint.
+          In these cases, rather than guessing, we do not fingerpring
+          at all, and we must hope the user ID on the keys are
+          useful. */
+       if(fpr)
+         {
+           xfree(*fpr);
+           if(stats->imported==1)
+             *fpr=fingerprint_from_pk(pk,NULL,fpr_len);
+           else
+             *fpr=NULL;
+         }
+
        revocation_present(keyblock);
        revocation_present(keyblock);
-       if(seckey_available(keyid)==0)
+       if(!from_sk && seckey_available(keyid)==0)
          check_prefs(keyblock);
       }
 
          check_prefs(keyblock);
       }
 
@@ -1156,7 +1172,7 @@ import_secret_one( const char *fname, KBNODE keyblock,
            if(pub_keyblock)
              {
                import_one(fname,pub_keyblock,stats,
            if(pub_keyblock)
              {
                import_one(fname,pub_keyblock,stats,
-                          NULL,NULL,opt.import_options);
+                          NULL,NULL,opt.import_options,1);
                release_kbnode(pub_keyblock);
              }
          }
                release_kbnode(pub_keyblock);
              }
          }
index f791c6c..7a62969 100644 (file)
@@ -42,6 +42,7 @@
 #include "trustdb.h"
 #include "status.h"
 #include "i18n.h"
 #include "trustdb.h"
 #include "status.h"
 #include "i18n.h"
+#include "keyserver-internal.h"
 #include "call-agent.h"
 
 
 #include "call-agent.h"
 
 
@@ -69,7 +70,8 @@ enum para_name {
   pPASSPHRASE_S2K,
   pSERIALNO,
   pBACKUPENCDIR,
   pPASSPHRASE_S2K,
   pSERIALNO,
   pBACKUPENCDIR,
-  pHANDLE
+  pHANDLE,
+  pKEYSERVER
 };
 
 struct para_data_s {
 };
 
 struct para_data_s {
@@ -125,6 +127,7 @@ static void do_generate_keypair( struct para_data_s *para,
 static int  write_keyblock( IOBUF out, KBNODE node );
 static int gen_card_key (int algo, int keyno, int is_primary,
                          KBNODE pub_root, KBNODE sec_root,
 static int  write_keyblock( IOBUF out, KBNODE node );
 static int gen_card_key (int algo, int keyno, int is_primary,
                          KBNODE pub_root, KBNODE sec_root,
+                        PKT_secret_key **ret_sk,
                          u32 expireval, struct para_data_s *para);
 static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
                                      KBNODE pub_root, KBNODE sec_root,
                          u32 expireval, struct para_data_s *para);
 static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
                                      KBNODE pub_root, KBNODE sec_root,
@@ -224,7 +227,7 @@ keygen_add_key_expire( PKT_signature *sig, void *opaque )
         if(pk->expiredate > pk->timestamp)
          u= pk->expiredate - pk->timestamp;
        else
         if(pk->expiredate > pk->timestamp)
          u= pk->expiredate - pk->timestamp;
        else
-         u= 0;
+         u= 1;
 
        buf[0] = (u >> 24) & 0xff;
        buf[1] = (u >> 16) & 0xff;
 
        buf[0] = (u >> 24) & 0xff;
        buf[1] = (u >> 16) & 0xff;
@@ -657,6 +660,7 @@ keygen_upd_std_prefs( PKT_signature *sig, void *opaque )
     /* Make sure that the MDC feature flag is set if needed */
     add_feature_mdc (sig,mdc_available);
     add_keyserver_modify (sig,ks_modify);
     /* Make sure that the MDC feature flag is set if needed */
     add_feature_mdc (sig,mdc_available);
     add_keyserver_modify (sig,ks_modify);
+    keygen_add_keyserver_url(sig,NULL);
 
     return 0;
 }
 
     return 0;
 }
@@ -675,6 +679,7 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
     do_add_key_flags (sig, pk->pubkey_usage);
     keygen_add_key_expire( sig, opaque );
     keygen_upd_std_prefs (sig, opaque);
     do_add_key_flags (sig, pk->pubkey_usage);
     keygen_add_key_expire( sig, opaque );
     keygen_upd_std_prefs (sig, opaque);
+    keygen_add_keyserver_url(sig,NULL);
 
     return 0;
 }
 
     return 0;
 }
@@ -684,6 +689,9 @@ keygen_add_keyserver_url(PKT_signature *sig, void *opaque)
 {
   const char *url=opaque;
 
 {
   const char *url=opaque;
 
+  if(!url)
+    url=opt.def_keyserver_url;
+
   if(url)
     build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url));
   else
   if(url)
     build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url));
   else
@@ -940,7 +948,6 @@ write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk,
     return rc;
 }
 
     return rc;
 }
 
-/* sub_sk is currently unused (reserved for backsigs) */
 static int
 write_keybinding( KBNODE root, KBNODE pub_root,
                  PKT_secret_key *pri_sk, PKT_secret_key *sub_sk,
 static int
 write_keybinding( KBNODE root, KBNODE pub_root,
                  PKT_secret_key *pri_sk, PKT_secret_key *sub_sk,
@@ -1224,20 +1231,54 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     PKT_public_key *pk;
     gcry_sexp_t s_parms, s_key;
     gcry_sexp_t misc_key_info;
     PKT_public_key *pk;
     gcry_sexp_t s_parms, s_key;
     gcry_sexp_t misc_key_info;
+    unsigned int qbits;
 
 
-    if( nbits > 1024 || nbits < 512 ) {
+    if ( nbits < 512 || (!opt.flags.dsa2 && nbits > 1024)) 
+      {
        nbits = 1024;
        log_info(_("keysize invalid; using %u bits\n"), nbits );
        nbits = 1024;
        log_info(_("keysize invalid; using %u bits\n"), nbits );
-    }
+      }
+    else if ( nbits > 3072 )
+      {
+       nbits = 3072;
+        log_info(_("keysize invalid; using %u bits\n"), nbits );
+      }
 
 
-    if( (nbits % 64) ) {
+    if( (nbits % 64) )
+      {
        nbits = ((nbits + 63) / 64) * 64;
        log_info(_("keysize rounded up to %u bits\n"), nbits );
        nbits = ((nbits + 63) / 64) * 64;
        log_info(_("keysize rounded up to %u bits\n"), nbits );
-    }
+      }
+
+    /*
+      Figure out a q size based on the key size.  FIPS 180-3 says:
+      L = 1024, N = 160
+      L = 2048, N = 224
+      L = 2048, N = 256
+      L = 3072, N = 256
+      2048/256 is an odd pair since there is also a 2048/224 and
+      3072/256.  Matching sizes is not a very exact science.
+      
+      We'll do 256 qbits for nbits over 2048, 224 for nbits over 1024
+      but less than 2048, and 160 for 1024 (DSA1).
+    */
+    if (nbits > 2048)
+      qbits = 256;
+    else if ( nbits > 1024)
+      qbits = 224;
+    else
+      qbits = 160;
+    if (qbits != 160 )
+      log_info (_("WARNING: some OpenPGP programs can't"
+                  " handle a DSA key with this digest size\n"));
 
     rc = gcry_sexp_build (&s_parms, NULL,
 
     rc = gcry_sexp_build (&s_parms, NULL,
-                          "(genkey(dsa(nbits %d)))",
-                          (int)nbits);
+                            "(genkey(dsa(nbits %d)(qbits %d)))",
+                            (int)nbits, (int)qbits);
     if (rc)
       log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc));
   
     if (rc)
       log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc));
   
@@ -1253,9 +1294,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     pk = xmalloc_clear( sizeof *pk );
     sk->timestamp = pk->timestamp = make_timestamp();
     sk->version = pk->version = 4;
     pk = xmalloc_clear( sizeof *pk );
     sk->timestamp = pk->timestamp = make_timestamp();
     sk->version = pk->version = 4;
-    if( expireval ) {
-       sk->expiredate = pk->expiredate = sk->timestamp + expireval;
-    }
+    if (expireval) 
+      sk->expiredate = pk->expiredate = sk->timestamp + expireval;
     sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA;
 
     rc = key_from_sexp (pk->pkey, s_key, "public-key", "pqgy");
     sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA;
 
     rc = key_from_sexp (pk->pkey, s_key, "public-key", "pqgy");
@@ -1633,10 +1673,10 @@ ask_keysize( int algo )
   switch(algo)
     {
     case PUBKEY_ALGO_DSA:
   switch(algo)
     {
     case PUBKEY_ALGO_DSA:
-      if(opt.expert)
+      if(opt.flags.dsa2)
        {
          def=1024;
        {
          def=1024;
-         max=1024;
+         max=3072;
        }
       else
        {
        }
       else
        {
@@ -2375,6 +2415,25 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
   /* Set preferences, if any. */
   keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0);
 
   /* Set preferences, if any. */
   keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0);
 
+  /* Set keyserver, if any. */
+  s1=get_parameter_value( para, pKEYSERVER );
+  if(s1)
+    {
+      struct keyserver_spec *spec;
+
+      spec=parse_keyserver_uri(s1,1,NULL,0);
+      if(spec)
+       {
+         free_keyserver_spec(spec);
+         opt.def_keyserver_url=s1;
+       }
+      else
+       {
+         log_error("%s:%d: invalid keyserver url\n", fname, r->lnr );
+         return -1;
+       }
+    }
+
   /* Set revoker, if any. */
   if (parse_revocation_key (fname, para, pREVOKER))
     return -1;
   /* Set revoker, if any. */
   if (parse_revocation_key (fname, para, pREVOKER))
     return -1;
@@ -2467,6 +2526,7 @@ read_parameter_file( const char *fname )
        { "Preferences",    pPREFERENCES },
        { "Revoker",        pREVOKER },
         { "Handle",         pHANDLE },
        { "Preferences",    pPREFERENCES },
        { "Revoker",        pREVOKER },
         { "Handle",         pHANDLE },
+       { "Keyserver",      pKEYSERVER },
        { NULL, 0 }
     };
     IOBUF fp;
        { NULL, 0 }
     };
     IOBUF fp;
@@ -2746,12 +2806,12 @@ generate_keypair (const char *fname, const char *card_serialno,
           sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
           r->next = para;
           para = r;
           sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
           r->next = para;
           para = r;
-          tty_printf(_("DSA keypair will have %u bits.\n"),1024);
-          r = xmalloc_clear( sizeof *r + 20 );
-          r->key = pKEYLENGTH;
-          strcpy( r->u.value, "1024" );
-          r->next = para;
-          para = r;
+         nbits = ask_keysize( PUBKEY_ALGO_DSA );
+         r = xmalloc_clear( sizeof *r + 20 );
+         r->key = pKEYLENGTH;
+         sprintf( r->u.value, "%u", nbits);
+         r->next = para;
+         para = r;
           r = xmalloc_clear( sizeof *r + 20 );
           r->key = pKEYUSAGE;
           strcpy( r->u.value, "sign" );
           r = xmalloc_clear( sizeof *r + 20 );
           r->key = pKEYUSAGE;
           strcpy( r->u.value, "sign" );
@@ -2791,7 +2851,7 @@ generate_keypair (const char *fname, const char *card_serialno,
             }
            
         }
             }
            
         }
-       
+
       nbits = ask_keysize( algo );
       r = xmalloc_clear( sizeof *r + 20 );
       r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
       nbits = ask_keysize( algo );
       r = xmalloc_clear( sizeof *r + 20 );
       r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
@@ -3057,7 +3117,7 @@ do_generate_keypair( struct para_data_s *para,
       }
     else
       {
       }
     else
       {
-        rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root,
+        rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, NULL,
                            get_parameter_u32 (para, pKEYEXPIRE), para);
         if (!rc)
           {
                            get_parameter_u32 (para, pKEYEXPIRE), para);
         if (!rc)
           {
@@ -3093,7 +3153,7 @@ do_generate_keypair( struct para_data_s *para,
 
     if (!rc && card && get_parameter (para, pAUTHKEYTYPE))
       {
 
     if (!rc && card && get_parameter (para, pAUTHKEYTYPE))
       {
-        rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root,
+        rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, NULL,
                            get_parameter_u32 (para, pKEYEXPIRE), para);
         
         if (!rc)
                            get_parameter_u32 (para, pKEYEXPIRE), para);
         
         if (!rc)
@@ -3129,6 +3189,7 @@ do_generate_keypair( struct para_data_s *para,
               }
             else
               rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
               }
             else
               rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root,
+                                NULL,
                                  get_parameter_u32 (para, pKEYEXPIRE), para);
           }
 
                                  get_parameter_u32 (para, pKEYEXPIRE), para);
           }
 
@@ -3353,7 +3414,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
     }
 
     rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
     }
 
     rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
-                                     dek, s2k, &sub_sk, expire, 1 );
+                   dek, s2k, &sub_sk, expire, 1 );
     if( !rc )
        rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
     if( !rc )
     if( !rc )
        rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
     if( !rc )
@@ -3387,7 +3448,7 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
 {
   int okay=0, rc=0;
   KBNODE node;
 {
   int okay=0, rc=0;
   KBNODE node;
-  PKT_secret_key *pri_sk = NULL;
+  PKT_secret_key *pri_sk = NULL, *sub_sk;
   int algo;
   unsigned int use;
   u32 expire;
   int algo;
   unsigned int use;
   u32 expire;
@@ -3467,11 +3528,12 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
 
   if (passphrase)
     set_next_passphrase (passphrase);
 
   if (passphrase)
     set_next_passphrase (passphrase);
-  rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock, expire, para);
+  rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock,
+                    &sub_sk, expire, para);
   if (!rc)
   if (!rc)
-    rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, NULL, use);
+    rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk, use);
   if (!rc)
   if (!rc)
-    rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, NULL, use);
+    rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk, use);
   if (!rc)
     {
       okay = 1;
   if (!rc)
     {
       okay = 1;
@@ -3518,7 +3580,7 @@ write_keyblock( IOBUF out, KBNODE node )
 
 static int
 gen_card_key (int algo, int keyno, int is_primary,
 
 static int
 gen_card_key (int algo, int keyno, int is_primary,
-              KBNODE pub_root, KBNODE sec_root,
+              KBNODE pub_root, KBNODE sec_root, PKT_secret_key **ret_sk,
               u32 expireval, struct para_data_s *para)
 {
 #ifdef ENABLE_CARD_SUPPORT
               u32 expireval, struct para_data_s *para)
 {
 #ifdef ENABLE_CARD_SUPPORT
@@ -3579,6 +3641,9 @@ gen_card_key (int algo, int keyno, int is_primary,
         sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s);
     }
 
         sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s);
     }
 
+  if( ret_sk )
+    *ret_sk = sk;
+
   pkt = xcalloc (1,sizeof *pkt);
   pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
   pkt->pkt.public_key = pk;
   pkt = xcalloc (1,sizeof *pkt);
   pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
   pkt->pkt.public_key = pk;
index b97b2f3..75c2745 100644 (file)
@@ -154,7 +154,8 @@ struct
   unsigned int export_options;
   unsigned int list_options;
   unsigned int verify_options;
   unsigned int export_options;
   unsigned int list_options;
   unsigned int verify_options;
-  char *def_preference_list;
+  const char *def_preference_list;
+  const char *def_keyserver_url;
   prefitem_t *personal_cipher_prefs;
   prefitem_t *personal_digest_prefs;
   prefitem_t *personal_compress_prefs;
   prefitem_t *personal_cipher_prefs;
   prefitem_t *personal_digest_prefs;
   prefitem_t *personal_compress_prefs;
index cd6e1db..d792bff 100644 (file)
@@ -1,6 +1,6 @@
 /* parse-packet.c  - read packets
 /* parse-packet.c  - read packets
- * 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.
  *
  *
  * This file is part of GnuPG.
  *
@@ -876,8 +876,13 @@ dump_sig_subpkt( int hashed, int type, int critical,
        break;
       case SIGSUBPKT_SIG_EXPIRE:
        if( length >= 4 )
        break;
       case SIGSUBPKT_SIG_EXPIRE:
        if( length >= 4 )
-           fprintf (listfp, "sig expires after %s",
-                                    strtimevalue( buffer_to_u32(buffer) ) );
+         {
+           if(buffer_to_u32(buffer))
+             fprintf (listfp, "sig expires after %s",
+                      strtimevalue( buffer_to_u32(buffer) ) );
+           else
+             fprintf (listfp, "sig does not expire");
+         }
        break;
       case SIGSUBPKT_EXPORTABLE:
        if( length )
        break;
       case SIGSUBPKT_EXPORTABLE:
        if( length )
@@ -901,8 +906,13 @@ dump_sig_subpkt( int hashed, int type, int critical,
        break;
       case SIGSUBPKT_KEY_EXPIRE:
        if( length >= 4 )
        break;
       case SIGSUBPKT_KEY_EXPIRE:
        if( length >= 4 )
-           fprintf (listfp, "key expires after %s",
-                                   strtimevalue( buffer_to_u32(buffer) ) );
+         {
+           if(buffer_to_u32(buffer))
+             fprintf (listfp, "key expires after %s",
+                      strtimevalue( buffer_to_u32(buffer) ) );
+           else
+             fprintf (listfp, "key does not expire");
+         }
        break;
       case SIGSUBPKT_PREF_SYM:
        fputs("pref-sym-algos:", listfp );
        break;
       case SIGSUBPKT_PREF_SYM:
        fputs("pref-sym-algos:", listfp );
@@ -1408,7 +1418,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
          log_info ("signature packet without keyid\n");
 
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
          log_info ("signature packet without keyid\n");
 
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
-       if(p)
+       if(p && buffer_to_u32(p))
          sig->expiredate=sig->timestamp+buffer_to_u32(p);
        if(sig->expiredate && sig->expiredate<=make_timestamp())
          sig->flags.expired=1;
          sig->expiredate=sig->timestamp+buffer_to_u32(p);
        if(sig->expiredate && sig->expiredate<=make_timestamp())
          sig->flags.expired=1;
@@ -2027,6 +2037,20 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 {
     byte *p;
 
 {
     byte *p;
 
+    /* Cap the size of a user ID at 2k: a value absurdly large enough
+       that there is no sane user ID string (which is printable text
+       as of RFC2440bis) that won't fit in it, but yet small enough to
+       avoid allocation problems.  A large pktlen may not be
+       allocatable, and a very large pktlen could actually cause our
+       allocation to wrap around in xmalloc to a small number. */
+
+    if (pktlen > 2048)
+      {
+       log_error ("packet(%d) too large\n", pkttype);
+       iobuf_skip_rest(inp, pktlen, 0);
+       return G10ERR_INVALID_PACKET;
+      }
+    
     packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id + pktlen);
     packet->pkt.user_id->len = pktlen;
     packet->pkt.user_id->ref=1;
     packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id + pktlen);
     packet->pkt.user_id->len = pktlen;
     packet->pkt.user_id->ref=1;
index 3e1d7bc..0538f00 100644 (file)
@@ -320,6 +320,12 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
       }
     else 
       {
       }
     else 
       {
+#if 0 /* disabled *.
+       /* Disabled for now.  It seems reasonable to accept a
+          truncated hash for a DSA1 key, even though we don't
+          generate it without --enable-dsa2.  Be liberal in what you
+          accept, etc. */
+
        /* If it's a DSA key, and q is 160 bits, it might be an
           old-style DSA key.  If the hash doesn't match the q, fail
           unless --enable-dsa2 is set.  If the q isn't 160 bits, then
        /* If it's a DSA key, and q is 160 bits, it might be an
           old-style DSA key.  If the hash doesn't match the q, fail
           unless --enable-dsa2 is set.  If the q isn't 160 bits, then
@@ -333,6 +339,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
            log_error(_("DSA requires the use of a 160 bit hash algorithm\n"));
            return G10ERR_GENERAL;
          }
            log_error(_("DSA requires the use of a 160 bit hash algorithm\n"));
            return G10ERR_GENERAL;
          }
+#endif /* disabled */
 
         frame = encode_md_value( NULL, sk, md, digest_algo );
         if (!frame)
 
         frame = encode_md_value( NULL, sk, md, digest_algo );
         if (!frame)
@@ -1539,7 +1546,7 @@ update_keysig_packet( PKT_signature **ret_sig,
       }
 
     /* Note that already expired sigs will remain expired (with a
       }
 
     /* Note that already expired sigs will remain expired (with a
-       duration of 0) since build-packet.c:build_sig_subpkt_from_sig
+       duration of 1) since build-packet.c:build_sig_subpkt_from_sig
        detects this case. */
 
     if( sig->version >= 4 )
        detects this case. */
 
     if( sig->version >= 4 )