You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2012/08/02 21:26:22 UTC
svn commit: r1368658 - in /subversion/branches/master-passphrase/subversion:
include/svn_auth.h libsvn_subr/cmdline.c libsvn_subr/gpg_agent.c
Author: cmpilato
Date: Thu Aug 2 19:26:22 2012
New Revision: 1368658
URL: http://svn.apache.org/viewvc?rev=1368658&view=rev
Log:
On the 'master-passphrase' branch: introduce GPG-Agent caching of the
master passphrase.
* subversion/include/svn_auth.h
(svn_auth_get_gpg_agent_master_passphrase_provider): New function.
* subversion/libsvn_subr/cmdline.c
(open_auth_store): Register the gpg-agent master passphrase provider
where available.
* subversion/libsvn_subr/gpg_agent.c
(get_password_via_agent): New function, abstracted from of
password_get_gpg_agent().
(password_get_gpg_agent): Now just a wrapper around
get_password_via_agent().
(master_passphrase_gpg_agent_first_creds,
gpg_agent_master_passphrase_provider,
svn_auth_get_gpg_agent_master_passphrase_provider): New stuff.
Modified:
subversion/branches/master-passphrase/subversion/include/svn_auth.h
subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c
subversion/branches/master-passphrase/subversion/libsvn_subr/gpg_agent.c
Modified: subversion/branches/master-passphrase/subversion/include/svn_auth.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/svn_auth.h?rev=1368658&r1=1368657&r2=1368658&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_auth.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_auth.h Thu Aug 2 19:26:22 2012
@@ -1328,6 +1328,22 @@ void svn_auth_get_master_passphrase_prom
int retry_limit,
apr_pool_t *pool);
+
+#if !defined(WIN32) || defined(DOXYGEN)
+/** Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_master_passphrase_t, allocated in @a pool.
+ *
+ * @a *provider retrieves its credentials via GPG-Agent. The returned
+ * credentials are used to unlock Subversion's encrypted
+ * authentication credential store.
+ *
+ * @since New in 1.8.
+ */
+void
+svn_auth_get_gpg_agent_master_passphrase_provider(
+ svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+#endif /* !defined(WIN32) || defined(DOXYGEN) */
#ifdef __cplusplus
}
Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c?rev=1368658&r1=1368657&r2=1368658&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c Thu Aug 2 19:26:22 2012
@@ -477,6 +477,12 @@ open_auth_store(svn_auth__store_t **auth
sizeof(svn_auth_provider_object_t *));
if (! non_interactive)
{
+#if !defined(WIN32) || defined(DOXYGEN)
+ /* ### FIXME!! This should be done by code that inspects
+ and honors the 'password-stores' configuration setting! */
+ svn_auth_get_gpg_agent_master_passphrase_provider(&provider, pool);
+ APR_ARRAY_PUSH(mp_providers, svn_auth_provider_object_t *) = provider;
+#endif /* !defined(WIN32) || defined(DOXYGEN) */
svn_auth_get_master_passphrase_prompt_provider(
&provider, svn_cmdline_auth_master_passphrase_prompt,
pb, 3, pool);
Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/gpg_agent.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/gpg_agent.c?rev=1368658&r1=1368657&r2=1368658&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/gpg_agent.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/gpg_agent.c Thu Aug 2 19:26:22 2012
@@ -155,12 +155,11 @@ send_option(int sd, char *buf, size_t n,
/* Implementation of svn_auth__password_get_t that retrieves the password
from gpg-agent */
static svn_error_t *
-password_get_gpg_agent(svn_boolean_t *done,
+get_password_via_agent(svn_boolean_t *done,
const char **password,
- apr_hash_t *creds,
const char *realmstring,
- const char *username,
- apr_hash_t *parameters,
+ const char *escaped_password_prompt,
+ const char *escaped_realm_prompt,
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
@@ -180,8 +179,6 @@ password_get_gpg_agent(svn_boolean_t *do
const char *display;
const char *socket_name = NULL;
svn_checksum_t *digest = NULL;
- char *password_prompt;
- char *realm_prompt;
*done = FALSE;
@@ -336,16 +333,12 @@ password_get_gpg_agent(svn_boolean_t *do
pool);
cache_id = svn_checksum_to_cstring(digest, pool);
- password_prompt = apr_psprintf(pool, _("Password for '%s': "), username);
- realm_prompt = apr_psprintf(pool, _("Enter your Subversion password for %s"),
- realmstring);
- request = apr_psprintf(pool,
- "GET_PASSPHRASE --data %s--repeat=1 "
- "%s X %s %s\n",
+ request = apr_psprintf(pool,
+ "GET_PASSPHRASE --data %s--repeat=1 %s X %s %s\n",
non_interactive ? "--no-ask " : "",
cache_id,
- escape_blanks(password_prompt),
- escape_blanks(realm_prompt));
+ escaped_password_prompt,
+ escaped_realm_prompt);
if (write(sd, request, strlen(request)) == -1)
{
@@ -381,6 +374,30 @@ password_get_gpg_agent(svn_boolean_t *do
}
+/* Implementation of svn_auth__password_get_t that retrieves the password
+ from gpg-agent */
+static svn_error_t *
+password_get_gpg_agent(svn_boolean_t *done,
+ 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)
+{
+ char *escaped_password_prompt =
+ escape_blanks(apr_psprintf(pool, _("Password for '%s': "), username));
+ char *escaped_realm_prompt =
+ escape_blanks(apr_psprintf(pool, _("Enter your Subversion password for %s"),
+ realmstring));
+
+ SVN_ERR(get_password_via_agent(done, password, realmstring,
+ escaped_password_prompt, escaped_realm_prompt,
+ non_interactive, pool));
+ return SVN_NO_ERROR;
+}
+
/* Implementation of svn_auth__password_set_t that would store the
password in GPG Agent if that's how this particular integration
worked. But it isn't. GPG Agent stores the password provided by
@@ -456,5 +473,71 @@ svn_auth_get_gpg_agent_simple_provider(s
*provider = po;
}
+
+
+/*** Master Passphrase Provider ***/
+
+/* An implementation of svn_auth_provider_t::first_credentials() */
+static svn_error_t *
+master_passphrase_gpg_agent_first_creds(void **credentials,
+ void **iter_baton,
+ void *provider_baton,
+ apr_hash_t *parameters,
+ const char *realmstring,
+ apr_pool_t *pool)
+{
+ char *escaped_password_prompt = _("Subversion+master+password");
+ char *escaped_realm_prompt = _("Enter+your+Subversion+master+password");
+ svn_boolean_t non_interactive = apr_hash_get(parameters,
+ SVN_AUTH_PARAM_NON_INTERACTIVE,
+ APR_HASH_KEY_STRING) != NULL;
+ svn_boolean_t done;
+ const char *passphrase;
+
+ *credentials = NULL;
+
+ SVN_ERR(get_password_via_agent(&done, &passphrase, realmstring,
+ escaped_password_prompt, escaped_realm_prompt,
+ non_interactive, pool));
+ if (done && passphrase)
+ {
+ svn_auth_cred_master_passphrase_t *creds;
+ svn_checksum_t *checksum;
+ int passphrase_len = strlen(passphrase);
+
+ SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1,
+ passphrase, passphrase_len, pool));
+ memset((void *)passphrase, 0, passphrase_len);
+ creds = apr_pcalloc(pool, sizeof(*creds));
+ creds->passphrase = svn_string_ncreate((const char *)checksum->digest,
+ svn_checksum_size(checksum),
+ pool);
+ *credentials = creds;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+static const svn_auth_provider_t gpg_agent_master_passphrase_provider = {
+ SVN_AUTH_CRED_MASTER_PASSPHRASE,
+ master_passphrase_gpg_agent_first_creds,
+ NULL,
+ NULL,
+};
+
+
+/* Public API */
+void
+svn_auth_get_gpg_agent_master_passphrase_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_master_passphrase_provider;
+ *provider = po;
+}
+
#endif /* SVN_HAVE_GPG_AGENT */
#endif /* !WIN32 */