[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-331-g0fc71f7

by Werner Koch cvs at cvs.gnupg.org
Fri Mar 7 10:56:53 CET 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  0fc71f7277c6f833f838bbd384f1a22d0c333e8e (commit)
       via  d8f0b83e4f04641e5e9adbdd8abada15380f981c (commit)
       via  dfb25d47a9fcfd7c7c084ea58744724cd5315086 (commit)
       via  db1f74ba5338f624f146a3cb41a346e46b15c8f9 (commit)
       via  90688b29f3701f4d3e2a5a49c5544fe8d2a84b2d (commit)
       via  7c4bfa599fa69c3a942c8deea83737a4c5a0806e (commit)
       via  5ca482d5f949444ffd453de158ee186ab07fc9b6 (commit)
       via  0ab752cc2d46bbd0077bed889676169b7aeb1eb6 (commit)
       via  76b1940ad6f5f058c4a6bec35902da9f6d4e27b0 (commit)
       via  63b7658a29809249d7aeb0423bf8c5a693eee0c7 (commit)
       via  9942a149ff2ab919c1b2916c7bc347e578a56b14 (commit)
       via  5105c8d2d344fd7301d456d8c13c7e90a54f7e98 (commit)
       via  179012ddd48e63ca83e8f5c24537a2db45c3e122 (commit)
       via  4ad123d6fe341da7768e43360375e17fa89e8e0d (commit)
       via  d2a6be24af0bf220bb448fdd50c0196faddee0f4 (commit)
       via  8fc9de8d6bf663f7c8419b42dab01f590a694d59 (commit)
      from  191e32026f02054b1edb4f02536875462fd0b6b3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 0fc71f7277c6f833f838bbd384f1a22d0c333e8e
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Nov 15 09:08:58 2013 +0100

    common: Fix build problem with Sun Studio compiler.
    
    * common/estream.c (ESTREAM_MUTEX_UNLOCK): Use int dummy dummy
    functions.
    (ESTREAM_MUTEX_INITIALIZE): Ditto.
    --
    
    GnuPG-bug-id: 1566
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 571bcd4662a351cfa55bbf1a79ed1bc26da5780f)
    
    Reolved conflicts:
    	common/estream.c
    
    Warning: estream.c still uses pth_mutex_* which is definitely wrong.
             Needs to be investigated.

diff --git a/common/estream.c b/common/estream.c
index 79e3efb..9c15100 100644
--- a/common/estream.c
+++ b/common/estream.c
@@ -171,7 +171,8 @@ typedef pth_mutex_t estream_mutex_t;
   ((pth_mutex_acquire (&(mutex), 1, NULL) == TRUE) ? 0 : -1)
 # define ESTREAM_MUTEX_INITIALIZE(mutex)  \
   pth_mutex_init    (&(mutex))
-#else
+
+#else /*!HAVE_NPTH*/
 
 typedef void *estream_mutex_t;
 
@@ -190,10 +191,11 @@ dummy_mutex_call_int (estream_mutex_t mutex)
 
 # define ESTREAM_MUTEX_INITIALIZER NULL
 # define ESTREAM_MUTEX_LOCK(mutex) dummy_mutex_call_void ((mutex))
-# define ESTREAM_MUTEX_UNLOCK(mutex) dummy_mutex_call_void ((mutex))
+# define ESTREAM_MUTEX_UNLOCK(mutex) dummy_mutex_call_int ((mutex))
 # define ESTREAM_MUTEX_TRYLOCK(mutex) dummy_mutex_call_int ((mutex))
-# define ESTREAM_MUTEX_INITIALIZE(mutex) dummy_mutex_call_void ((mutex))
-#endif
+# define ESTREAM_MUTEX_INITIALIZE(mutex) dummy_mutex_call_int ((mutex))
+
+#endif /*!HAVE_NPTH*/
 
 /* Primitive system I/O.  */
 

commit d8f0b83e4f04641e5e9adbdd8abada15380f981c
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Oct 11 09:25:58 2013 +0200

    gpg: Do not require a trustdb with --always-trust.
    
    * g10/tdbio.c (tdbio_set_dbname): Add arg R_NOFILE.
    * g10/trustdb.c (trustdb_args): Add field no_trustdb.
    (init_trustdb): Set that field.
    (revalidation_mark):  Take care of a nonexistent trustdb file.
    (read_trust_options): Ditto.
    (tdb_get_ownertrust): Ditto.
    (tdb_get_min_ownertrust): Ditto.
    (tdb_update_ownertrust): Ditto.
    (update_min_ownertrust): Ditto.
    (tdb_clear_ownertrusts): Ditto.
    (tdb_cache_disabled_value): Ditto.
    (tdb_check_trustdb_stale): Ditto.
    (tdb_get_validity_core): Ditto.
    * g10/gpg.c (main): Do not create a trustdb with most commands for
    trust-model always.
    --
    
    This slightly changes the semantics of most commands in that they
    won't create a trustdb if --trust-model=always is used.  It just does
    not make sense to create a trustdb if there is no need for it.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 1a0eeaacd1bf09fe5125dbc3f56016bc20f3512e)
    
    Resolved conflicts:
    	NEWS
    	g10/trustdb.c: Manually apply changes due to changed
                           function names.
    
    Note that this also includes the fix for clear_ownertrust, see
    GnuPG-bug-id: 1622.

diff --git a/NEWS b/NEWS
index 2efc395..da771f1 100644
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,10 @@ Noteworthy changes in version 2.1.0-betaN (unreleased)
  * Only the major version number is by default included in the armored
    output.
 
+ * Do not create a trustdb file if --trust-model=always is used.
+
+ * Protect against rogue keyservers sending secret keys.
+
 
 Noteworthy changes in version 2.1.0beta3 (2011-12-20)
 -----------------------------------------------------
diff --git a/g10/gpg.c b/g10/gpg.c
index 15cbe4b..65a9cab 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -3539,15 +3539,11 @@ main (int argc, char **argv)
       case aListTrustDB:
         rc = setup_trustdb (argc? 1:0, trustdb_name);
         break;
-      case aEncr:
-      case aEncrFiles:
+      default:
         /* If we are using TM_ALWAYS, we do not need to create the
            trustdb.  */
         rc = setup_trustdb (opt.trust_model != TM_ALWAYS, trustdb_name);
         break;
-      default:
-        rc = setup_trustdb (1, trustdb_name );
-        break;
       }
     if (rc)
       log_error (_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc));
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 0a659b1..db7a67c 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -480,7 +480,7 @@ create_version_record (void)
 
 
 int
-tdbio_set_dbname( const char *new_dbname, int create )
+tdbio_set_dbname( const char *new_dbname, int create, int *r_nofile)
 {
     char *fname;
     static int initialized = 0;
@@ -490,6 +490,8 @@ tdbio_set_dbname( const char *new_dbname, int create )
 	initialized = 1;
     }
 
+    *r_nofile = 0;
+
     if(new_dbname==NULL)
       fname=make_filename(opt.homedir,"trustdb" EXTSEP_S GPGEXT_GPG, NULL);
     else if (*new_dbname != DIRSEP_C )
@@ -515,7 +517,9 @@ tdbio_set_dbname( const char *new_dbname, int create )
 	    xfree(fname);
 	    return G10ERR_TRUSTDB;
 	}
-	if( create ) {
+	if (!create)
+          *r_nofile = 1;
+        else {
 	    FILE *fp;
 	    TRUSTREC rec;
 	    int rc;
diff --git a/g10/tdbio.h b/g10/tdbio.h
index 252a393..4f37de4 100644
--- a/g10/tdbio.h
+++ b/g10/tdbio.h
@@ -93,7 +93,7 @@ typedef struct trust_record TRUSTREC;
 
 /*-- tdbio.c --*/
 int tdbio_update_version_record(void);
-int tdbio_set_dbname( const char *new_dbname, int create );
+int tdbio_set_dbname( const char *new_dbname, int create, int *r_nofile);
 const char *tdbio_get_dbname(void);
 void tdbio_dump_record( TRUSTREC *rec, FILE *fp );
 int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 733fa79..ea07399 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -49,19 +49,22 @@ typedef struct key_item **KeyHashTable; /* see new_key_hash_table() */
  * the item right after the last one has a keyblock set to NULL.
  * Maybe we can drop this thing and replace it by key_item
  */
-struct key_array {
+struct key_array
+{
   KBNODE keyblock;
 };
 
 
-/* control information for the trust DB */
-static struct {
-    int init;
-    int level;
-    char *dbname;
+/* Control information for the trust DB.  */
+static struct
+{
+  int init;
+  int level;
+  char *dbname;
+  int no_trustdb;
 } trustdb_args;
 
-/* some globals */
+/* Some globals.  */
 static struct key_item *user_utk_list; /* temp. used to store --trusted-keys */
 static struct key_item *utk_list;      /* all ultimately trusted keys */
 
@@ -417,7 +420,7 @@ how_to_fix_the_trustdb ()
 
 
 void
-init_trustdb()
+init_trustdb ()
 {
   int level = trustdb_args.level;
   const char* dbname = trustdb_args.dbname;
@@ -429,7 +432,7 @@ init_trustdb()
 
   if(level==0 || level==1)
     {
-      int rc = tdbio_set_dbname( dbname, !!level );
+      int rc = tdbio_set_dbname( dbname, !!level, &trustdb_args.no_trustdb);
       if( rc )
 	log_fatal("can't init trustdb: %s\n", g10_errstr(rc) );
     }
@@ -525,10 +528,13 @@ void
 tdb_revalidation_mark (void)
 {
   init_trustdb();
-  /* we simply set the time for the next check to 1 (far back in 1970)
-   * so that a --update-trustdb will be scheduled */
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    return;
+
+  /* We simply set the time for the next check to 1 (far back in 1970)
+     so that a --update-trustdb will be scheduled.  */
   if (tdbio_write_nextcheck (1))
-      do_sync ();
+    do_sync ();
   pending_check_trustdb = 1;
 }
 
@@ -560,8 +566,10 @@ read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck,
   TRUSTREC opts;
 
   init_trustdb();
-
-  read_record(0,&opts,RECTYPE_VER);
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    memset (&opts, 0, sizeof opts);
+  else
+    read_record (0, &opts, RECTYPE_VER);
 
   if(trust_model)
     *trust_model=opts.r.ver.trust_model;
@@ -619,6 +627,9 @@ tdb_get_ownertrust ( PKT_public_key *pk)
   TRUSTREC rec;
   int rc;
 
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    return TRUST_UNKNOWN;
+
   rc = read_trust_record (pk, &rec);
   if (rc == -1)
     return TRUST_UNKNOWN; /* no record yet */
@@ -638,6 +649,9 @@ tdb_get_min_ownertrust (PKT_public_key *pk)
   TRUSTREC rec;
   int rc;
 
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    return TRUST_UNKNOWN;
+
   rc = read_trust_record (pk, &rec);
   if (rc == -1)
     return TRUST_UNKNOWN; /* no record yet */
@@ -661,6 +675,9 @@ tdb_update_ownertrust (PKT_public_key *pk, unsigned int new_trust )
   TRUSTREC rec;
   int rc;
 
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    return;
+
   rc = read_trust_record (pk, &rec);
   if (!rc)
     {
@@ -705,6 +722,9 @@ update_min_ownertrust (u32 *kid, unsigned int new_trust )
   TRUSTREC rec;
   int rc;
 
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    return;
+
   pk = xmalloc_clear (sizeof *pk);
   rc = get_pubkey (pk, kid);
   if (rc)
@@ -761,6 +781,11 @@ tdb_clear_ownertrusts (PKT_public_key *pk)
   TRUSTREC rec;
   int rc;
 
+  init_trustdb ();
+
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    return 0;
+
   rc = read_trust_record (pk, &rec);
   if (!rc)
     {
@@ -865,6 +890,9 @@ tdb_cache_disabled_value (PKT_public_key *pk)
 
   init_trustdb();
 
+  if (trustdb_args.no_trustdb)
+    return 0;  /* No trustdb => not disabled.  */
+
   rc = read_trust_record (pk, &trec);
   if (rc && rc != -1)
     {
@@ -893,6 +921,10 @@ tdb_check_trustdb_stale (void)
   static int did_nextcheck=0;
 
   init_trustdb ();
+
+  if (trustdb_args.no_trustdb)
+    return;  /* No trustdb => can't be stale.  */
+
   if (!did_nextcheck
       && (opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC))
     {
@@ -931,6 +963,14 @@ tdb_get_validity_core (PKT_public_key *pk, PKT_user_id *uid,
   unsigned int validity;
 
   init_trustdb ();
+
+  /* If we have no trustdb (which also means it has not been created)
+     and the trust-model is always, we don't know the validity -
+     return immediately.  If we won't do that the tdbio code would try
+     to open the trustdb and run into a fatal error.  */
+  if (trustdb_args.no_trustdb && opt.trust_model == TM_ALWAYS)
+    return TRUST_UNKNOWN;
+
   check_trustdb_stale();
 
   if(opt.trust_model==TM_DIRECT)

commit dfb25d47a9fcfd7c7c084ea58744724cd5315086
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Oct 4 18:34:56 2013 +0200

    gpg: Print a "not found" message for an unknown key in --key-edit.
    
    * g10/keyedit.c (keyedit_menu): Print message.
    --
    
    GnuPG-bug-id: 1420
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 0bf54e60d31389812d05c3fd29bece876204561d)
    
    Resolved conflicts:
    	g10/keyedit.c: Fix white spaces

diff --git a/g10/keyedit.c b/g10/keyedit.c
index 2b8b582..47a2234 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1506,7 +1506,10 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
   /* Get the public key */
   err = get_pubkey_byname (ctrl, NULL, NULL, username, &keyblock, &kdbhd, 1, 1);
   if (err)
-    goto leave;
+    {
+      log_error (_("key \"%s\" not found: %s\n"), username, gpg_strerror (err));
+      goto leave;
+    }
   if (fix_keyblock (keyblock))
     modified++;
   if (collapse_uids (&keyblock))

commit db1f74ba5338f624f146a3cb41a346e46b15c8f9
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Oct 4 13:44:39 2013 +0200

    gpg: Protect against rogue keyservers sending secret keys.
    
    * g10/options.h (IMPORT_NO_SECKEY): New.
    * g10/keyserver.c (keyserver_spawn, keyserver_import_cert): Set new
    flag.
    * g10/import.c (import_secret_one): Deny import if flag is set.
    --
    
    By modifying a keyserver or a DNS record to send a secret key, an
    attacker could trick a user into signing using a different key and
    user id.  The trust model should protect against such rogue keys but
    we better make sure that secret keys are never received from remote
    sources.
    
    Suggested-by: Stefan Tomanek
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit e7abed3448c1c1a4e756c12f95b665b517d22ebe)
    
    Resolved conflicts:
    	g10/import.c
    	g10/keyserver.c

diff --git a/g10/import.c b/g10/import.c
index 74443ef..c3ad536 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1563,6 +1563,12 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
     }
   stats->secret_read++;
 
+  if ((options & IMPORT_NO_SECKEY))
+    {
+      log_error (_("importing secret keys not allowed\n"));
+      return 0;
+    }
+
   if (!uidnode)
     {
       log_error( _("key %s: no user ID\n"), keystr_from_pk (pk));
diff --git a/g10/keyserver.c b/g10/keyserver.c
index 4de56fc..28b4a10 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -1578,11 +1578,14 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
          harmless to ignore them, but ignoring them does make gpg
          complain about "no valid OpenPGP data found".  One way to do
          this could be to continue parsing this line-by-line and make
-         a temp iobuf for each key. */
+         a temp iobuf for each key.  Note that we don't allow the
+         import of secret keys from a keyserver.  Keyservers should
+         never accept or send them but we better protect against rogue
+         keyservers. */
 
       import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL,
-                             opt.keyserver_options.import_options);
-
+                             (opt.keyserver_options.import_options
+                              | IMPORT_NO_SECKEY));
       import_print_stats (stats_handle);
       import_release_stats_handle (stats_handle);
     }
@@ -1721,7 +1724,8 @@ keyserver_import_cert (ctrl_t ctrl,
       opt.no_armor=1;
 
       err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
-                                  opt.keyserver_options.import_options);
+                                   (opt.keyserver_options.import_options
+                                    | IMPORT_NO_SECKEY));
 
       opt.no_armor=armor_status;
 
diff --git a/g10/options.h b/g10/options.h
index 15ae412..47b8bfb 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -324,6 +324,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
 #define IMPORT_MERGE_ONLY                (1<<4)
 #define IMPORT_MINIMAL                   (1<<5)
 #define IMPORT_CLEAN                     (1<<6)
+#define IMPORT_NO_SECKEY                 (1<<7)
 
 #define EXPORT_LOCAL_SIGS                (1<<0)
 #define EXPORT_ATTRIBUTES                (1<<1)

commit 90688b29f3701f4d3e2a5a49c5544fe8d2a84b2d
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Aug 19 11:44:59 2013 +0200

    agent: Fix UPDATESTARTUPTTY for ssh.
    
    * agent/command-ssh.c (setup_ssh_env): Fix env setting.
    --
    
    gniibe reported this to gnupg-devel on 2012-07-04:
    
      [...]
      (2) UPDATESTARTUPTTY doesn't work to switch TTY for pinentry for
          SSH.
    
      [...]
    
      Current implementation:
    
          In the function start_command_handler_ssh, the logic puts
          priority on ctrl->session_env which is initialized by
          agent_init_default_ctrl.  There are always GPG_TTY and TERM
          defined, because lines around 968 in gpg-agent.c, it says:
    
      	/* Make sure that we have a default ttyname. */
    
          While UPDATESTARTUPTTY updates opt.startup_env, it doesn't
          affect at all.
    
      Here is a patch to point the issue.  Tested and works for me.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 9f5578c29adba6d4f7d3650121d07322c2f8d254)

diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 4bd1aa7..4191d6f 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -3370,8 +3370,7 @@ setup_ssh_env (ctrl_t ctrl)
   const char *value;
 
   for (idx=0; !err && names[idx]; idx++)
-    if (!session_env_getenv (ctrl->session_env, names[idx])
-        && (value = session_env_getenv (opt.startup_env, names[idx])))
+      if ((value = session_env_getenv (opt.startup_env, names[idx])))
       err = session_env_setenv (ctrl->session_env, names[idx], value);
 
   if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype)

commit 7c4bfa599fa69c3a942c8deea83737a4c5a0806e
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Aug 19 11:22:11 2013 +0200

    gpgv: Init Libgcrypt to avoid syslog warning.
    
    * g10/gpgv.c (main): Check libgcrypt version and disable secure
    memory.
    --
    
    GnuPG-bug-id: 1376
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 3966eb244518d5612385d35a5149f7164a9fb707)
    
    Resolved conflicts:
    	g10/gpgv.c

diff --git a/g10/gpgv.c b/g10/gpgv.c
index debde9d..d79b899 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -151,11 +151,18 @@ main( int argc, char **argv )
   i18n_init();
   init_common_subsystems (&argc, &argv);
 
+  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
+    {
+      log_fatal ( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
+                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
+    }
+  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+
   gnupg_init_signals (0, NULL);
 
   opt.command_fd = -1; /* no command fd */
   opt.pgp2_workarounds = 1;
-  opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
+  opt.keyserver_options.options |= KEYSERVER_AUTO_KEY_RETRIEVE;
   opt.trust_model = TM_ALWAYS;
   opt.batch = 1;
 
@@ -164,6 +171,7 @@ main( int argc, char **argv )
   tty_no_terminal(1);
   tty_batchmode(1);
   dotlock_disable ();
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
 
   pargs.argc = &argc;
   pargs.argv = &argv;

commit 5ca482d5f949444ffd453de158ee186ab07fc9b6
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Aug 6 10:31:54 2013 +0200

    Improve libcurl detection.
    
    * m4/libcurl.m4: Do not use AC_PATH_PROG if --with-libcurl as been
    given.  Suggested by John Marshall.
    --
    
    GnuPG-bug-id: 1510
    (cherry picked from commit 110b52fffa77b339e6d59eba939408f7e87e7138)

diff --git a/m4/libcurl.m4 b/m4/libcurl.m4
index 7d1dbd3..f6a631b 100644
--- a/m4/libcurl.m4
+++ b/m4/libcurl.m4
@@ -71,7 +71,11 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG],
      if test -d "$_libcurl_with" ; then
         LIBCURL_CPPFLAGS="-I$withval/include"
         _libcurl_ldflags="-L$withval/lib"
-        AC_PATH_PROG([_libcurl_config],["$withval/bin/curl-config"])
+        if test -x "$withval/bin/curl-config" ; then
+          _libcurl_config="$withval/bin/curl-config"
+        else
+          _libcurl_config=
+        fi
      else
 	AC_PATH_PROG([_libcurl_config],[curl-config])
      fi

commit 0ab752cc2d46bbd0077bed889676169b7aeb1eb6
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Aug 6 10:04:12 2013 +0200

    gpg: Remove legacy keyserver examples from the template conf file.
    
    * g10/options.skel: Update.
    
    (cherry picked from commit f3c5cc8bcd37e38b5d65db6a50466e22d03d1f0c)

diff --git a/g10/options.skel b/g10/options.skel
index 87bbd4e..9303f79 100644
--- a/g10/options.skel
+++ b/g10/options.skel
@@ -101,14 +101,9 @@ require-cross-certification
 #
 # Example HKP keyservers:
 #      hkp://keys.gnupg.net
-#      hkp://subkeys.pgp.net
-#
-# Example email keyserver:
-#      mailto:pgp-public-keys at keys.pgp.net
 #
 # Example LDAP keyservers:
 #      ldap://pgp.surfnet.nl:11370
-#      ldap://keyserver.pgp.com
 #
 # Regular URL syntax applies, and you can set an alternate port
 # through the usual method:
@@ -131,8 +126,6 @@ require-cross-certification
 keyserver hkp://keys.gnupg.net
 #keyserver http://http-keys.gnupg.net
 #keyserver mailto:pgp-public-keys at keys.nl.pgp.net
-#keyserver ldap://pgp.surfnet.nl:11370
-#keyserver ldap://keyserver.pgp.com
 
 # Common options for keyserver functions:
 #

commit 76b1940ad6f5f058c4a6bec35902da9f6d4e27b0
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Mar 7 09:46:44 2014 +0100

    w32: Define WINVER only if needed.
    
    * common/sysutils.c (WINVER): Define only if less that 5.0.

diff --git a/common/sysutils.c b/common/sysutils.c
index a00cd94..f0c2ad8 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -54,7 +54,9 @@
 # include <sys/resource.h>
 #endif
 #ifdef HAVE_W32_SYSTEM
-# define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
+# if WINVER < 0x0500
+#   define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
+# endif
 # include <windows.h>
 #endif
 #ifdef HAVE_NPTH

commit 63b7658a29809249d7aeb0423bf8c5a693eee0c7
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Aug 1 14:02:50 2013 +0200

    w32: Remove unused code.
    
    * jnlib/w32-reg.c (write_w32_registry_string): Remove.

diff --git a/common/w32-reg.c b/common/w32-reg.c
index 3ef7a0a..428705c 100644
--- a/common/w32-reg.c
+++ b/common/w32-reg.c
@@ -223,102 +223,4 @@ read_w32_registry_string (const char *root, const char *dir, const char *name)
 }
 
 
-/* Note: This code is not well tested.  However, it is not used in
-   GnuPG.  */
-#if 0
-int
-write_w32_registry_string (const char *root, const char *dir,
-                           const char *name, const char *value)
-{
-  HKEY root_key, reg_key;
-#ifdef HAVE_W32CE_SYSTEM
-  wchar_t *wdir, *wname, *wvalue;
-  DWORD disp;
-
-  if ( !(root_key = get_root_key(root) ) )
-    return -1;
-
-  wdir = utf8_to_wchar (dir);
-  if (!wdir)
-    return -1;
-
-  if (RegOpenKeyEx (root_key, wdir, 0, 0, &reg_key))
-    {
-      jnlib_free (wdir);
-      return -1;
-    }
-  jnlib_free (wdir);
-
-  if (name)
-    {
-      wname = utf8_to_wchar (name);
-      if (!wname)
-        return -1;
-    }
-  else
-    wname = NULL;
-
-  wvalue = utf8_to_wchar (value);
-  if (wvalue)
-    {
-      jnlib_free (wname);
-      return -1;
-    }
-
-  if (RegSetValueEx (reg_key, wname, 0, REG_SZ,
-                     (BYTE *)wvalue, wcslen (wvalue)) != ERROR_SUCCESS )
-    {
-
-      if (RegCreateKeyEx (root_key, wname, 0, NULL, 0, 0, NULL,
-                          &reg_key, &disp) != ERROR_SUCCESS)
-        {
-          RegCloseKey(reg_key);
-          jnlib_free (wname);
-          jnlib_free (wvalue);
-          return -1;
-        }
-      if (RegSetValueEx (reg_key, wname, 0, REG_SZ,
-                         (BYTE *)wvalue, wcslen (wvalue)) != ERROR_SUCCESS )
-        {
-          RegCloseKey(reg_key);
-          jnlib_free (wname);
-          jnlib_free (wvalue);
-          return -1;
-        }
-    }
-
-  jnlib_free (wname);
-  jnlib_free (wvalue);
-  RegCloseKey (reg_key);
-  return 0;
-#else /*!HAVE_W32CE_SYSTEM*/
-
-  if ( !(root_key = get_root_key(root) ) )
-    return -1;
-
-  if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, &reg_key )
-       != ERROR_SUCCESS )
-    return -1;
-
-  if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value,
-                      strlen( value ) ) != ERROR_SUCCESS )
-    {
-      if ( RegCreateKey( root_key, name, &reg_key ) != ERROR_SUCCESS )
-        {
-          RegCloseKey(reg_key);
-          return -1;
-        }
-      if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value,
-                          strlen( value ) ) != ERROR_SUCCESS )
-        {
-          RegCloseKey(reg_key);
-          return -1;
-        }
-    }
-
-  RegCloseKey (reg_key);
-  return 0;
-#endif /*!HAVE_W32CE_SYSTEM*/
-}
-#endif /*0*/
 #endif /*HAVE_W32_SYSTEM*/

commit 9942a149ff2ab919c1b2916c7bc347e578a56b14
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Jul 3 15:20:25 2013 +0200

    agent: Make --allow-mark-trusted the default.
    
    * agent/gpg-agent.c (opts, main): Add option --no-allow-mark-trusted.
    Put this option into the gpgconf-list.
    (main): Enable opt.allow_mark_trusted by default.
    * tools/gpgconf-comp.c (gc_options_gpg_agent): Replace
    allow-mark-trusted by no-allow-mark-trusted.
    
    * agent/trustlist.c (agent_marktrusted): Always set the "relax" flag.
    
    --
    
    These changes have been in effect for the Gpg4win Windows version
    since 2011-01-24 and thus first released with Gpg4win 2.1.0.  Given
    the current state of PKIX it does not make any sense to lure the Unix
    user into false security by making it harder to trust self-signed or
    CAcert certificates.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 90b419f3e9d05e509348d047e05fcc79e87be6cf)
    
    Resolved conflicts:
    	NEWS
    	agent/gpg-agent.c

diff --git a/NEWS b/NEWS
index 0c02a90..2efc395 100644
--- a/NEWS
+++ b/NEWS
@@ -6,8 +6,14 @@ Noteworthy changes in version 2.1.0-betaN (unreleased)
 
  * The GNU Pth library has been replaced by the new nPth library.
 
- * New option --enable-putty-support to allow gpg-agent to act as a
-   Pageant replacement including full smartcard support.
+ * By default the users are now asked via the Pinentry whether they
+   trust an X.509 root key.  To prohibit interactive marking of such
+   keys, the new option --no-allow-mark-trusted may be used.
+
+ * The included ssh agent does now support ECDSA keys.
+
+ * The new option --enable-putty-support allows gpg-agent on Windows
+   to act as a Pageant replacement with full smartcard support.
 
  * Removed support for the original HKP keyserver which is not anymore
    used by any site.
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 25750f2..87915d6 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -116,6 +116,7 @@ enum cmd_and_opt_values
 
   oIgnoreCacheForSigning,
   oAllowMarkTrusted,
+  oNoAllowMarkTrusted,
   oAllowPresetPassphrase,
   oAllowLoopbackPinentry,
   oKeepTTY,
@@ -137,8 +138,8 @@ static ARGPARSE_OPTS opts[] = {
 
   { 301, NULL, 0, N_("@Options:\n ") },
 
-  { oServer,   "server",     0, N_("run in server mode (foreground)") },
   { oDaemon,   "daemon",     0, N_("run in daemon mode (background)") },
+  { oServer,   "server",     0, N_("run in server mode (foreground)") },
   { oVerbose, "verbose",     0, N_("verbose") },
   { oQuiet,	"quiet",     0, N_("be somewhat more quiet") },
   { oSh,	"sh",        0, N_("sh-style command output") },
@@ -191,8 +192,9 @@ static ARGPARSE_OPTS opts[] = {
 
   { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0,
                                N_("do not use the PIN cache when signing")},
-  { oAllowMarkTrusted, "allow-mark-trusted", 0,
-                             N_("allow clients to mark keys as \"trusted\"")},
+  { oNoAllowMarkTrusted, "no-allow-mark-trusted", 0,
+                            N_("disallow clients to mark keys as \"trusted\"")},
+  { oAllowMarkTrusted, "allow-mark-trusted", 0, "@"},
   { oAllowPresetPassphrase, "allow-preset-passphrase", 0,
                              N_("allow presetting passphrase")},
   { oAllowLoopbackPinentry, "allow-loopback-pinentry", 0,
@@ -523,7 +525,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
       opt.max_passphrase_days = MAX_PASSPHRASE_DAYS;
       opt.enable_passhrase_history = 0;
       opt.ignore_cache_for_signing = 0;
-      opt.allow_mark_trusted = 0;
+      opt.allow_mark_trusted = 1;
       opt.disable_scdaemon = 0;
       disable_check_own_socket = 0;
       return 1;
@@ -583,6 +585,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
     case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
 
     case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break;
+    case oNoAllowMarkTrusted: opt.allow_mark_trusted = 0; break;
 
     case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break;
 
@@ -1008,7 +1011,7 @@ main (int argc, char **argv )
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("ignore-cache-for-signing:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
-      es_printf ("allow-mark-trusted:%lu:\n",
+      es_printf ("no-allow-mark-trusted:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("disable-scdaemon:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
diff --git a/agent/trustlist.c b/agent/trustlist.c
index 7829f01..e8f8fff 100644
--- a/agent/trustlist.c
+++ b/agent/trustlist.c
@@ -774,7 +774,8 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
     }
   else
     es_fputs (nameformatted, fp);
-  es_fprintf (fp, "\n%s%s %c\n", yes_i_trust?"":"!", fprformatted, flag);
+  es_fprintf (fp, "\n%s%s %c%s\n", yes_i_trust?"":"!", fprformatted, flag,
+              flag == 'S'? " relax":"");
   if (es_ferror (fp))
     err = gpg_error_from_syserror ();
 
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index e97c7bd..4906994 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -542,8 +542,8 @@ static gc_option_t gc_options_gpg_agent[] =
    { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
-   { "allow-mark-trusted", GC_OPT_FLAG_RUNTIME,
-     GC_LEVEL_ADVANCED, "gnupg", "allow clients to mark keys as \"trusted\"",
+   { "no-allow-mark-trusted", GC_OPT_FLAG_RUNTIME,
+     GC_LEVEL_ADVANCED, "gnupg", "disallow clients to mark keys as \"trusted\"",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
      "gnupg", "do not grab keyboard and mouse",

commit 5105c8d2d344fd7301d456d8c13c7e90a54f7e98
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Mar 7 09:46:44 2014 +0100

    ssh: Add support for Putty.
    
    * agent/gpg-agent.c [W32]: Include Several Windows header.
    (opts): Change help text for enable-ssh-support.
    (opts, main): Add option --enable-putty-support
    (putty_support, PUTTY_IPC_MAGIC, PUTTY_IPC_MAXLEN): New for W32.
    (agent_init_default_ctrl): Add and asssert call.
    (putty_message_proc, putty_message_thread): New.
    (handle_connections) [W32]: Start putty message thread.
    * common/sysutils.c (w32_get_user_sid): New for W32 only
    * tools/gpgconf-comp.c (gc_options_gpg_agent): Add
    --enable-ssh-support and --enable-putty-support.  Make the
    configuration group visible at basic level.
    * agent/command-ssh.c (serve_mmapped_ssh_request): New for W32 only.
    --
    
    This patch enables support for Putty.  It has been tested with Putty
    0.62 using an Unix created ssh key copied to the private-keys-v1.d
    directory on Windows and with a manually crafted sshcontrol file.  It
    also works with a smartcard key.
    
    May thanks to gniibe who implemented a proxy in Python to test the
    putty/gpg-agent communication.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 9f32499f99a0817f63f7a73b09bdcebe60d4775d)
    
    Resolved conflicts:
    	NEWS
    	agent/agent.h
    	agent/gpg-agent.c: Convert from pth to npth.
    	common/sysutils.c
    	common/sysutils.h

diff --git a/NEWS b/NEWS
index 7eb1fe9..0c02a90 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ Noteworthy changes in version 2.1.0-betaN (unreleased)
 
  * The GNU Pth library has been replaced by the new nPth library.
 
+ * New option --enable-putty-support to allow gpg-agent to act as a
+   Pageant replacement including full smartcard support.
+
  * Removed support for the original HKP keyserver which is not anymore
    used by any site.
 
diff --git a/agent/agent.h b/agent/agent.h
index d409300..eac7ba5 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -289,9 +289,14 @@ gpg_error_t agent_print_status (ctrl_t ctrl, const char *keyword,
 void bump_key_eventcounter (void);
 void bump_card_eventcounter (void);
 void start_command_handler (ctrl_t, gnupg_fd_t, gnupg_fd_t);
-gpg_error_t pinentry_loopback(ctrl_t, const char *keyword,
-	                      unsigned char **buffer, size_t *size,
-			      size_t max_length);
+gpg_error_t pinentry_loopback (ctrl_t, const char *keyword,
+	                       unsigned char **buffer, size_t *size,
+			       size_t max_length);
+
+#ifdef HAVE_W32_SYSTEM
+int serve_mmapped_ssh_request (ctrl_t ctrl,
+                               unsigned char *request, size_t maxreqlen);
+#endif /*HAVE_W32_SYSTEM*/
 
 /*-- command-ssh.c --*/
 ssh_control_file_t ssh_open_control_file (void);
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 46aa94c..4bd1aa7 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -3443,3 +3443,149 @@ start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
   if (stream_sock)
     es_fclose (stream_sock);
 }
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Serve one ssh-agent request.  This is used for the Putty support.
+   REQUEST is the the mmapped memory which may be accessed up to a
+   length of MAXREQLEN.  Returns 0 on success which also indicates
+   that a valid SSH response message is now in REQUEST.  */
+int
+serve_mmapped_ssh_request (ctrl_t ctrl,
+                           unsigned char *request, size_t maxreqlen)
+{
+  gpg_error_t err;
+  int send_err = 0;
+  int valid_response = 0;
+  ssh_request_spec_t *spec;
+  u32 msglen;
+  estream_t request_stream, response_stream;
+
+  if (setup_ssh_env (ctrl))
+    goto leave; /* Error setting up the environment.  */
+
+  if (maxreqlen < 5)
+    goto leave; /* Caller error.  */
+
+  msglen = uint32_construct (request[0], request[1], request[2], request[3]);
+  if (msglen < 1 || msglen > maxreqlen - 4)
+    {
+      log_error ("ssh message len (%u) out of range", (unsigned int)msglen);
+      goto leave;
+    }
+
+  spec = request_spec_lookup (request[4]);
+  if (!spec)
+    {
+      send_err = 1;  /* Unknown request type.  */
+      goto leave;
+    }
+
+  /* Create a stream object with the data part of the request.  */
+  if (spec->secret_input)
+    request_stream = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
+  else
+    request_stream = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
+  if (!request_stream)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+  /* We have to disable the estream buffering, because the estream
+     core doesn't know about secure memory.  */
+  if (es_setvbuf (request_stream, NULL, _IONBF, 0))
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+  /* Copy the request to the stream but omit the request type.  */
+  err = stream_write_data (request_stream, request + 5, msglen - 1);
+  if (err)
+    goto leave;
+  es_rewind (request_stream);
+
+  response_stream = es_fopenmem (0, "r+b");
+  if (!response_stream)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  if (opt.verbose)
+    log_info ("ssh request handler for %s (%u) started\n",
+	       spec->identifier, spec->type);
+
+  err = (*spec->handler) (ctrl, request_stream, response_stream);
+
+  if (opt.verbose)
+    {
+      if (err)
+        log_info ("ssh request handler for %s (%u) failed: %s\n",
+                  spec->identifier, spec->type, gpg_strerror (err));
+      else
+        log_info ("ssh request handler for %s (%u) ready\n",
+                  spec->identifier, spec->type);
+    }
+
+  es_fclose (request_stream);
+  request_stream = NULL;
+
+  if (err)
+    {
+      send_err = 1;
+      goto leave;
+    }
+
+  /* Put the response back into the mmapped buffer.  */
+  {
+    void *response_data;
+    size_t response_size;
+
+    /* NB: In contrast to the request-stream, the response stream
+       includes the the message type byte.  */
+    if (es_fclose_snatch (response_stream, &response_data, &response_size))
+      {
+        log_error ("snatching ssh response failed: %s",
+                   gpg_strerror (gpg_error_from_syserror ()));
+        send_err = 1; /* Ooops.  */
+        goto leave;
+      }
+
+    if (opt.verbose > 1)
+      log_info ("sending ssh response of length %u\n",
+                (unsigned int)response_size);
+    if (response_size > maxreqlen - 4)
+      {
+        log_error ("invalid length of the ssh response: %s",
+                   gpg_strerror (GPG_ERR_INTERNAL));
+        es_free (response_data);
+        send_err = 1;
+        goto leave;
+      }
+
+    request[0] = response_size >> 24;
+    request[1] = response_size >> 16;
+    request[2] = response_size >>  8;
+    request[3] = response_size >>  0;
+    memcpy (request+4, response_data, response_size);
+    es_free (response_data);
+    valid_response = 1;
+  }
+
+ leave:
+  if (send_err)
+    {
+      request[0] = 0;
+      request[1] = 0;
+      request[2] = 0;
+      request[3] = 1;
+      request[4] = SSH_RESPONSE_FAILURE;
+      valid_response = 1;
+    }
+
+  /* Reset the SCD in case it has been used. */
+  agent_reset_scd (ctrl);
+
+  return valid_response? 0 : -1;
+}
+#endif /*HAVE_W32_SYSTEM*/
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index c53566b..25750f2 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -1,6 +1,7 @@
 /* gpg-agent.c  -  The GnuPG Agent
  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009,
  *               2010 Free Software Foundation, Inc.
+ * Copyright (C) 2013 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -30,7 +31,16 @@
 #include <time.h>
 #include <fcntl.h>
 #include <sys/stat.h>
-#ifndef HAVE_W32_SYSTEM
+#ifdef HAVE_W32_SYSTEM
+# ifndef WINVER
+#  define WINVER 0x0500  /* Same as in common/sysutils.c */
+# endif
+# ifdef HAVE_WINSOCK2_H
+#  include <winsock2.h>
+# endif
+# include <aclapi.h>
+# include <sddl.h>
+#else /*!HAVE_W32_SYSTEM*/
 # include <sys/socket.h>
 # include <sys/un.h>
 #endif /*!HAVE_W32_SYSTEM*/
@@ -111,6 +121,7 @@ enum cmd_and_opt_values
   oKeepTTY,
   oKeepDISPLAY,
   oSSHSupport,
+  oPuttySupport,
   oDisableScdaemon,
   oDisableCheckOwnSocket,
   oWriteEnvFile
@@ -186,7 +197,14 @@ static ARGPARSE_OPTS opts[] = {
                              N_("allow presetting passphrase")},
   { oAllowLoopbackPinentry, "allow-loopback-pinentry", 0,
                              N_("allow presetting passphrase")},
-  { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") },
+  { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh support") },
+  { oPuttySupport, "enable-putty-support", 0,
+#ifdef HAVE_W32_SYSTEM
+      N_("enable putty support")
+#else
+      "@"
+#endif
+  },
   { oWriteEnvFile, "write-env-file", 2|8,
             N_("|FILE|write environment settings also to FILE")},
   {0}
@@ -218,6 +236,17 @@ static ARGPARSE_OPTS opts[] = {
 #endif
 
 
+#ifdef HAVE_W32_SYSTEM
+/* Flag indicating that support for Putty has been enabled.  */
+static int putty_support;
+/* A magic value used with WM_COPYDATA.  */
+#define PUTTY_IPC_MAGIC 0x804e50ba
+/* To avoid surprises we limit the size of the mapped IPC file to this
+   value.  Putty currently (0.62) uses 8k, thus 16k should be enough
+   for the foreseeable future.  */
+#define PUTTY_IPC_MAXLEN 16384
+#endif /*HAVE_W32_SYSTEM*/
+
 /* The list of open file descriptors at startup.  Note that this list
    has been allocated using the standard malloc.  */
 static int *startup_fd_list;
@@ -815,6 +844,13 @@ main (int argc, char **argv )
         case oKeepDISPLAY: opt.keep_display = 1; break;
 
 	case oSSHSupport:  opt.ssh_support = 1; break;
+        case oPuttySupport:
+#        ifdef HAVE_W32_SYSTEM
+          putty_support = 1;
+          opt.ssh_support = 1;
+#        endif
+          break;
+
         case oWriteEnvFile:
           if (pargs.r_type)
             env_file_name = pargs.r.ret_str;
@@ -976,6 +1012,11 @@ main (int argc, char **argv )
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
       es_printf ("disable-scdaemon:%lu:\n",
               GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME);
+#ifdef HAVE_W32_SYSTEM
+      es_printf ("enable-putty-support:%lu:\n", GC_OPT_FLAG_NONE);
+#else
+      es_printf ("enable-ssh-support:%lu:\n", GC_OPT_FLAG_NONE);
+#endif
 
       agent_exit (0);
     }
@@ -1311,6 +1352,8 @@ agent_exit (int rc)
 static void
 agent_init_default_ctrl (ctrl_t ctrl)
 {
+  assert (ctrl->session_env);
+
   /* Note we ignore malloc errors because we can't do much about it
      and the request will fail anyway shortly after this
      initialization. */
@@ -1328,7 +1371,6 @@ agent_init_default_ctrl (ctrl_t ctrl)
     xfree (ctrl->lc_messages);
   ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages)
                                     /**/ : NULL;
-
   ctrl->cache_ttl_opt_preset = CACHE_TTL_OPT_PRESET;
 }
 
@@ -1820,6 +1862,196 @@ check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce)
 }
 
 
+#ifdef HAVE_W32_SYSTEM
+/* The window message processing function for Putty.  Warning: This
+   code runs as a native Windows thread.  Use of our own functions
+   needs to be bracket with pth_leave/pth_enter. */
+static LRESULT CALLBACK
+putty_message_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+  int ret = 0;
+  int w32rc;
+  COPYDATASTRUCT *cds;
+  const char *mapfile;
+  HANDLE maphd;
+  PSID mysid = NULL;
+  PSID mapsid = NULL;
+  void *data = NULL;
+  PSECURITY_DESCRIPTOR psd = NULL;
+  ctrl_t ctrl = NULL;
+
+  if (msg != WM_COPYDATA)
+    {
+      return DefWindowProc (hwnd, msg, wparam, lparam);
+    }
+
+  cds = (COPYDATASTRUCT*)lparam;
+  if (cds->dwData != PUTTY_IPC_MAGIC)
+    return 0;  /* Ignore data with the wrong magic.  */
+  mapfile = cds->lpData;
+  if (!cds->cbData || mapfile[cds->cbData - 1])
+    return 0;  /* Ignore empty and non-properly terminated strings.  */
+
+  if (DBG_ASSUAN)
+    {
+      npth_protect ();
+      log_debug ("ssh map file '%s'", mapfile);
+      npth_unprotect ();
+    }
+
+  maphd = OpenFileMapping (FILE_MAP_ALL_ACCESS, FALSE, mapfile);
+  if (DBG_ASSUAN)
+    {
+      npth_protect ();
+      log_debug ("ssh map handle %p\n", maphd);
+      npth_unprotect ();
+    }
+
+  if (!maphd || maphd == INVALID_HANDLE_VALUE)
+    return 0;
+
+  npth_protect ();
+
+  mysid = w32_get_user_sid ();
+  if (!mysid)
+    {
+      log_error ("error getting my sid\n");
+      goto leave;
+    }
+
+  w32rc = GetSecurityInfo (maphd, SE_KERNEL_OBJECT,
+                           OWNER_SECURITY_INFORMATION,
+                           &mapsid, NULL, NULL, NULL,
+                           &psd);
+  if (w32rc)
+    {
+      log_error ("error getting sid of ssh map file: rc=%d", w32rc);
+      goto leave;
+    }
+
+  if (DBG_ASSUAN)
+    {
+      char *sidstr;
+
+      if (!ConvertSidToStringSid (mysid, &sidstr))
+        sidstr = NULL;
+      log_debug ("          my sid: '%s'", sidstr? sidstr: "[error]");
+      LocalFree (sidstr);
+      if (!ConvertSidToStringSid (mapsid, &sidstr))
+        sidstr = NULL;
+      log_debug ("ssh map file sid: '%s'", sidstr? sidstr: "[error]");
+      LocalFree (sidstr);
+    }
+
+  if (!EqualSid (mysid, mapsid))
+    {
+      log_error ("ssh map file has a non-matching sid\n");
+      goto leave;
+    }
+
+  data = MapViewOfFile (maphd, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+  if (DBG_ASSUAN)
+    log_debug ("ssh IPC buffer at %p\n", data);
+  if (!data)
+    goto leave;
+
+  /* log_printhex ("request:", data, 20); */
+
+  ctrl = xtrycalloc (1, sizeof *ctrl);
+  if (!ctrl)
+    {
+      log_error ("error allocating connection control data: %s\n",
+                 strerror (errno) );
+      goto leave;
+    }
+  ctrl->session_env = session_env_new ();
+  if (!ctrl->session_env)
+    {
+      log_error ("error allocating session environment block: %s\n",
+                 strerror (errno) );
+      goto leave;
+    }
+
+  agent_init_default_ctrl (ctrl);
+  if (!serve_mmapped_ssh_request (ctrl, data, PUTTY_IPC_MAXLEN))
+    ret = 1; /* Valid ssh message has been constructed.  */
+  agent_deinit_default_ctrl (ctrl);
+  /* log_printhex ("  reply:", data, 20); */
+
+ leave:
+  xfree (ctrl);
+  if (data)
+    UnmapViewOfFile (data);
+  xfree (mapsid);
+  if (psd)
+    LocalFree (psd);
+  xfree (mysid);
+  CloseHandle (maphd);
+
+  npth_unprotect ();
+
+  return ret;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+#ifdef HAVE_W32_SYSTEM
+/* The thread handling Putty's IPC requests.  */
+static void *
+putty_message_thread (void *arg)
+{
+  WNDCLASS wndwclass = {0, putty_message_proc, 0, 0,
+                        NULL, NULL, NULL, NULL, NULL, "Pageant"};
+  HWND hwnd;
+  MSG msg;
+
+  (void)arg;
+
+  if (opt.verbose)
+    log_info ("putty message loop thread started\n");
+
+  /* The message loop runs as thread independent from our nPth system.
+     This also means that we need to make sure that we switch back to
+     our system before calling any no-windows function.  */
+  npth_unprotect ();
+
+  /* First create a window to make sure that a message queue exists
+     for this thread.  */
+  if (!RegisterClass (&wndwclass))
+    {
+      npth_protect ();
+      log_error ("error registering Pageant window class");
+      return NULL;
+    }
+  hwnd = CreateWindowEx (0, "Pageant", "Pageant", 0,
+                         0, 0, 0, 0,
+                         HWND_MESSAGE,  /* hWndParent */
+                         NULL,          /* hWndMenu   */
+                         NULL,          /* hInstance  */
+                         NULL);         /* lpParm     */
+  if (!hwnd)
+    {
+      npth_protect ();
+      log_error ("error creating Pageant window");
+      return NULL;
+    }
+
+  while (GetMessage(&msg, NULL, 0, 0))
+    {
+      TranslateMessage(&msg);
+      DispatchMessage(&msg);
+    }
+
+  /* Back to nPth.  */
+  npth_protect ();
+
+  if (opt.verbose)
+    log_info ("putty message loop thread stopped\n");
+  return NULL;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
 /* This is the standard connection thread's main function.  */
 static void *
 start_connection_thread (void *arg)
@@ -1920,6 +2152,22 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
 # endif
 #endif
 
+  /* On Windows we need to fire up a separate thread to listen for
+     requests from Putty (an SSH client), so we can replace Putty's
+     Pageant (its ssh-agent implementation). */
+#ifdef HAVE_W32_SYSTEM
+  if (putty_support)
+    {
+      npth_t thread;
+
+      ret = npth_create (&thread, &tattr, putty_message_thread, NULL);
+      if (ret)
+        {
+          log_error ("error spawning putty message loop: %s\n", strerror (ret));
+        }
+    }
+#endif /*HAVE_W32_SYSTEM*/
+
   /* Set a flag to tell call-scd.c that it may enable event
      notifications.  */
   opt.sigusr2_enabled = 1;
diff --git a/common/sysutils.c b/common/sysutils.c
index f57dcc1..a00cd94 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -1,6 +1,7 @@
 /* sysutils.c -  system helpers
  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004,
  *               2007, 2008  Free Software Foundation, Inc.
+ * Copyright (C) 2013 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -688,3 +689,59 @@ _gnupg_getenv (const char *name)
 }
 
 #endif /*HAVE_W32CE_SYSTEM*/
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Return the user's security identifier from the current process.  */
+PSID
+w32_get_user_sid (void)
+{
+  int okay = 0;
+  HANDLE proc = NULL;
+  HANDLE token = NULL;
+  TOKEN_USER *user = NULL;
+  PSID sid = NULL;
+  DWORD tokenlen, sidlen;
+
+  proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
+  if (!proc)
+    goto leave;
+
+  if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
+    goto leave;
+
+  if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
+      && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    goto leave;
+
+  user = xtrymalloc (tokenlen);
+  if (!user)
+    goto leave;
+
+  if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
+    goto leave;
+  if (!IsValidSid (user->User.Sid))
+    goto leave;
+  sidlen = GetLengthSid (user->User.Sid);
+  sid = xtrymalloc (sidlen);
+  if (!sid)
+    goto leave;
+  if (!CopySid (sidlen, sid, user->User.Sid))
+    goto leave;
+  okay = 1;
+
+ leave:
+  xfree (user);
+  if (token)
+    CloseHandle (token);
+  if (proc)
+    CloseHandle (proc);
+
+  if (!okay)
+    {
+      xfree (sid);
+      sid = NULL;
+    }
+  return sid;
+}
+#endif /*HAVE_W32_SYSTEM*/
diff --git a/common/sysutils.h b/common/sysutils.h
index 5faa7b3..da2c250 100644
--- a/common/sysutils.h
+++ b/common/sysutils.h
@@ -65,6 +65,7 @@ int  gnupg_setenv (const char *name, const char *value, int overwrite);
 int  gnupg_unsetenv (const char *name);
 
 #ifdef HAVE_W32_SYSTEM
+void *w32_get_user_sid (void);
 
 #include "../common/w32help.h"
 
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index dda4c9a..e97c7bd 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -492,7 +492,7 @@ static gc_option_t gc_options_gpg_agent[] =
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
    { "Configuration",
-     GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
+     GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the configuration") },
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", "|FILE|read options from FILE",
@@ -500,6 +500,12 @@ static gc_option_t gc_options_gpg_agent[] =
    { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", "do not use the SCdaemon",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
+   { "enable-ssh-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
+     "gnupg", "enable ssh support",
+     GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
+   { "enable-putty-support", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
+     "gnupg", "enable putty support",
+     GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,

commit 179012ddd48e63ca83e8f5c24537a2db45c3e122
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Jul 3 13:10:29 2013 +0200

    agent: Fix binary vs. text mode problem in ssh.
    
    * agent/command-ssh.c (file_to_buffer)
    (ssh_handler_request_identities): Open streams in binary mode.
    (start_command_handler_ssh): Factor some code out to ..
    (setup_ssh_env): new function.
    --
    
    This is for now a theoretical fix because there is no ssh client yet
    which uses the GnuPG style IPC.  OpenSSL for Cygwin uses only a quite
    similar one.  gniibe suggested to implement that IPC style in
    Libassuan so that a Cygwin version of OpenSSL may be used with GnuPG.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit ed056d67c7c93306b68829f83a2565e978dcfd9b)
    
    Also fixed one typo.

diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 8f8e285..46aa94c 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -684,7 +684,7 @@ file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n)
   buffer_new = NULL;
   err = 0;
 
-  stream = es_fopen (filename, "r");
+  stream = es_fopen (filename, "rb");
   if (! stream)
     {
       err = gpg_error_from_syserror ();
@@ -2281,7 +2281,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
   key_counter = 0;
   err = 0;
 
-  key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
+  key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+b");
   if (! key_blobs)
     {
       err = gpg_error_from_syserror ();
@@ -3356,44 +3356,51 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
   return !!err;
 }
 
-/* Start serving client on SOCK_CLIENT.  */
-void
-start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
+
+/* Because the ssh protocol does not send us information about the
+   current TTY setting, we use this function to use those from startup
+   or those explictly set.  */
+static gpg_error_t
+setup_ssh_env (ctrl_t ctrl)
 {
-  estream_t stream_sock = NULL;
+  static const char *names[] =
+    {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL};
   gpg_error_t err = 0;
-  int ret;
+  int idx;
+  const char *value;
 
-  /* Because the ssh protocol does not send us information about the
-     the current TTY setting, we resort here to use those from startup
-     or those explictly set.  */
-  {
-    static const char *names[] =
-      {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL};
-    int idx;
-    const char *value;
+  for (idx=0; !err && names[idx]; idx++)
+    if (!session_env_getenv (ctrl->session_env, names[idx])
+        && (value = session_env_getenv (opt.startup_env, names[idx])))
+      err = session_env_setenv (ctrl->session_env, names[idx], value);
 
-    for (idx=0; !err && names[idx]; idx++)
-      if (!session_env_getenv (ctrl->session_env, names[idx])
-          && (value = session_env_getenv (opt.startup_env, names[idx])))
-        err = session_env_setenv (ctrl->session_env, names[idx], value);
+  if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype)
+    if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype)))
+      err = gpg_error_from_syserror ();
 
-    if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype)
-      if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype)))
-        err = gpg_error_from_syserror ();
+  if (!err && !ctrl->lc_messages && opt.startup_lc_messages)
+    if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages)))
+      err = gpg_error_from_syserror ();
 
-    if (!err && !ctrl->lc_messages && opt.startup_lc_messages)
-      if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages)))
-        err = gpg_error_from_syserror ();
+  if (err)
+    log_error ("error setting default session environment: %s\n",
+               gpg_strerror (err));
 
-    if (err)
-      {
-        log_error ("error setting default session environment: %s\n",
-                   gpg_strerror (err));
-        goto out;
-      }
-  }
+  return err;
+}
+
+
+/* Start serving client on SOCK_CLIENT.  */
+void
+start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
+{
+  estream_t stream_sock = NULL;
+  gpg_error_t err;
+  int ret;
 
+  err = setup_ssh_env (ctrl);
+  if (err)
+    goto out;
 
   /* Create stream from socket.  */
   stream_sock = es_fdopen (FD2INT(sock_client), "r+");

commit 4ad123d6fe341da7768e43360375e17fa89e8e0d
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Apr 25 12:00:16 2013 +0100

    Fix syntax error for building on APPLE.
    
    * scd/pcsc-wrapper.c [__APPLE__]: Fix syntax error.
    --
    
    For W32 and probably for Cygwin we don't need the wrapper, thus the
    problems does not exhibit itself.
    
    (cherry picked from commit 8ddf604659b93754ffa6dea295678a8adc293f90)

diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c
index f39a5dd..e20e111 100644
--- a/scd/pcsc-wrapper.c
+++ b/scd/pcsc-wrapper.c
@@ -66,7 +66,7 @@
 static int verbose;
 
 #if defined(__APPLE__) || defined(_WIN32) || defined(__CYGWIN__)
-typedef unsinged int pcsc_dword_t;
+typedef unsigned int pcsc_dword_t;
 #else
 typedef unsigned long pcsc_dword_t;
 #endif

commit d2a6be24af0bf220bb448fdd50c0196faddee0f4
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Apr 18 14:40:43 2013 +0200

    Ignore obsolete option --disable-keypad.
    
    * scd/scdaemon.c (opts): Ignore --disable-keypad.
    --
    
    The renaming of --disable-keypad to --disable-pinpad might mess up
    configuration files managed with a GUI.  The GUI does not not anymore
    know about the old option and would allow the user to switch
    "disable-pinpad" on.  However, a "disable-keypad" might still linger
    in the conf file with gpgconf not knowing about it.  Thus the conf
    file would always be rejected and manual intervention would be
    required.  Ignoring the old option nicely solves the problem.
    
    (cherry picked from commit e24e92d7e244edd578c0c1f0fba6e0070cb5f104)

diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index daa4eea..982c52f 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -144,8 +144,11 @@ static ARGPARSE_OPTS opts[] = {
                 /* end --disable-ccid */),
   ARGPARSE_s_u (oCardTimeout, "card-timeout",
                 N_("|N|disconnect the card after N seconds of inactivity")),
+
   ARGPARSE_s_n (oDisablePinpad, "disable-pinpad",
                 N_("do not use a reader's pinpad")),
+  ARGPARSE_ignore (300, "disable-keypad"),
+
   ARGPARSE_s_n (oAllowAdmin, "allow-admin", "@"),
   ARGPARSE_s_n (oDenyAdmin, "deny-admin",
                 N_("deny the use of admin card commands")),

commit 8fc9de8d6bf663f7c8419b42dab01f590a694d59
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Apr 18 14:40:43 2013 +0200

    Allow marking options as ignored.
    
    * jnlib/argparse.h (ARGPARSE_OPT_IGNORE): New.
    (ARGPARSE_TYPE_MASK): New, for internal use.
    (ARGPARSE_ignore): New.
    * jnlib/argparse.c (optfile_parse, arg_parse): Replace remaining
    constants by macros.
    (optfile_parse): Implement ARGPARSE_OPT_IGNORE.
    (arg_parse): Exclide ignore options from --dump-options.
    --
    
    In addition to the ignore-invalid-option (commit 41d56433) it is often
    useful to mark options in a configuration which as NOP.  For example
    options which have no more function at all but can be expected to be
    found in existing conf files.  Such an option (or command) may now be
    given as
    
      ARGPARSE_ignore (300, "obsolete-option")
    
    The 300 is merely used as a non-valid single option name much like
    group names or the 500+n values used for long options.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (cherry picked from commit 54c54e2824aab5716a187bbbf6dff8860d6a6056)
    
    Resolved conflicts:
    	common/argparse.c: Fixed.

diff --git a/common/argparse.c b/common/argparse.c
index fb3dbb6..6d18bd4 100644
--- a/common/argparse.c
+++ b/common/argparse.c
@@ -1,6 +1,7 @@
 /* [argparse.c wk 17.06.97] Argument Parser for option handling
  * Copyright (C) 1998, 1999, 2000, 2001, 2006
  *               2007, 2008, 2012  Free Software Foundation, Inc.
+ * Copyright (C) 1997, 2013 Werner Koch
  *
  * This file is part of JNLIB, which is a subsystem of GnuPG.
  *
@@ -104,7 +105,8 @@
  *		 4 = takes ulong argument
  *     Bit 3 : argument is optional (r_type will the be set to 0)
  *     Bit 4 : allow 0x etc. prefixed values.
- *     Bit 7 : this is a command and not an option
+ *     Bit 6 : Ignore this option
+ *     Bit 7 : This is a command and not an option
  *  You stop the option processing by setting opts to NULL, the function will
  *  then return 0.
  * @Return Value
@@ -128,6 +130,7 @@
  *     { 'o', "output",    2 },
  *     { 'c', "cross-ref", 2|8 },
  *     { 'm', "my-option", 1|8 },
+ *     { 300, "ignored-long-option, ARGPARSE_OP_IGNORE},
  *     { 500, "have-no-short-option-for-this-long-option", 0 },
  *     {0} };
  *     ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
@@ -482,7 +485,12 @@ optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
                 }
               idx = i;
               arg->r_opt = opts[idx].short_opt;
-              if (!opts[idx].short_opt )
+              if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
+                {
+                  state = i = 0;
+                  continue;
+                }
+              else if (!opts[idx].short_opt )
                 {
                   if (!strcmp (keyword, "ignore-invalid-option"))
                     {
@@ -500,9 +508,9 @@ optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
                                 ? ARGPARSE_INVALID_COMMAND
                                 : ARGPARSE_INVALID_OPTION);
                 }
-              else if (!(opts[idx].flags & 7))
+              else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
                 arg->r_type = 0; /* Does not take an arg. */
-              else if ((opts[idx].flags & 8) )
+              else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) )
                 arg->r_type = 0; /* Arg is optional.  */
               else
                 arg->r_opt = ARGPARSE_MISSING_ARG;
@@ -514,9 +522,9 @@ optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
               /* No argument found.  */
               if (in_alias)
                 arg->r_opt = ARGPARSE_MISSING_ARG;
-              else if (!(opts[idx].flags & 7))
+              else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
                 arg->r_type = 0; /* Does not take an arg. */
-              else if ((opts[idx].flags & 8))
+              else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
                 arg->r_type = 0; /* No optional argument. */
               else
                 arg->r_opt = ARGPARSE_MISSING_ARG;
@@ -552,7 +560,7 @@ optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
                         }
 		    }
 		}
-              else if (!(opts[idx].flags & 7))
+              else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
                 arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
               else
                 {
@@ -614,7 +622,11 @@ optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
               break;
           idx = i;
           arg->r_opt = opts[idx].short_opt;
-          if (!opts[idx].short_opt)
+          if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
+            {
+              state = 1; /* Process like a comment.  */
+            }
+          else if (!opts[idx].short_opt)
             {
               if (!strcmp (keyword, "alias"))
                 {
@@ -849,7 +861,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
         {
           for (i=0; opts[i].short_opt; i++ )
             {
-              if ( opts[i].long_opt )
+              if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE))
                 writestrings (0, "--", opts[i].long_opt, "\n", NULL);
 	    }
           writestrings (0, "--dump-options\n--help\n--version\n--warranty\n",
@@ -868,7 +880,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
         arg->r_opt = opts[i].short_opt;
       if ( i < 0 )
         ;
-      else if ( (opts[i].flags & 0x07) )
+      else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
         {
           if ( argpos )
             {
@@ -952,7 +964,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
 	    arg->internal.inarg++; /* Point to the next arg.  */
 	    arg->r.ret_str = s;
           }
-	else if ( (opts[i].flags & 7) )
+	else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
           {
 	    if ( s[1] && !dash_kludge )
               {
@@ -1024,9 +1036,9 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
 static int
 set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
 {
-  int base = (flags & 16)? 0 : 10;
+  int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10;
 
-  switch ( (arg->r_type = (flags & 7)) )
+  switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) )
     {
     case ARGPARSE_TYPE_INT:
       arg->r.ret_int = (int)strtol(s,NULL,base);
diff --git a/common/argparse.h b/common/argparse.h
index a36218f..29c7b62 100644
--- a/common/argparse.h
+++ b/common/argparse.h
@@ -94,7 +94,10 @@ typedef struct
 #define ARGPARSE_TYPE_ULONG       4  /* Takes an unsigned long argument.  */
 #define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional.             */
 #define ARGPARSE_OPT_PREFIX   (1<<4) /* Allow 0x etc. prefixed values.    */
-#define ARGPARSE_OPT_COMMAND  (1<<8) /* The argument is a command.        */
+#define ARGPARSE_OPT_IGNORE   (1<<6) /* Ignore command or option.         */
+#define ARGPARSE_OPT_COMMAND  (1<<7) /* The argument is a command.        */
+
+#define ARGPARSE_TYPE_MASK  7  /* Mask for the type values (internal).  */
 
 /* A set of macros to make option definitions easier to read.  */
 #define ARGPARSE_x(s,l,t,f,d) \
@@ -161,6 +164,8 @@ typedef struct
 #define ARGPARSE_c(s,l,d) \
      { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) }
 
+#define ARGPARSE_ignore(s,l) \
+     { (s), (l), (ARGPARSE_OPT_IGNORE), "@" }
 
 #define ARGPARSE_group(s,d) \
      { (s), NULL, 0, (d) }

-----------------------------------------------------------------------

Summary of changes:
 NEWS                 |   13 +++
 agent/agent.h        |   11 ++-
 agent/command-ssh.c  |  216 ++++++++++++++++++++++++++++++++++------
 agent/gpg-agent.c    |  267 ++++++++++++++++++++++++++++++++++++++++++++++++--
 agent/trustlist.c    |    3 +-
 common/argparse.c    |   38 ++++---
 common/argparse.h    |    7 +-
 common/estream.c     |   10 +-
 common/sysutils.c    |   61 +++++++++++-
 common/sysutils.h    |    1 +
 common/w32-reg.c     |   98 ------------------
 g10/gpg.c            |    6 +-
 g10/gpgv.c           |   10 +-
 g10/import.c         |    6 ++
 g10/keyedit.c        |    5 +-
 g10/keyserver.c      |   12 ++-
 g10/options.h        |    1 +
 g10/options.skel     |    7 --
 g10/tdbio.c          |    8 +-
 g10/tdbio.h          |    2 +-
 g10/trustdb.c        |   68 ++++++++++---
 m4/libcurl.m4        |    6 +-
 scd/pcsc-wrapper.c   |    2 +-
 scd/scdaemon.c       |    3 +
 tools/gpgconf-comp.c |   12 ++-
 25 files changed, 672 insertions(+), 201 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list