Merged recent changes from 1.4
authorWerner Koch <wk@gnupg.org>
Fri, 28 Apr 2006 14:31:29 +0000 (14:31 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 28 Apr 2006 14:31:29 +0000 (14:31 +0000)
15 files changed:
g10/ChangeLog
g10/armor.c
g10/encode.c
g10/getkey.c
g10/gpg.c
g10/keyedit.c
g10/keygen.c
g10/keyserver.c
g10/main.h
g10/mainproc.c
g10/options.h
g10/pkclist.c
g10/plaintext.c
g10/sign.c
g10/status.c

index 6259bdc..b8f789e 100644 (file)
@@ -1,3 +1,59 @@
+2006-04-28  David Shaw  <dshaw@jabberwocky.com>  (wk)
+       
+       * keyserver.c (direct_uri_map): New.
+       (keyserver_spawn): Used here to add "_uri" to certain gpgkeys_xxx
+       helpers when the meaning is different if a path is provided (i.e. 
+       ldap).
+       (keyserver_import_cert): Show warning if there is a CERT
+       fingerprint, but no --keyserver set.
+
+       * keyserver.c: Fix build problem with platforms that stick libcurl
+       in a place not in the regular include search path.
+
+       * options.h, gpg.c (main): Add --enable-dsa2 and --disable-dsa2.
+       Defaults to disable.
+
+       * pkclist.c (algo_available): If --enable-dsa2 is set, we're
+       allowed to truncate hashes to fit DSA keys.
+
+       * sign.c (match_dsa_hash): New.  Return the best match hash for a
+       given q size.
+       (do_sign, hash_for, sign_file): When signing with a DSA key, if it
+       has q==160, assume it is an old DSA key and don't allow truncation
+       unless --enable-dsa2 is also set.  q!=160 always allows truncation
+       since they must be DSA2 keys.
+       (make_keysig_packet): If the user doesn't specify a
+       --cert-digest-algo, use match_dsa_hash to pick the best hash for
+       key signatures.
+
+       * gpg.c (print_mds): Add SHA-224.
+       * armor.c (armor_filter, parse_hash_header): Add SHA-224.
+
+       * sign.c (write_plaintext_packet):
+       Factor common literal packet setup code from here, to...
+       * encode.c (encode_simple): .. there.
+       
+       * main.h, plaintext.c (setup_plaintext_name): Here. New. Make sure
+       the literal packet filename field is UTF-8 encoded.
+
+       * options.h, gpg.c (main): Make sure --set-filename is UTF-8
+       encoded and note when filenames are already UTF-8.
+
+       * keyedit.c (menu_backsign): Give some more verbose errors when we
+       have no need to backsign.
+
+       * getkey.c (parse_auto_key_locate): Fix dupe-removal code.
+
+       * keyedit.c (menu_backsign): Allow backsigning even if the secret
+       subkey doesn't have a binding signature.
+
+       * armor.c (radix64_read): Don't report EOF when reading only a pad
+       (=) character.  The EOF actually starts after the pad.
+
+       * gpg.c (main): Make --export, --send-keys, --recv-keys,
+       --refresh-keys, and --fetch-keys follow their arguments from left
+       to right.  Suggested by Peter Palfrader.
+
 2006-04-18  Werner Koch  <wk@g10code.com>
 
        * tdbio.c (open_db, migrate_from_v2): Removed feature to migration
index a154c5c..e025913 100644 (file)
@@ -1,6 +1,6 @@
 /* armor.c - Armor flter
- * 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.
  *
@@ -242,12 +242,14 @@ parse_hash_header( const char *line )
            found |= 2;
        else if( !strncmp( s, "MD5", s2-s ) )
            found |= 4;
-       else if( !strncmp( s, "SHA256", s2-s ) )
+       else if( !strncmp( s, "SHA224", s2-s ) )
            found |= 8;
-       else if( !strncmp( s, "SHA384", s2-s ) )
+       else if( !strncmp( s, "SHA256", s2-s ) )
            found |= 16;
-       else if( !strncmp( s, "SHA512", s2-s ) )
+       else if( !strncmp( s, "SHA384", s2-s ) )
            found |= 32;
+       else if( !strncmp( s, "SHA512", s2-s ) )
+           found |= 64;
        else
            return 0;
        for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
@@ -676,7 +678,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
     int checkcrc=0;
     int rc = 0;
     size_t n = 0;
-    int  idx, i;
+    int  idx, i, onlypad=0;
     u32 crc;
 
     crc = afx->crc;
@@ -720,6 +722,8 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                    goto again;
                }
            }
+           else if(n==0)
+             onlypad=1;
 
            if( idx == 1 )
                buf[n++] = val;
@@ -848,7 +852,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
        }
     }
 
-    if( !n )
+    if( !n && !onlypad )
        rc = -1;
 
     *retn = n;
@@ -951,10 +955,12 @@ armor_filter( void *opaque, int control,
                 if( hashes & 4 )
                     buf[n++] = DIGEST_ALGO_MD5;
                 if( hashes & 8 )
-                    buf[n++] = DIGEST_ALGO_SHA256;
+                    buf[n++] = DIGEST_ALGO_SHA224;
                 if( hashes & 16 )
-                    buf[n++] = DIGEST_ALGO_SHA384;
+                    buf[n++] = DIGEST_ALGO_SHA256;
                 if( hashes & 32 )
+                    buf[n++] = DIGEST_ALGO_SHA384;
+                if( hashes & 64 )
                     buf[n++] = DIGEST_ALGO_SHA512;
                 buf[1] = n - 2;
 
index bb3e7bb..292e2bc 100644 (file)
@@ -1,6 +1,6 @@
 /* encode.c - encode data
- * 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.
  *
@@ -278,22 +278,8 @@ encode_simple( const char *filename, int mode, int use_seskey )
        xfree(enc);
     }
 
-    if (!opt.no_literal) {
-       /* setup the inner packet */
-       if( filename || opt.set_filename ) {
-           char *s = make_basename( opt.set_filename ? opt.set_filename
-                                                     : filename,
-                                    iobuf_get_real_fname( inp ) );
-           pt = xmalloc( sizeof *pt + strlen(s) - 1 );
-           pt->namelen = strlen(s);
-           memcpy(pt->name, s, pt->namelen );
-           xfree(s);
-       }
-       else { /* no filename */
-           pt = xmalloc( sizeof *pt - 1 );
-           pt->namelen = 0;
-       }
-    }
+    if (!opt.no_literal)
+      pt=setup_plaintext_name(filename,inp);
 
     /* Note that PGP 5 has problems decrypting symmetrically encrypted
        data if the file length is in the inner packet. It works when
index acd992c..bff2a0d 100644 (file)
@@ -2948,7 +2948,7 @@ parse_auto_key_locate(char *options)
 
   while((tok=optsep(&options)))
     {
-      struct akl *akl,*last;
+      struct akl *akl,*check,*last=NULL;
       int dupe=0;
 
       if(tok[0]=='\0')
@@ -2977,13 +2977,13 @@ parse_auto_key_locate(char *options)
        }
 
       /* We must maintain the order the user gave us */
-      for(last=opt.auto_key_locate;last && last->next;last=last->next)
+      for(check=opt.auto_key_locate;check;last=check,check=check->next)
        {
          /* Check for duplicates */
-         if(last && last->type==akl->type
+         if(check->type==akl->type
             && (akl->type!=AKL_SPEC
                 || (akl->type==AKL_SPEC
-                    && strcmp(last->spec->uri,akl->spec->uri)==0)))
+                    && strcmp(check->spec->uri,akl->spec->uri)==0)))
            {
              dupe=1;
              free_akl(akl);
index 49687ff..25b55b7 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -354,6 +354,8 @@ enum cmd_and_opt_values
     oAutoKeyLocate,
     oNoAutoKeyLocate,
     oAllowMultisigVerification,
+    oEnableDSA2,
+    oDisableDSA2,
 
     oNoop
   };
@@ -684,6 +686,8 @@ static ARGPARSE_OPTS opts[] = {
     { oLimitCardInsertTries, "limit-card-insert-tries", 1, "@"},
 
     { oAllowMultisigVerification, "allow-multisig-verification", 0, "@"},
+    { oEnableDSA2, "enable-dsa2", 0, "@"},
+    { oDisableDSA2, "disable-dsa2", 0, "@"},
 
     /* These two are aliases to help users of the PGP command line
        product use gpg with minimal pain.  Many commands are common
@@ -2169,7 +2173,12 @@ main (int argc, char **argv )
          case oCompressSigs: opt.compress_sigs = 1; break;
          case oRFC2440Text: opt.rfc2440_text=1; break;
          case oNoRFC2440Text: opt.rfc2440_text=0; break;
-         case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
+         case oSetFilename:
+            if(utf8_strings)
+              opt.set_filename = pargs.r.ret_str;
+            else
+              opt.set_filename = native_to_utf8(pargs.r.ret_str);
+           break;
          case oForYourEyesOnly: eyes_only = 1; break;
          case oNoForYourEyesOnly: eyes_only = 0; break;
          case oSetPolicyURL:
@@ -2195,8 +2204,12 @@ main (int argc, char **argv )
            opt.verify_options&=~VERIFY_SHOW_POLICY_URLS;
            break;
          case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break;
-         case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break;
-         case oNoUseEmbeddedFilename: opt.use_embedded_filename = 0; break;
+         case oUseEmbeddedFilename:
+           opt.flags.use_embedded_filename=1;
+           break;
+         case oNoUseEmbeddedFilename:
+           opt.flags.use_embedded_filename=0;
+           break;
          case oComment:
            if(pargs.r.ret_str[0])
              append_to_strlist(&opt.comments,pargs.r.ret_str);
@@ -2639,6 +2652,9 @@ main (int argc, char **argv )
             opt.allow_multisig_verification = 1;
             break;
 
+         case oEnableDSA2: opt.flags.dsa2=1; break;
+         case oDisableDSA2: opt.flags.dsa2=0; break;
+
          case oNoop: break;
 
          default : pargs.err = configfp? 1:2; break;
@@ -3086,6 +3102,9 @@ main (int argc, char **argv )
 
     fname = argc? *argv : NULL;
 
+    if(fname && utf8_strings)
+      opt.flags.utf8_filename=1;
+
     switch( cmd ) {
       case aPrimegen:
       case aPrintMD:
@@ -3390,12 +3409,17 @@ main (int argc, char **argv )
        import_keys( argc? argv:NULL, argc, NULL, opt.import_options );
        break;
 
+       /* TODO: There are a number of command that use this same
+          "make strlist, call function, report error, free strlist"
+          pattern.  Join them together here and avoid all that
+          duplicated code. */
+
       case aExport:
       case aSendKeys:
       case aRecvKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist2( &sl, *argv, utf8_strings );
+           append_to_strlist2( &sl, *argv, utf8_strings );
        if( cmd == aSendKeys )
            rc=keyserver_export( sl );
        else if( cmd == aRecvKeys )
@@ -3427,7 +3451,7 @@ main (int argc, char **argv )
       case aRefreshKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist2( &sl, *argv, utf8_strings );
+           append_to_strlist2( &sl, *argv, utf8_strings );
        rc=keyserver_refresh(sl);
        if(rc)
          log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc));
@@ -3437,7 +3461,7 @@ main (int argc, char **argv )
       case aFetchKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
-           add_to_strlist2( &sl, *argv, utf8_strings );
+           append_to_strlist2( &sl, *argv, utf8_strings );
        rc=keyserver_fetch(sl);
        if(rc)
          log_error("key fetch failed: %s\n",g10_errstr(rc));
@@ -3913,6 +3937,7 @@ print_mds( const char *fname, int algo )
        gcry_md_enable (md, GCRY_MD_SHA1);
        gcry_md_enable (md, GCRY_MD_RMD160);
 #ifdef USE_SHA256
+       gcry_md_enable (md, DIGEST_ALGO_SHA224);
        gcry_md_enable (md, GCRY_MD_SHA256);
 #endif
 #ifdef USE_SHA512
@@ -3935,6 +3960,8 @@ print_mds( const char *fname, int algo )
                 print_hashline( md, GCRY_MD_SHA1, fname );
                 print_hashline( md, GCRY_MD_RMD160, fname );
 #ifdef USE_SHA256
+                if (!gcry_md_test_algo (DIGEST_ALGO_SHA224)
+                    print_hashline (md, DIGEST_ALGO_SHA224, fname);
                 print_hashline( md, GCRY_MD_SHA256, fname );
 #endif
 #ifdef USE_SHA512
@@ -3951,6 +3978,8 @@ print_mds( const char *fname, int algo )
                 print_hex( md, GCRY_MD_SHA1, fname );
                 print_hex( md, GCRY_MD_RMD160, fname );
 #ifdef USE_SHA256
+                if (!gcry_md_test_algo (DIGEST_ALGO_SHA224)
+                    print_hex (md, DIGEST_ALGO_SHA224, fname);
                 print_hex( md, GCRY_MD_SHA256, fname );
 #endif
 #ifdef USE_SHA512
index bfe3f85..80d714a 100644 (file)
@@ -3661,10 +3661,21 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
        }
 
       /* Find a signing subkey with no backsig */
-      if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY
-         && (node->pkt->pkt.public_key->pubkey_usage&PUBKEY_USAGE_SIG)
-         && !node->pkt->pkt.public_key->backsig)
-        sub_pk=node->pkt->pkt.public_key;
+      if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY)
+       {
+         if(node->pkt->pkt.public_key->pubkey_usage&PUBKEY_USAGE_SIG)
+           {
+             if(node->pkt->pkt.public_key->backsig)
+               tty_printf(_("signing subkey %s is already cross-certified\n"),
+                          keystr_from_pk(node->pkt->pkt.public_key));
+             else
+               sub_pk=node->pkt->pkt.public_key;
+           }
+         else
+           tty_printf(_("subkey %s does not sign and so does"
+                        " not need to be cross-certified\n"),
+                      keystr_from_pk(node->pkt->pkt.public_key));
+       }
 
       if(!sub_pk)
        continue;
@@ -3693,7 +3704,11 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
          }
 
       if(!sub_sk)
-       continue;
+       {
+         tty_printf(_("no secret subkey for public subkey %s - ignoring\n"),
+                    keystr_from_pk(sub_pk));
+         continue;
+       }
 
       /* Now finally find the matching selfsig on the secret subkey.
         We can't use chosen_selfsig here (it's not set for secret
@@ -3712,11 +3727,8 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
            break;
          }
 
-      if(!sig_sk)
-       continue;
-
       /* Now we can get to work.  We have a main key and secret part,
-        a signing subkey with signature and secret part with
+        a signing subkey with signature and secret part possibly with
         signature. */
 
       passphrase=get_last_passphrase();
@@ -3745,13 +3757,16 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock)
              xfree(sig_pk->pkt);
              sig_pk->pkt=newpkt;
 
-             /* Put the new sig into place on the seckey */
-             newpkt=xmalloc_clear(sizeof(*newpkt));
-             newpkt->pkttype=PKT_SIGNATURE;
-             newpkt->pkt.signature=copy_signature(NULL,newsig);
-             free_packet(sig_sk->pkt);
-             xfree(sig_sk->pkt);
-             sig_sk->pkt=newpkt;
+             if(sig_sk)
+               {
+                 /* Put the new sig into place on the seckey */
+                 newpkt=xmalloc_clear(sizeof(*newpkt));
+                 newpkt->pkttype=PKT_SIGNATURE;
+                 newpkt->pkt.signature=copy_signature(NULL,newsig);
+                 free_packet(sig_sk->pkt);
+                 xfree(sig_sk->pkt);
+                 sig_sk->pkt=newpkt;
+               }
 
              modified=1;
            }
index 32c09a9..c7a97a0 100644 (file)
@@ -341,7 +341,7 @@ keygen_set_std_prefs (const char *string,int personal)
            /* SHA-1 */
            strcat(dummy_string,"H2 ");
 
-           if(!check_digest_algo(DIGEST_ALGO_SHA256))
+           if (!openpgp_md_test_algo(DIGEST_ALGO_SHA256))
              strcat(dummy_string,"H8 ");
 
            /* RIPEMD160 */
@@ -370,12 +370,12 @@ keygen_set_std_prefs (const char *string,int personal)
 
        while((tok=strsep(&prefstring," ,")))
          {
-           if((val=openpgp_cipher_map_name (tok)))
+           if((val=gcry_cipher_map_name (tok)))
              {
                if(set_one_pref(val,1,tok,sym,&nsym))
                  rc=-1;
              }
-           else if((val=openpgp_md_map_name (tok)))
+           else if((val=gcry_md_map_name (tok)))
              {
                if(set_one_pref(val,2,tok,hash,&nhash))
                  rc=-1;
@@ -2138,7 +2138,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key )
     if( digitp( r->u.value ) )
        i = atoi( r->u.value );
     else
-        i = openpgp_pk_map_name (r->u.value);
+        i = gcry_pk_map_name (r->u.value);
     if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S)
       i = 0; /* we don't want to allow generation of these algorithms */
     return i;
@@ -2289,7 +2289,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname,
   if(r)
     {
       algo=get_parameter_algo(para,pKEYTYPE);
-      if (openpgp_pk_test_algo (algo, PUBKEY_USAGE_SIG))
+      if (openpgp_pk_test_algo2 (algo, PUBKEY_USAGE_SIG))
        {
          log_error("%s:%d: invalid algorithm\n", fname, r->lnr );
          return -1;
index 3e72b28..3127a47 100644 (file)
@@ -26,9 +26,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <assert.h>
-#ifdef HAVE_LIBCURL
-#include <curl/curl.h>
-#endif
+#include <errno.h>
 
 #include "gpg.h"
 #include "iobuf.h"
 #include "keyserver-internal.h"
 #include "util.h"
 
-#define GPGKEYS_PREFIX "gpgkeys_"
-
-#if defined(HAVE_LIBCURL) || defined(FAKE_CURL)
-#define GPGKEYS_CURL "gpgkeys_curl"
-#endif
-
-#ifdef GPGKEYS_CURL
-#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_PREFIX)+strlen(GPGKEYS_CURL))
-#else
-#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_PREFIX))
-#endif
-
 struct keyrec
 {
   KEYDB_SEARCH_DESC desc;
@@ -419,7 +405,7 @@ parse_keyserver_uri(const char *string,int require_scheme,
       else
        keyserver->path=xstrdup("/");
 
-      if(keyserver->path[1]!='\0')
+      if(keyserver->path[1])
        keyserver->flags.direct_uri=1;
     }
   else if(uri[0]!='/')
@@ -941,19 +927,20 @@ keyserver_typemap(const char *type)
     return type;
 }
 
-#ifdef GPGKEYS_CURL
 /* The PGP LDAP and the curl fetch-a-LDAP-object methodologies are
    sufficiently different that we can't use curl to do LDAP. */
 static int
-curl_cant_handle(const char *scheme,unsigned int direct_uri)
+direct_uri_map(const char *scheme,unsigned int is_direct)
 {
-  if(!direct_uri && (strcmp(scheme,"ldap")==0 || strcmp(scheme,"ldaps")==0))
+  if(is_direct && strcmp(scheme,"ldap")==0)
     return 1;
 
   return 0;
 }
-#endif
 
+#define GPGKEYS_PREFIX "gpgkeys_"
+#define GPGKEYS_CURL GPGKEYS_PREFIX "curl" EXEEXT
+#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_CURL))
 #define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\""
 #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\""
 
@@ -1021,19 +1008,29 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
 
   end=command+strlen(command);
 
+  /* Build a path for the keyserver helper.  If it is direct_uri
+     (i.e. an object fetch and not a keyserver), then add "_uri" to
+     the end to distinguish the keyserver helper from an object
+     fetcher that can speak that protocol (this is a problem for
+     LDAP). */
+
   strcat(command,GPGKEYS_PREFIX); 
   strcat(command,scheme);
 
-  if(keyserver->flags.direct_uri)
-    strcat(command,"uri");
+  /* This "_uri" thing is in case we need to call a direct handler
+     instead of the keyserver handler.  This lets us use gpgkeys_curl
+     or gpgkeys_ldap_uri (we don't provide it, but a user might)
+     instead of gpgkeys_ldap to fetch things like
+     ldap://keyserver.pgp.com/o=PGP%20keys?pgpkey?sub?pgpkeyid=99242560 */
+
+  if(direct_uri_map(scheme,keyserver->flags.direct_uri))
+    strcat(command,"_uri");
 
   strcat(command,EXEEXT);
 
-#ifdef GPGKEYS_CURL
-  if(!curl_cant_handle(scheme,keyserver->flags.direct_uri)
-     && path_access(command,X_OK)!=0)
+  /* Can we execute it?  If not, try curl as our catchall. */
+  if(path_access(command,X_OK)!=0)
     strcpy(end,GPGKEYS_CURL);
-#endif
 
   if(opt.keyserver_options.options&KEYSERVER_USE_TEMP_FILES)
     {
@@ -1950,15 +1947,6 @@ keyserver_fetch(STRLIST urilist)
        {
          int rc;
 
-         /*
-           Set the direct_uri flag so we know later to call a direct
-           handler instead of the keyserver style.  This lets us use
-           gpgkeys_curl or gpgkeys_ldapuri instead of gpgkeys_ldap to
-           fetch things like
-           ldap://keyserver.pgp.com/o=PGP%20keys?pgpkey?sub?pgpkeyid=99242560
-         */
-         spec->flags.direct_uri=1;
-
          rc=keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,spec);
          if(rc)
            log_info (_("WARNING: unable to fetch URI %s: %s\n"),
@@ -2038,6 +2026,12 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
 
          rc=keyserver_import_fprint(*fpr,*fpr_len,opt.keyserver);
        }
+      else
+       log_info(_("no keyserver known (use option --keyserver)\n"));
+
+      /* Give a better string here? "CERT fingerprint for \"%s\"
+        found, but no keyserver" " known (use option
+        --keyserver)\n" ? */
 
       xfree(url);
     }
index fd306a4..cd6926b 100644 (file)
@@ -282,6 +282,7 @@ void decrypt_messages(int nfiles, char *files[]);
 /*-- plaintext.c --*/
 int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2,
                    STRLIST files, const char *sigfilename, int textmode );
+PKT_plaintext *setup_plaintext_name(const char *filename,IOBUF iobuf);
 
 /*-- signal.c --*/
 void init_signals(void);
index 27989d3..1f91c8c 100644 (file)
@@ -659,9 +659,9 @@ proc_plaintext( CTX c, PACKET *pkt )
           often.  There is no good way to specify what algorithms to
           use in that case, so these three are the historical
           answer. */
-       md_enable( c->mfx.md, DIGEST_ALGO_RMD160 );
-       md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
-       md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
+       gcry_md_enable( c->mfx.md, DIGEST_ALGO_RMD160 );
+       gcry_md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
+       gcry_md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
       }
     if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) {
        /* This is a kludge to work around a bug in pgp2.  It does only
index f61cd4c..de5fa79 100644 (file)
@@ -170,7 +170,6 @@ struct
   STRLIST sig_keyserver_url;
   STRLIST cert_subpackets;
   STRLIST sig_subpackets;
-  int use_embedded_filename;
   int allow_non_selfsigned_uid;
   int allow_freeform_uid;
   int no_literal;
@@ -222,6 +221,10 @@ struct
        made by signing subkeys.  If not set, a missing backsig is not
        an error (but an invalid backsig still is). */
     unsigned int require_cross_cert:1;
+
+    unsigned int use_embedded_filename:1;
+    unsigned int utf8_filename:1;
+    unsigned int dsa2:1;
   } flags;
 
   /* Linked list of ways to find a key if the key isn't on the local
index 9e2a636..4a12083 100644 (file)
@@ -1,6 +1,6 @@
 /* pkclist.c - create a list of public keys
- * 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.
  *
@@ -1210,8 +1210,20 @@ algo_available( preftype_t preftype, int algo, void *hint )
     }
   else if( preftype == PREFTYPE_HASH )
     {
-      if(hint && ((*(int *)hint) != gcry_md_get_algo_dlen (algo)))
-       return 0;
+      if(hint)
+       {
+         if(opt.flags.dsa2)
+           {
+             /* If --enable-dsa2 is set, then we'll accept a hash
+                that is larger than we need.  If --enable-dsa2 is not
+                set, then we won't accept any hash that isn't exactly
+                the right size. */
+             if ((*(int *)hint) > gcry_md_get_algo_dlen (algo))
+               return 0;
+           }
+         else if (((*(int *)hint) != gcry_md_get_algo_dlen (algo)))
+           return 0;
+       }
 
       if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5
                            && algo != DIGEST_ALGO_SHA1
index 2ae851e..c0a6c3e 100644 (file)
@@ -1,6 +1,6 @@
 /* plaintext.c -  process plaintext packets
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- *               2005, 2006 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.
  *
@@ -91,7 +91,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
        log_info(_("data not saved; use option \"--output\" to save it\n"));
        nooutput = 1;
     }
-    else if( !opt.use_embedded_filename ) {
+    else if( !opt.flags.use_embedded_filename ) {
        fname = make_outfile_name( iobuf_get_real_fname(pt->buf) );
        if( !fname )
            fname = ask_outfile_name( pt->name, pt->namelen );
@@ -100,9 +100,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
              goto leave;
        }
     }
-    else {
-       fname = make_printable_string( pt->name, pt->namelen, 0 );
-    }
+    else
+      fname=utf8_to_native(pt->name,pt->namelen,0);
 
     if( nooutput )
        ;
@@ -318,9 +317,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
                        goto leave;
                      }
                    else if( fwrite( buffer, 1, len, fp ) != len ) {
+                     rc = (errno? gpg_error_from_errno (errno)
+                            : gpg_error (GPG_ERR_INTERNAL));
                      log_error("Error writing to `%s': %s\n",
                                fname, strerror(errno) );
-                     rc = G10ERR_WRITE_FILE;
                      xfree( buffer );
                      goto leave;
                    }
@@ -554,3 +554,44 @@ hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, STRLIST files,
 
     return 0;
 }
+
+
+/* Set up a plaintext packet with the appropriate filename.  If there
+   is a --set-filename, use it (it's already UTF8).  If there is a
+   regular filename, UTF8-ize it if necessary.  If there is no
+   filenames at all, set the field empty. */
+
+PKT_plaintext *
+setup_plaintext_name(const char *filename,IOBUF iobuf)
+{
+  PKT_plaintext *pt;
+
+  if(filename || opt.set_filename)
+    {
+      char *s;
+
+      if(opt.set_filename)
+       s=make_basename(opt.set_filename,iobuf_get_real_fname(iobuf));
+      else if(filename && !opt.flags.utf8_filename)
+       {
+         char *tmp=native_to_utf8(filename);
+         s=make_basename(tmp,iobuf_get_real_fname(iobuf));
+         xfree(tmp);
+       }
+      else
+       s=make_basename(filename,iobuf_get_real_fname(iobuf));
+
+      pt = xmalloc (sizeof *pt + strlen(s) - 1);
+      pt->namelen = strlen (s);
+      memcpy (pt->name, s, pt->namelen);
+      xfree (s);
+    }
+  else
+    {
+      /* no filename */
+      pt = xmalloc (sizeof *pt - 1);
+      pt->namelen = 0;
+    }
+
+  return pt;
+}
index 9bb35c8..fa37967 100644 (file)
@@ -320,11 +320,15 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
       }
     else 
       {
-       /* TODO: remove this check in the future once all the
-          variable-q DSA stuff makes it into the standard. */
-       if(!opt.expert
-          && sk->pubkey_algo==PUBKEY_ALGO_DSA
-          && gcry_md_get_algo_dlen (digest_algo)!=20)
+       /* 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
+          allow any hash since it must be a DSA2 key (if the hash is
+          too small, we'll fail in encode_md_value). */
+       if (sk->pubkey_algo==PUBKEY_ALGO_DSA
+            && (gcry_mpi_get_nbits (sk->skey[1])/8)==20
+            && !opt.flags.dsa2
+            && gcry_md_get_algo_dlen (digest_algo)!=20)
          {
            log_error(_("DSA requires the use of a 160 bit hash algorithm\n"));
            return G10ERR_GENERAL;
@@ -384,6 +388,32 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md )
     return rc;
 }
 
+
+
+static int
+match_dsa_hash (unsigned int qbytes)
+{
+  if (qbytes <= 20)
+    return DIGEST_ALGO_SHA1;
+#ifdef USE_SHA256
+  if (qbytes <= 28)
+    return DIGEST_ALGO_SHA224;
+  if (qbytes <= 32)
+    return DIGEST_ALGO_SHA256;
+#endif
+
+#ifdef USE_SHA512
+  if (qbytes <= 48)
+    return DIGEST_ALGO_SHA384;
+  if (qbytes <= 64)
+    return DIGEST_ALGO_SHA512;
+#endif
+  return DEFAULT_DIGEST_ALGO;
+  /* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong
+     answer we have if the larger SHAs aren't there. */
+}
+
+
 /*
   First try --digest-algo.  If that isn't set, see if the recipient
   has a preferred algorithm (which is also filtered through
@@ -397,7 +427,6 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md )
   the signing key prefs either before or after using the personal
   list?
 */
-
 static int
 hash_for(PKT_secret_key *sk)
 {
@@ -405,32 +434,61 @@ hash_for(PKT_secret_key *sk)
     return opt.def_digest_algo;
   else if( recipient_digest_algo )
     return recipient_digest_algo;
-  else if(sk->pubkey_algo==PUBKEY_ALGO_DSA
-         || (sk->is_protected && sk->protect.s2k.mode==1002))
+  else if(sk->pubkey_algo==PUBKEY_ALGO_DSA)
     {
-      /* The sk lives on a smartcard, or it's a DSA key.  DSA requires
-        a 160-bit hash, and current smartcards only handle SHA-1 and
-        RIPEMD/160 (i.e. 160-bit hashes).  This is correct now, but
-        may need revision as the cards add algorithms and/or DSA is
-        expanded to use larger hashes. */
+      unsigned int qbytes = gcry_mpi_get_nbits (sk->skey[1]) / 8;
+
+      /* It's a DSA key, so find a hash that is the same size as q or
+        larger.  If q is 160, assume it is an old DSA key and use a
+        160-bit hash unless --enable-dsa2 is set, in which case act
+        like a new DSA key that just happens to have a 160-bit q
+        (i.e. allow truncation).  If q is not 160, by definition it
+        must be a new DSA key. */
+
+      if (opt.personal_digest_prefs)
+       {
+         prefitem_t *prefs;
+
+         if (qbytes != 20 || opt.flags.dsa2)
+           {
+             for (prefs=opt.personal_digest_prefs; prefs->type; prefs++)
+               if (gcry_md_get_algo_dlen (prefs->value) >= qbytes)
+                 return prefs->value;
+           }
+         else
+           {
+             for (prefs=opt.personal_digest_prefs; prefs->type; prefs++)
+               if (gcry_md-get_algo_dlen (prefs->value) == qbytes)
+                 return prefs->value;
+           }
+       }
+
+      return match_dsa_hash(qbytes);
+    }
+  else if (sk->is_protected && sk->protect.s2k.mode==1002)
+    {
+      /* The sk lives on a smartcard, and current smartcards only
+        handle SHA-1 and RIPEMD/160.  This is correct now, but may
+        need revision as the cards add algorithms. */
 
       if(opt.personal_digest_prefs)
        {
          prefitem_t *prefs;
 
-         for(prefs=opt.personal_digest_prefs;prefs->type;prefs++)
-           if (gcry_md_get_algo_dlen (prefs->value) == 20)
+         for (prefs=opt.personal_digest_prefs;prefs->type;prefs++)
+           if (prefs->value==DIGEST_ALGO_SHA1
+                || prefs->value==DIGEST_ALGO_RMD160)
              return prefs->value;
        }
 
       return DIGEST_ALGO_SHA1;
     }
-  else if(PGP2 && sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 )
+  else if (PGP2 && sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 )
     {
-      /* Old-style PGP only understands MD5. */
+      /* Old-style PGP only understands MD5 */
       return DIGEST_ALGO_MD5;
     }
-  else if( opt.personal_digest_prefs )
+  else if ( opt.personal_digest_prefs )
     {
       /* It's not DSA, so we can use whatever the first hash algorithm
         is in the pref list */
@@ -440,6 +498,7 @@ hash_for(PKT_secret_key *sk)
     return DEFAULT_DIGEST_ALGO;
 }
 
+
 static int
 only_old_style( SK_LIST sk_list )
 {
@@ -537,21 +596,8 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
     u32 filesize;
     int rc = 0;
 
-    if (!opt.no_literal) {
-        if (fname || opt.set_filename) {
-            char *s = make_basename (opt.set_filename? opt.set_filename
-                                                     : fname,
-                                     iobuf_get_real_fname(inp));
-            pt = xmalloc (sizeof *pt + strlen(s) - 1);
-            pt->namelen = strlen (s);
-            memcpy (pt->name, s, pt->namelen);
-            xfree (s);
-        }
-        else { /* no filename */
-            pt = xmalloc (sizeof *pt - 1);
-            pt->namelen = 0;
-        }
-    }
+    if (!opt.no_literal)
+      pt=setup_plaintext_name(fname,inp);
 
     /* try to calculate the length of the data */
     if ( !iobuf_is_pipe_filename (fname) && *fname )
@@ -1367,16 +1413,19 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
       {
        /* Basically, this means use SHA1 always unless it's a v3 RSA
           key making a v3 cert (use MD5), or the user specified
-          something (use whatever they said).  They still must use a
-          160-bit hash with DSA, or the signature will fail.  Note
-          that this still allows the caller of make_keysig_packet to
-          override the user setting if it must. */
+          something (use whatever they said), or it's DSA (use the
+          best match).  They still can't pick an inappropriate hash
+          for DSA or the signature will fail.  Note that this still
+          allows the caller of make_keysig_packet to override the
+          user setting if it must. */
 
        if(opt.cert_digest_algo)
          digest_algo=opt.cert_digest_algo;
        else if(sk->pubkey_algo==PUBKEY_ALGO_RSA
                && pk->version<4 && sigversion<4)
          digest_algo = DIGEST_ALGO_MD5;
+       else if(sk->pubkey_algo==PUBKEY_ALGO_DSA)
+         digest_algo = match_dsa_hash (gcry_mpi_get_nbits (sk->skey[1])/8);
        else
          digest_algo = DIGEST_ALGO_SHA1;
       }
index ffee855..2098d67 100644 (file)
@@ -209,9 +209,10 @@ set_status_fd ( int fd )
                   fd, strerror(errno));
     }
     last_fd = fd;
-    register_primegen_progress ( progress_cb, "primegen" );
-    register_pk_dsa_progress ( progress_cb, "pk_dsa" );
-    register_pk_elg_progress ( progress_cb, "pk_elg" );
+#warning Use libgrypt calls for progress indicators
+/*     register_primegen_progress ( progress_cb, "primegen" ); */
+/*     register_pk_dsa_progress ( progress_cb, "pk_dsa" ); */
+/*     register_pk_elg_progress ( progress_cb, "pk_elg" ); */
 }
 
 int