[PATCH] gpg-agent support
Dan Engel <[email protected]>
| Newsgroups | gmane.comp.version-control.subversion.devel,gmane.comp.version-control.subversion.rapidsvn.devel |
|---|---|
| Message-ID | <[email protected]> |
All, I hope you will forgive any breach in protocol or etiquette in this submission. This is my first post. I tried to read and follow the guidelines, but there really are a lot of them! This code is a first cut (well, an in-use first cut). I developed it specifically for use at work, but once it was up and running I decided to follow through and turn it into a patch submission. There are definitely more efficient ways to do some of what's in here, and I'll eventually get around to figuring them out if someone else doesn't do so first; in the meantime, there may be others who would benefit from this functionality. I also didn't like having to modify the simple_provider_helper function with special handling for the GPG_AGENT password type, but it seemed like there was some special GNOME_KEYRING code in that same file (in the save_creds helper function). If that was the wrong way to go about this, then I'd welcome some better instruction. I'm not sure whether the save function is even necessary (password_set). It just returns true. It seems that at one point while I was trying to get things to work correctly, I concluded that it was necessary to take that step. I hope this log is detailed/inclusive enough. [[[ Add GPG-AGENT support for Subversion password handling. * Makefile.in Include support for building libsvn_auth_gpg_agent. * build.conf Include support for building libsvn_auth_gpg_agent. * configure.ac Include support for configuring a build to include gpg-agent support. * subversion/include/private/svn_auth_private.h Add password type #define for gpg-agent type. * subversion/include/svn_auth.h Add declarations of functions provided by libsvn_auth_gpg_agent library. * subversion/libsvn_auth_gpg_agent/gpg_agent.c Password handling functions for gpg-agent password store. * subversion/libsvn_auth_gpg_agent/version.c Provide version information for libsvn_auth_gpg_agent. * subversion/libsvn_subr/auth.c Add gpg-agent to the list of password store types supported. * subversion/libsvn_subr/simple_providers.c Add some special handling for gpg-agent type password. ]]] Thanks! -Dan Engel ------------------------------------------------------ http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2424464 Please start new threads on the <[email protected]> mailing list. To subscribe to the new list, send an empty e-mail to <[email protected]>.
subversion-gpg-agent.patch
(text/x-patch, 20.3 KB)
diff -ur --unidirectional-new-file ./Makefile.in ../subversion-gpg-agent/Makefile.in
--- ./Makefile.in 2009-11-25 18:50:03.000000000 -0500
+++ ../subversion-gpg-agent/Makefile.in 2009-11-25 18:09:19.000000000 -0500
@@ -47,6 +47,7 @@
SVN_APRUTIL_LIBS = @SVN_APRUTIL_LIBS@
SVN_APR_MEMCACHE_LIBS = @SVN_APR_MEMCACHE_LIBS@
SVN_DB_LIBS = @SVN_DB_LIBS@
+SVN_GPG_AGENT_LIBS = @SVN_GPG_AGENT_LIBS@
SVN_GNOME_KEYRING_LIBS = @SVN_GNOME_KEYRING_LIBS@
SVN_GSSAPI_LIBS = @SVN_GSSAPI_LIBS@
SVN_KWALLET_LIBS = @SVN_KWALLET_LIBS@
@@ -65,6 +66,7 @@
ramod_libdir = @libdir@
bdb_libdir = @libdir@
gnome_keyring_libdir = @libdir@
+gpg_agent_libdir = @libdir@
gssapi_libdir = @libdir@
kwallet_libdir = @libdir@
neon_libdir = @libdir@
@@ -237,6 +239,7 @@
INSTALL_RAMOD_LIB = $(INSTALL_LIB)
INSTALL_APR_MEMCACHE_LIB = $(INSTALL_LIB)
INSTALL_BDB_LIB = $(INSTALL_LIB)
+INSTALL_GPG_AGENT_LIB = $(INSTALL_LIB)
INSTALL_GNOME_KEYRING_LIB = $(INSTALL_LIB)
INSTALL_GSSAPI_LIB = $(INSTALL_LIB)
INSTALL_KWALLET_LIB = $(INSTALL_LIB)
diff -ur --unidirectional-new-file ./build.conf ../subversion-gpg-agent/build.conf
--- ./build.conf 2009-11-25 18:50:03.000000000 -0500
+++ ../subversion-gpg-agent/build.conf 2009-11-25 17:40:55.000000000 -0500
@@ -179,6 +179,14 @@
install = bin
manpages = subversion/svnversion/svnversion.1
+# Support for GPG Agent
+[libsvn_auth_gpg_agent]]
+description = Subversion GPG Agent library
+type = lib
+install = gpg-agent-lib
+path = subversion/libsvn_auth_gpg_agent
+libs = apr libsvn_subr
+
# Support for GNOME Keyring
[libsvn_auth_gnome_keyring]
description = Subversion GNOME Keyring Library
diff -ur --unidirectional-new-file ./configure.ac ../subversion-gpg-agent/configure.ac
--- ./configure.ac 2009-11-25 18:50:03.000000000 -0500
+++ ../subversion-gpg-agent/configure.ac 2009-11-25 18:13:14.000000000 -0500
@@ -516,6 +516,37 @@
fi
fi
+dnl GPG Agent -------------------
+
+AC_ARG_WITH(gpg_agent,
+ AS_HELP_STRING([--with-gpg-agent],
+ [Enable use of GPG AGENT for auth credentials]),
+ [with_gpg_agent="$withval"],
+ [with_gpg_agent=no])
+
+AC_MSG_CHECKING([whether to look for GPG AGENT])
+if test "$with_gpg_agent" != "no"; then
+ AC_MSG_RESULT([yes])
+ if test "$enable_shared" = "yes"; then
+ if test "$APR_HAS_DSO" = "yes"; then
+ if test "$with_gpg_agent" = "yes"; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([SVN_HAVE_GPG_AGENT], [1],
+ [Is GPG Agent support enabled?])
+ SVN_GPG_AGENT_LIBS="-lapr-1 -laprutil-1"
+ fi
+ else
+ AC_MSG_ERROR([APR does not have support for DSOs])
+ fi
+ else
+ AC_MSG_ERROR([--with-gpg-agent conflicts with --disable-shared])
+ fi
+else
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(SVN_GPG_AGENT_LIBS)
+
dnl GNOME Keyring -------------------
AC_ARG_WITH(gnome_keyring,
@@ -712,6 +743,12 @@
INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-gnome-keyring-lib"
fi
+if test "$with_gpg_agent" = "yes"; then
+ BUILD_RULES="$BUILD_RULES gpg-agent-lib"
+ INSTALL_RULES="`echo $INSTALL_RULES | sed 's/install-lib/install-lib install-gpg-agent-lib/'`"
+ INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-gpg-agent-lib"
+fi
+
if test "$USE_NLS" = "yes"; then
BUILD_RULES="$BUILD_RULES locale"
INSTALL_RULES="$INSTALL_RULES install-locale"
diff -ur --unidirectional-new-file ./subversion/include/private/svn_auth_private.h ../subversion-gpg-agent/subversion/include/private/svn_auth_private.h
--- ./subversion/include/private/svn_auth_private.h 2009-11-25 18:49:53.000000000 -0500
+++ ../subversion-gpg-agent/subversion/include/private/svn_auth_private.h 2009-11-25 18:36:33.000000000 -0500
@@ -46,6 +46,7 @@
#define SVN_AUTH__KEYCHAIN_PASSWORD_TYPE "keychain"
#define SVN_AUTH__KWALLET_PASSWORD_TYPE "kwallet"
#define SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE "gnome-keyring"
+#define SVN_AUTH__GPG_AGENT_PASSWORD_TYPE "gpg-agent"
/* A function that stores in *PASSWORD (potentially after decrypting it)
the user's password. It might be obtained directly from CREDS, or
diff -ur --unidirectional-new-file ./subversion/include/svn_auth.h ../subversion-gpg-agent/subversion/include/svn_auth.h
--- ./subversion/include/svn_auth.h 2009-11-25 18:49:53.000000000 -0500
+++ ../subversion-gpg-agent/subversion/include/svn_auth.h 2009-11-25 18:26:47.000000000 -0500
@@ -914,6 +914,36 @@
svn_auth_get_keychain_simple_provider(svn_auth_provider_object_t **provider,
apr_pool_t *pool);
+
+/**
+ * Get libsvn_auth_gpg_agent version information.
+ *
+ */
+const svn_version_t *
+svn_auth_gpg_agent_version(void);
+
+
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory.
+ *
+ * This is like svn_client_get_simple_provider(), except that the
+ * password is obtained from gpg_agent, which will keep it in
+ * a memory cache.
+ *
+ * Allocate @a *provider in @a pool.
+ *
+ * @since New in 1.6
+ * @note This function actually works only on systems with
+ * libsvn_auth_gpg_agent and GNU Privacy Guard installed.
+ */
+void
+svn_auth_get_gpg_agent_simple_provider
+ (svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+
+
/**
* Set @a *provider to an authentication provider of type @c
* svn_auth_cred_ssl_client_cert_pw_t that gets/sets information from the
diff -ur --unidirectional-new-file ./subversion/libsvn_auth_gpg_agent/gpg_agent.c ../subversion-gpg-agent/subversion/libsvn_auth_gpg_agent/gpg_agent.c
--- ./subversion/libsvn_auth_gpg_agent/gpg_agent.c 1969-12-31 19:00:00.000000000 -0500
+++ ../subversion-gpg-agent/subversion/libsvn_auth_gpg_agent/gpg_agent.c 2009-11-24 17:03:40.000000000 -0500
@@ -0,0 +1,388 @@
+/*
+ * gpg_agent.c: GPG Agent provider for SVN_AUTH_CRED_*
+ *
+ * ====================================================================
+ * Copyright (c) 2008-2009 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+//#include <stdio.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <apr_pools.h>
+#include "svn_auth.h"
+#include "svn_config.h"
+#include "svn_error.h"
+#include "svn_pools.h"
+#include "svn_cmdline.h"
+#include "svn_checksum.h"
+
+#include "private/svn_auth_private.h"
+
+#include "svn_private_config.h"
+
+static const int buffer_size = 1024;
+
+/* Implementation of password_get_t that retrieves the password
+ from gpg-agent */
+static svn_boolean_t
+password_get_gpg_agent(const char **password,
+ apr_hash_t *creds,
+ const char *realmstring,
+ const char *username,
+ apr_hash_t *parameters,
+ svn_boolean_t non_interactive,
+ apr_pool_t *pool)
+{
+ int s;
+ char *gpg_agent_info = NULL;
+ char *value;
+ char *p = NULL;
+ char *ep = NULL;
+ char *buffer;
+ int i;
+
+ char *realm_str = NULL;
+ char *user_str = NULL;
+
+ char *request = NULL;
+ const char *cache_id = NULL;
+ svn_checksum_t *digest;
+ int request_len = 0;
+ struct sockaddr_un addr;
+ int recvd;
+ int tot_recvd;
+ char *ttyname;
+ char *ttytype;
+
+ //fprintf( stderr, "doing gpg-agent stuff\n");
+ value = getenv( "GPG_AGENT_INFO");
+
+ if ( value != NULL)
+ {
+ gpg_agent_info = apr_pstrmemdup( pool, value, strlen( value));
+
+ p = strrchr( gpg_agent_info, ':');
+
+ if ( p != NULL)
+ {
+ *p = '\0';
+ p = strrchr( gpg_agent_info, ':');
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ if ( p == NULL)
+ {
+ return FALSE;
+ }
+
+ *p = '\0';
+
+ value = getenv( "GPG_TTY");
+ if ( value == NULL)
+ {
+ return FALSE;
+ }
+
+ ttyname = apr_pstrmemdup( pool, value, strlen( value));
+
+ value = getenv( "TERM");
+ if ( value == NULL)
+ {
+ return FALSE;
+ }
+
+ ttytype = apr_pstrmemdup( pool, value, strlen( value));
+
+ if ( ( ttyname == NULL) || ( ttytype == NULL))
+ {
+ return FALSE;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strncpy( &addr.sun_path[0], gpg_agent_info, 108);
+
+ s = socket( AF_UNIX, SOCK_STREAM, 0);
+ if ( s == -1)
+ {
+ return FALSE;
+ }
+
+ //fprintf( stderr, "opening socket\n");
+ if ( connect( s, (struct sockaddr *)&addr, sizeof( addr)) != 0)
+ {
+ close( s);
+ return FALSE;
+ }
+
+ //fprintf( stderr, "opened socket\n");
+
+ realm_str = apr_pstrmemdup( pool, realmstring, strlen( realmstring));
+ user_str = apr_pstrmemdup( pool, username, strlen( username));
+
+ cache_id = apr_pstrmemdup( pool, realm_str, strlen( realmstring));
+ cache_id = apr_pstrcat( pool, cache_id, user_str, NULL);
+
+ //fprintf( stderr, "fixing strings\n");
+
+ p = realm_str;
+ while ( *p)
+ {
+ if ( *p == ' ')
+ {
+ *p = '+';
+ }
+ p++;
+ }
+
+ //fprintf( stderr, "fixing strings\n");
+ p = user_str;
+ while ( *p)
+ {
+ if ( *p == ' ')
+ {
+ *p = '+';
+ }
+ p++;
+ }
+
+ buffer = apr_palloc( pool, buffer_size);
+
+ //fprintf( stderr, "receiving from socket\n");
+ recvd = recv( s, buffer, buffer_size-1, 0);
+ buffer[recvd] = '\0';
+ //fprintf( stderr, "received '%s'\n", &buffer[0]);
+ if ( strncmp( buffer, "OK", 2) != 0)
+ {
+ return FALSE;
+ }
+
+ request_len = snprintf( request, 0, "OPTION ttyname=%s\n", ttyname);
+ request = apr_palloc( pool, request_len + 1);
+ snprintf( request, request_len + 1, "OPTION ttyname=%s\n", ttyname);
+ request[request_len] = '\0';
+
+ //fprintf( stderr, "sending '%s', len = %d\n", request, request_len);
+ send( s, request, request_len, 0);
+
+ recvd = recv( s, buffer, buffer_size - 1, 0);
+ buffer[recvd] = '\0';
+
+ if ( strncmp( &buffer[0], "OK", 2) != 0)
+ {
+ return FALSE;
+ }
+
+ request_len = snprintf( request, 0, "OPTION ttytype=%s\n", ttytype);
+ request = apr_palloc( pool, request_len + 1);
+ snprintf( request, request_len + 1, "OPTION ttytype=%s\n", ttytype);
+ request[request_len] = '\0';
+
+ //fprintf( stderr, "sending '%s', len = %d\n", request, request_len);
+ send( s, request, request_len, 0);
+
+ recvd = recv( s, buffer, buffer_size - 1, 0);
+ buffer[recvd] = '\0';
+
+ if ( strncmp( &buffer[0], "OK", 2) != 0)
+ {
+ return FALSE;
+ }
+
+ digest = svn_checksum_create( svn_checksum_md5, pool);
+
+ svn_checksum( &digest, svn_checksum_md5, cache_id, strlen(cache_id), pool);
+ cache_id = svn_checksum_to_cstring( digest, pool);
+
+ if ( non_interactive)
+ {
+ request_len = snprintf( request, 0, "GET_PASSPHRASE --data --no-ask %s X Password: Subversion+needs+a+password+for+user+%s+to+access+repository+%s\n", cache_id, user_str, realm_str);
+ if ( request_len > 0)
+ {
+ request = (char *)apr_palloc( pool, request_len + 5);
+ }
+ request_len = snprintf( request, request_len + 5, "GET_PASSPHRASE --data --no-ask %s X Password: Subversion+needs+a+password+for+user+%s+to+access+repository+%s\n", cache_id, user_str, realm_str);
+ }
+ else
+ {
+ request_len = snprintf( request, 0, "GET_PASSPHRASE --data %s X Password: Subversion+needs+a+password+for+user+%s+to+access+repository+%s\n", cache_id, user_str, realm_str);
+ if ( request_len > 0)
+ {
+ request = (char *)apr_palloc( pool, request_len + 5);
+ }
+ request_len = snprintf( request, request_len + 5, "GET_PASSPHRASE --data %s X Password: Subversion+needs+a+password+for+user+%s+to+access+repository+%s\n", cache_id, user_str, realm_str);
+ }
+
+
+ send( s, request, request_len, 0);
+
+ recvd = recv( s, buffer, buffer_size - 1, 0);
+ buffer[recvd] = '\0';
+
+ tot_recvd = 0;
+ while ( recvd > 0)
+ {
+ // if it's the beginning of the response
+ if ( tot_recvd == 0)
+ {
+ if ( strncmp( buffer, "ERR", 3) == 0)
+ {
+ return FALSE;
+ }
+
+ if ( strncmp( buffer, "D", 1) == 0)
+ {
+ p = &buffer[2];
+ }
+ }
+ else
+ {
+ p = &buffer[0];
+ }
+
+
+ ep = strchr( p, '\n');
+ if ( ep != NULL)
+ {
+ *ep = '\0';
+ }
+
+ if ( tot_recvd == 0)
+ {
+ *password = apr_pstrmemdup( pool, p, recvd);
+ }
+ else
+ {
+ *password = apr_pstrcat( pool, *password, p, NULL);
+ }
+
+ tot_recvd += recvd;
+
+ // keep going until we find the newline
+ if ( ep == NULL)
+ {
+ recvd = recv( s, buffer, buffer_size - 1, 0);
+ buffer[recvd] = '\0';
+ }
+ else
+ {
+ recvd = 0;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Implementation of password_set_t that stores the password in
+ GPG Agent. */
+static svn_boolean_t
+password_set_gpg_agent(apr_hash_t *creds,
+ const char *realmstring,
+ const char *username,
+ const char *password,
+ apr_hash_t *parameters,
+ svn_boolean_t non_interactive,
+ apr_pool_t *pool)
+{
+ // just return true
+ return TRUE;
+}
+
+
+
+/* Get cached encrypted credentials from the simple provider's cache.
+ *
+ * Calls:
+static svn_boolean_t
+password_get_gpg_agent(const char **password,
+ apr_hash_t *creds,
+ const char *realmstring,
+ const char *username,
+ apr_hash_t *parameters,
+ svn_boolean_t non_interactive,
+ apr_pool_t *pool)
+*
+*/
+
+static svn_error_t *
+simple_gpg_agent_first_creds(void **credentials,
+ void **iter_baton,
+ void *provider_baton,
+ apr_hash_t *parameters,
+ const char *realmstring,
+ apr_pool_t *pool)
+{
+
+ return svn_auth__simple_first_creds_helper
+ (credentials,
+ iter_baton, provider_baton,
+ parameters, realmstring,
+ password_get_gpg_agent,
+ SVN_AUTH__GPG_AGENT_PASSWORD_TYPE,
+ pool);
+
+}
+
+
+/* Save encrypted credentials to the simple provider's cache. */
+static svn_error_t *
+simple_gpg_agent_save_creds(svn_boolean_t *saved,
+ void *credentials,
+ void *provider_baton,
+ apr_hash_t *parameters,
+ const char *realmstring,
+ apr_pool_t *pool)
+{
+
+ return svn_auth__simple_save_creds_helper
+ (saved, credentials,
+ provider_baton, parameters,
+ realmstring,
+ password_set_gpg_agent,
+ SVN_AUTH__GPG_AGENT_PASSWORD_TYPE,
+ pool);
+}
+
+static const svn_auth_provider_t gpg_agent_simple_provider = {
+ SVN_AUTH_CRED_SIMPLE,
+ simple_gpg_agent_first_creds,
+ NULL,
+ simple_gpg_agent_save_creds
+};
+
+/* Public API */
+void
+svn_auth_get_gpg_agent_simple_provider
+ (svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+
+
+ po->vtable = &gpg_agent_simple_provider;
+ *provider = po;
+}
+
diff -ur --unidirectional-new-file ./subversion/libsvn_auth_gpg_agent/version.c ../subversion-gpg-agent/subversion/libsvn_auth_gpg_agent/version.c
--- ./subversion/libsvn_auth_gpg_agent/version.c 1969-12-31 19:00:00.000000000 -0500
+++ ../subversion-gpg-agent/subversion/libsvn_auth_gpg_agent/version.c 2009-11-21 19:18:48.000000000 -0500
@@ -0,0 +1,30 @@
+/*
+ * version.c: libsvn_auth_gpg_agent version number
+ *
+ * ====================================================================
+ * Copyright (c) 2008 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+#include "svn_auth.h"
+#include "svn_version.h"
+
+const svn_version_t *
+svn_auth_gpg_agent_version(void)
+{
+ SVN_VERSION_BODY;
+}
diff -ur --unidirectional-new-file ./subversion/libsvn_subr/auth.c ../subversion-gpg-agent/subversion/libsvn_subr/auth.c
--- ./subversion/libsvn_subr/auth.c 2009-11-25 18:49:54.000000000 -0500
+++ ../subversion-gpg-agent/subversion/libsvn_subr/auth.c 2009-11-25 18:39:22.000000000 -0500
@@ -390,9 +390,10 @@
*provider = NULL;
if (apr_strnatcmp(provider_name, "gnome_keyring") == 0 ||
- apr_strnatcmp(provider_name, "kwallet") == 0)
+ apr_strnatcmp(provider_name, "kwallet") == 0 ||
+ apr_strnatcmp(provider_name, "gpg_agent") == 0)
{
-#if defined(SVN_HAVE_GNOME_KEYRING) || defined(SVN_HAVE_KWALLET)
+#if defined(SVN_HAVE_GNOME_KEYRING) || defined(SVN_HAVE_KWALLET) || defined(SVN_HAVE_GPG_AGENT)
apr_dso_handle_t *dso;
apr_dso_handle_sym_t provider_function_symbol, version_function_symbol;
const char *library_label, *library_name;
@@ -498,11 +499,11 @@
&password_stores_config_option,
SVN_CONFIG_SECTION_AUTH,
SVN_CONFIG_OPTION_PASSWORD_STORES,
- "gnome-keyring,kwallet,keychain,windows-cryptoapi");
+ "gnome-keyring,gpg-agent,kwallet,keychain,windows-cryptoapi");
}
else
{
- password_stores_config_option = "gnome-keyring,kwallet,keychain,windows-cryptoapi";
+ password_stores_config_option = "gnome-keyring,gpg-agent,kwallet,keychain,windows-cryptoapi";
}
*providers = apr_array_make(pool, 12, sizeof(svn_auth_provider_object_t *));
@@ -538,6 +539,20 @@
continue;
}
+ /* GPG-AGENT Keyring */
+ if (apr_strnatcmp(password_store, "gpg-agent") == 0)
+ {
+ SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
+ "gpg_agent",
+ "simple",
+ pool));
+
+ if (provider)
+ {
+ APR_ARRAY_PUSH(*providers, svn_auth_provider_object_t *) = provider;
+ }
+ }
+
/* KWallet */
if (apr_strnatcmp(password_store, "kwallet") == 0)
{
diff -ur --unidirectional-new-file ./subversion/libsvn_subr/simple_providers.c ../subversion-gpg-agent/subversion/libsvn_subr/simple_providers.c
--- ./subversion/libsvn_subr/simple_providers.c 2009-11-25 18:49:54.000000000 -0500
+++ ../subversion-gpg-agent/subversion/libsvn_subr/simple_providers.c 2009-11-25 18:35:39.000000000 -0500
@@ -269,6 +269,16 @@
NULL);
}
+ /* We have to check for whether we should be using GPG agent here */
+ if ( ( strcmp(passtype, SVN_AUTH__GPG_AGENT_PASSWORD_TYPE) == 0) && !password)
+ {
+ if (!password_get(&default_password, creds_hash, realmstring,
+ username, parameters, non_interactive, pool))
+ {
+ password = NULL;
+ }
+ }
+
/* Ask the OS for the username if we have a password but no
username. */
if (password && ! username)
@@ -357,7 +367,8 @@
(strcmp(passtype, SVN_AUTH__WINCRYPT_PASSWORD_TYPE) == 0
|| strcmp(passtype, SVN_AUTH__KEYCHAIN_PASSWORD_TYPE) == 0
|| strcmp(passtype, SVN_AUTH__KWALLET_PASSWORD_TYPE) == 0
- || strcmp(passtype, SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE) == 0) )
+ || strcmp(passtype, SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE) == 0)
+ || strcmp(passtype, SVN_AUTH__GPG_AGENT_PASSWORD_TYPE) == 0)
{
may_save_password = TRUE;
}