[prev in list] [next in list] [prev in thread] [next in thread] 

List:       subversion-dev
Subject:    Re: [PATCH] Cache ssl client cert passphrase in gnome-keyring
From:       Senthil Kumaran S <senthil () collab ! net>
Date:       2008-05-30 11:32:15
Message-ID: 483FE2EF.8040801 () collab ! net
[Download RAW message or body]

Hi Arfrever,

Arfrever Frehtes Taifersar Arahesis wrote:
>> Index: subversion/libsvn_auth_gnome_keyring/gnome_keyring.c
>> ===================================================================
>> --- subversion/libsvn_auth_gnome_keyring/gnome_keyring.c (revision 31507)
>> +++ subversion/libsvn_auth_gnome_keyring/gnome_keyring.c (working copy)
>> @@ -189,3 +189,60 @@
>>  
>>    gnome_keyring_init();
>>  }
>> +
>> +/* Get cached encrypted credentials from the ssl client cert password
>> + * provider's cache. */
>> +static svn_error_t *
>> +gnome_keyring_ssl_client_cert_pw_first_creds(void **credentials,
>> +                                             void **iter_baton,
>> +                                             void *provider_baton,
>> +                                             apr_hash_t *parameters,
>> +                                             const char *realmstring,
>> +                                             apr_pool_t *pool)
>> +{
>> +  return svn_auth__ssl_client_cert_pw_file_first_creds_helper
>> +           (credentials,
>> +            iter_baton, provider_baton,
>> +            parameters, realmstring,
>> +            gnome_keyring_password_get,
>> +            SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE,
>> +            pool);
>> +}
>> +
>> +/* Save encrypted credentials to the ssl client cert password provider's
>> + * cache. */
>> +static svn_error_t *
>> +gnome_keyring_ssl_client_cert_pw_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__ssl_client_cert_pw_file_save_creds_helper
>> +           (saved, credentials,
>> +            provider_baton, parameters,
>> +            realmstring,
>> +            gnome_keyring_password_set,
>> +            SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE,
>> +            pool);
>> +}
> 
> You use gnome_keyring_password_get() and gnome_keyring_password_set().
> Won't it cause collision with passwords stored by GNOME Keyring simple provider?

No it wont't cause a collision since we have realmstring to differentiate. I 
verified it.

Updated patch attached as per your other comments.

-- 
Senthil Kumaran S
http://www.stylesen.org/

["client_passphrase_cache_gnome_keyring_3.patch.txt" (text/plain)]

[[[
Cache ssl client certificate passphrase.

* subversion/libsvn_ra/ra_loader.c
  (svn_ra_open3): Load config options for storing passphrase from servers
   config file.

* subversion/libsvn_subr/config_file.c
  (ensure_auth_dirs): Create new auth dir to store ssl client cert passphrase.
  (svn_config_ensure): Add doc for the new options in the servers file string.

* subversion/libsvn_subr/cmdline.c
  (get_auth_simple_provider): Rename ...
  (get_auth_provider): ... Return providers based on the provider_type.
  (svn_cmdline_setup_auth_baton): If we have gnome keyring support get the
   corresponding ssl client cert passphrase provider.

* subversion/libsvn_subr/ssl_client_cert_pw_providers.c
  (): Include some private headers. Define SVN_AUTH__AUTHFILE_PASSPHRASE_KEY,
   SVN_AUTH__AUTHFILE_PASSTYPE_KEY.
  (ssl_client_cert_pw_file_provider_baton_t): New baton for ssl client cert
   passphrase provider.
  (simple_passphrase_get): New function to get plaintext passphrase.
  (simple_passphrase_set): New function to store plaintext passphrase.
  (ssl_client_cert_pw_file_first_credentials): Move logic to new helper.
  (ssl_client_cert_pw_file_save_credentials): Move logic to new helper.
  (svn_auth__ssl_client_cert_pw_file_first_creds_helper): New helper function
   for ssl_client_cert_pw_file_first_credentials.
  (svn_auth__ssl_client_cert_pw_file_save_creds_helper): New helper function
   for ssl_client_cert_pw_file_save_credentials.
  (ssl_client_cert_pw_file_provider): Add provision for saving credentials.
  (svn_auth_get_ssl_client_cert_pw_file_provider2): New public API which has
   a prompt function now.
  (svn_auth_get_ssl_client_cert_pw_file_provider): Update API for the above.

* subversion/libsvn_subr/prompt.c
  (plaintext_prompt_helper): New function which has the logic for plaintext
   promting functions.
  (svn_cmdline_auth_plaintext_prompt): Move logic to above function.
  (svn_cmdline_auth_plaintext_passphrase_prompt): New prompt function for
   plaintext passphrase prompt.

* subversion/libsvn_auth_gnome_keyring/gnome_keyring.c
  (gnome_keyring_ssl_client_cert_pw_first_creds): New function to get ssl
   client cert passphrase from encrypted credentials.
  (gnome_keyring_ssl_client_cert_pw_save_creds): New function to save
   encrypted ssl client cert passphrase.
  (gnome_keyring_ssl_client_cert_pw_provider): New baton.
  (svn_auth_get_gnome_keyring_ssl_client_cert_pw_provider): New public API for
   gnome keyring based ssl client cert passphrase storage and retrieval.

* subversion/include/svn_config.h
  (SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP): New option to store ssl client
   cert passphrase.
  (SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSPHRASE): New option to store plaintext
   passphrase.
  (SVN_CONFIG_DEFAULT_OPTION_STORE_PASSPHRASE): New default option for storing
   passphrase set to 'yes'.
  (SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSPHRASE): New default option to
   store plaintext passphrase set to 'ask'.

* subversion/include/svn_auth_dso.h
  (svn_auth_get_gnome_keyring_ssl_client_cert_pw_provider): New public API.

* subversion/include/svn_cmdline.h
  (svn_cmdline_auth_plaintext_passphrase_prompt): New public API added to
   prompt for storing plaintext passphrases.

* subversion/include/private/svn_auth_private.h
  (svn_auth__ssl_client_cert_pw_file_first_creds_helper): New private function.
  (svn_auth__ssl_client_cert_pw_file_save_creds_helper): New private function.

* subversion/include/svn_auth.h
  (svn_auth_ssl_client_cert_pw_provider_func_t): Define function type for the
   provider.
  (svn_auth_plaintext_passphrase_prompt_func_t): New function prototype.
  (SVN_AUTH_PARAM_DONT_STORE_PASSPHRASE): New constant.
  (SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSPHRASE): New constant.
  (svn_auth_get_ssl_client_cert_pw_file_provider2): New public API.

* subversion/libsvn_ra_neon/session.c
  (client_ssl_decrypt_cert): Call svn_auth_save_credentials to save the ssl
   client certificate passphrase.

Patch by: stylesen
]]]
Index: subversion/libsvn_ra/ra_loader.c
===================================================================
--- subversion/libsvn_ra/ra_loader.c	(revision 31532)
+++ subversion/libsvn_ra/ra_loader.c	(working copy)
@@ -401,6 +401,9 @@
   svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
   const char *store_plaintext_passwords
     = SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS;
+  const char *store_plaintext_passphrase
+    = SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSPHRASE;
+  svn_boolean_t store_passphrase = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSPHRASE;
 
   if (callbacks->auth_baton)
     {
@@ -447,6 +450,16 @@
              SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));
 
           SVN_ERR(svn_config_get_bool
+            (servers, &store_passphrase, SVN_CONFIG_SECTION_GLOBAL,
+             SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
+             store_passphrase));
+
+          SVN_ERR(svn_config_get_yes_no_ask
+            (servers, &store_plaintext_passphrase, SVN_CONFIG_SECTION_GLOBAL,
+             SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSPHRASE,
+             SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSPHRASE));
+
+          SVN_ERR(svn_config_get_bool
             (servers, &store_auth_creds, SVN_CONFIG_SECTION_GLOBAL,
               SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
               store_auth_creds));
@@ -483,6 +496,16 @@
                 (servers, &store_plaintext_passwords, server_group,
                  SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
                  store_plaintext_passwords));
+
+              SVN_ERR(svn_config_get_bool
+                (servers, &store_passphrase,
+                 server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
+                 store_passphrase));
+
+              SVN_ERR(svn_config_get_yes_no_ask
+                (servers, &store_plaintext_passphrase, server_group,
+                 SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSPHRASE,
+                 store_plaintext_passphrase));
             }
 #ifdef MUST_CHOOSE_DAV
           /* Now, which DAV-based RA method do we want to use today? */
@@ -513,6 +536,14 @@
                              SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
                              store_plaintext_passwords);
 
+      if (! store_passphrase)
+        svn_auth_set_parameter(callbacks->auth_baton,
+                               SVN_AUTH_PARAM_DONT_STORE_PASSPHRASE, "");
+
+      svn_auth_set_parameter(callbacks->auth_baton,
+                             SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSPHRASE,
+                             store_plaintext_passphrase);
+
       if (! store_auth_creds)
         svn_auth_set_parameter(callbacks->auth_baton,
                                SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
Index: subversion/libsvn_subr/config_file.c
===================================================================
--- subversion/libsvn_subr/config_file.c	(revision 31532)
+++ subversion/libsvn_subr/config_file.c	(working copy)
@@ -497,6 +497,15 @@
       svn_error_clear(err);
       svn_error_clear(svn_io_dir_make(auth_subdir, APR_OS_DEFAULT, pool));
     }
+
+  auth_subdir = svn_path_join_many(pool, auth_dir,
+                                   SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, NULL);
+  err = svn_io_check_path(auth_subdir, &kind, pool);
+  if (err || kind == svn_node_none)
+    {
+      svn_error_clear(err);
+      svn_error_clear(svn_io_dir_make(auth_subdir, APR_OS_DEFAULT, pool));
+    }
 }
 
 
@@ -757,7 +766,12 @@
         "###                              to disk in any way."               NL
         "###   store-plaintext-passwords  Specifies whether passwords may"   NL
         "###                              be cached on disk unencrypted."    NL
-        "###"                                                                NL
+        "###   store-ssl-client-cert-pp   Specifies whether passphrase used" NL
+        "###                              to authenticate against a client"  NL
+        "###                              certificate may be cached to disk" NL
+        "###                              in any way"                        NL
+        "###   store-plaintext-passphrase Specifies whether passphrases may" NL
+        "###                              be cached on disk unencrypted."    NL
         "###   store-auth-creds           Specifies whether any auth info"   NL
         "###                              (passwords as well as server certs)"
                                                                              NL
@@ -780,6 +794,24 @@
         "### this option has no effect if either 'store-passwords' or "      NL
         "### 'store-auth-creds' is set to 'no'."                             NL
         "###"                                                                NL
+        "### Set store-ssl-client-cert-pp to 'no' to avoid storing ssl"      NL
+        "### client certificate passphrase in the auth/ area of your"        NL
+        "### config directory. It defaults to 'yes', but Subversion will"    NL
+        "### never save your passphrase to disk in plaintext unless you tell"NL
+        "### it to."                                                         NL
+        "### Note that this option only prevents saving of *new* passphrase;"NL
+        "### it doesn't invalidate existing passphrase. (To do that, remove" NL
+        "### the cache files by hand as described in the Subversion book.)"  NL
+        "###"                                                                NL
+        "### Set store-plaintext-passphrase to 'no' to avoid storing"        NL
+        "### passphrase in unencrypted form in the auth/ area of your config"NL
+        "### directory. Set it to 'yes' to allow Subversion to store"        NL
+        "### unencrypted passphrase in the auth/ area.  The default is"      NL
+        "### 'ask', which means that Subversion will ask you before"         NL
+        "### saving a passphrase to disk in unencrypted form.  Note that"    NL
+        "### this option has no effect if either 'store-passphrase' or "     NL
+        "### 'store-auth-creds' is set to 'no'."                             NL
+        "###"                                                                NL
         "### Set store-auth-creds to 'no' to avoid storing any Subversion"   NL
         "### credentials in the auth/ area of your config directory."        NL
         "### Note that this includes SSL server certificates."               NL
Index: subversion/libsvn_subr/cmdline.c
===================================================================
--- subversion/libsvn_subr/cmdline.c	(revision 31532)
+++ subversion/libsvn_subr/cmdline.c	(working copy)
@@ -355,11 +355,12 @@
 }
 
 #if defined(SVN_HAVE_KWALLET) || defined(SVN_HAVE_GNOME_KEYRING)
-/* Dynamically load authentication simple provider. */
+/* Dynamically load authentication provider. */
 static svn_boolean_t
-get_auth_simple_provider(svn_auth_provider_object_t **provider,
-                         const char *provider_name,
-                         apr_pool_t *pool)
+get_auth_provider(svn_auth_provider_object_t **provider,
+                  const char *provider_name,
+                  const char *provider_type,
+                  apr_pool_t *pool)
 {
   apr_dso_handle_t *dso;
   apr_dso_handle_sym_t symbol;
@@ -372,8 +373,9 @@
                          provider_name,
                          SVN_VER_MAJOR);
   funcname = apr_psprintf(pool,
-                          "svn_auth_get_%s_simple_provider",
-                          provider_name);
+                          "svn_auth_get_%s_%s_provider",
+                          provider_name, provider_type);
+
   err = svn_dso_load(&dso, libname);
   if (err == SVN_NO_ERROR)
     {
@@ -381,10 +383,20 @@
         {
           if (! apr_dso_sym(&symbol, dso, funcname))
             {
-              svn_auth_simple_provider_func_t func;
-              func = (svn_auth_simple_provider_func_t) symbol;
-              func(provider, pool);
-              ret = TRUE;
+              if (strcmp(provider_type, "simple") == 0)
+                {
+                  svn_auth_simple_provider_func_t func;
+                  func = (svn_auth_simple_provider_func_t) symbol;
+                  func(provider, pool);
+                  ret = TRUE;
+                }
+              else if (strcmp(provider_type, "ssl_client_cert_pw") == 0)
+                {
+                  svn_auth_ssl_client_cert_pw_provider_func_t func;
+                  func = (svn_auth_ssl_client_cert_pw_provider_func_t) symbol;
+                  func(provider, pool);
+                  ret = TRUE;
+                }
             }
         }
     }
@@ -464,10 +476,16 @@
       if (apr_strnatcmp(password_store, "gnome-keyring") == 0)
         {
 #ifdef SVN_HAVE_GNOME_KEYRING
-          if (get_auth_simple_provider(&provider, "gnome_keyring", pool))
+          if (get_auth_provider(&provider, "gnome_keyring", "simple", pool))
             {
               APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
             }
+          if (get_auth_provider(&provider, "gnome_keyring",
+                                "ssl_client_cert_pw", pool))
+            {
+              APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *)
+                = provider;
+            }
 #endif
           continue;
         }
@@ -475,7 +493,7 @@
       if (apr_strnatcmp(password_store, "kwallet") == 0)
         {
 #ifdef SVN_HAVE_KWALLET
-          if (get_auth_simple_provider(&provider, "kwallet", pool))
+          if (get_auth_provider(&provider, "kwallet", pool))
             {
               APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
             }
@@ -490,10 +508,8 @@
 
   if (non_interactive == FALSE)
     {
-      /* This provider is odd in that it isn't a prompting provider in
-         the classic sense.  That is, it doesn't need to prompt in
-         order to get creds, but it *does* need to prompt the user
-         regarding the *cache storage* of creds. */
+      /* This provider doesn't prompt the user in order to get creds.
+       * It prompts the user regarding the caching of creds. */
       svn_auth_get_simple_provider2(&provider,
                                     svn_cmdline_auth_plaintext_prompt,
                                     pb, pool);
@@ -515,7 +531,20 @@
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
   svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-  svn_auth_get_ssl_client_cert_pw_file_provider(&provider, pool);
+
+  if (non_interactive == FALSE)
+    {
+      /* This provider doesn't prompt the user in order to get creds.
+       * It prompts the user regarding the caching of creds. */
+      svn_auth_get_ssl_client_cert_pw_file_provider2
+        (&provider, svn_cmdline_auth_plaintext_passphrase_prompt,
+         pb, pool);
+    }
+  else
+    {
+      svn_auth_get_ssl_client_cert_pw_file_provider2(&provider, NULL, NULL,
+                                                     pool);
+    }
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 
   if (non_interactive == FALSE)
Index: subversion/libsvn_subr/ssl_client_cert_pw_providers.c
===================================================================
--- subversion/libsvn_subr/ssl_client_cert_pw_providers.c	(revision 31532)
+++ subversion/libsvn_subr/ssl_client_cert_pw_providers.c	(working copy)
@@ -28,31 +28,112 @@
 #include "svn_error.h"
 #include "svn_config.h"
 
+#include "private/svn_auth_private.h"
+
+#include "svn_private_config.h"
 
 /*-----------------------------------------------------------------------*/
 /* File provider                                                         */
 /*-----------------------------------------------------------------------*/
 
-/* retrieve and load a password for a client certificate from servers file */
-static svn_error_t *
-ssl_client_cert_pw_file_first_credentials(void **credentials_p,
-                                          void **iter_baton,
-                                          void *provider_baton,
-                                          apr_hash_t *parameters,
-                                          const char *realmstring,
-                                          apr_pool_t *pool)
+/* The keys that will be stored on disk */
+#define SVN_AUTH__AUTHFILE_PASSPHRASE_KEY            "passphrase"
+#define SVN_AUTH__AUTHFILE_PASSTYPE_KEY              "passtype"
+
+/* Baton type for the ssl client cert passphrase provider. */
+typedef struct
 {
+  svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func;
+  void *prompt_baton;
+  /* We cache the user's answer to the plaintext prompt, keyed
+   * by realm, in case we'll be called multiple times for the
+   * same realm. */
+  apr_hash_t *plaintext_answers;
+} ssl_client_cert_pw_file_provider_baton_t;
+
+/* Implementation of svn_auth__password_get_t that retrieves
+   the plaintext passphrase from CREDS. */
+static svn_boolean_t
+simple_passphrase_get(const char **passphrase,
+                      apr_hash_t *creds,
+                      const char *realmstring,
+                      const char *username,
+                      svn_boolean_t non_interactive,
+                      apr_pool_t *pool)
+{
+  svn_string_t *str;
+  str = apr_hash_get(creds, SVN_AUTH__AUTHFILE_PASSPHRASE_KEY,
+                     APR_HASH_KEY_STRING);
+  if (str && str->data)
+    {
+      *passphrase = str->data;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+/* Implementation of svn_auth__password_set_t that stores
+   the plaintext passphrase in CREDS. */
+static svn_boolean_t
+simple_passphrase_set(apr_hash_t *creds,
+                      const char *realmstring,
+                      const char *username,
+                      const char *passphrase,
+                      svn_boolean_t non_interactive,
+                      apr_pool_t *pool)
+{
+  apr_hash_set(creds, SVN_AUTH__AUTHFILE_PASSPHRASE_KEY, APR_HASH_KEY_STRING,
+               svn_string_create(passphrase, pool));
+  return TRUE;
+}
+
+/* retrieve and load a password for a client certificate from servers file,
+ * else from the auth/ cache. */
+svn_error_t *
+svn_auth__ssl_client_cert_pw_file_first_creds_helper
+  (void **credentials_p,
+   void **iter_baton,
+   void *provider_baton,
+   apr_hash_t *parameters,
+   const char *realmstring,
+   svn_auth__password_get_t passphrase_get,
+   const char *passtype,
+   apr_pool_t *pool)
+{
   svn_config_t *cfg = apr_hash_get(parameters,
                                    SVN_AUTH_PARAM_CONFIG,
                                    APR_HASH_KEY_STRING);
   const char *server_group = apr_hash_get(parameters,
                                           SVN_AUTH_PARAM_SERVER_GROUP,
                                           APR_HASH_KEY_STRING);
-
+  svn_boolean_t non_interactive = apr_hash_get(parameters,
+                                               SVN_AUTH_PARAM_NON_INTERACTIVE,
+                                               APR_HASH_KEY_STRING) != NULL;
   const char *password =
     svn_config_get_server_setting(cfg, server_group,
                                   SVN_CONFIG_OPTION_SSL_CLIENT_CERT_PASSWORD,
                                   NULL);
+  if (! password)
+    {
+      svn_error_t *err;
+      apr_hash_t *creds_hash = NULL;
+      const char *config_dir = apr_hash_get(parameters,
+                                            SVN_AUTH_PARAM_CONFIG_DIR,
+                                            APR_HASH_KEY_STRING);
+
+      /* Try to load passphrase from the auth/ cache. */
+      err = svn_config_read_auth_data(&creds_hash,
+                                      SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
+                                      realmstring, config_dir, pool);
+      svn_error_clear(err);
+      if (! err && creds_hash)
+        {
+          if (!passphrase_get(&password, creds_hash, realmstring,
+                              NULL, non_interactive, pool))
+            password = NULL;
+        }
+    }
+
   if (password)
     {
       svn_auth_cred_ssl_client_cert_pw_t *cred
@@ -67,23 +148,244 @@
 }
 
 
+/* Save passphrase for a client certificate in auth/ cache */
+svn_error_t *
+svn_auth__ssl_client_cert_pw_file_save_creds_helper
+  (svn_boolean_t *saved,
+   void *credentials,
+   void *provider_baton,
+   apr_hash_t *parameters,
+   const char *realmstring,
+   svn_auth__password_set_t passphrase_set,
+   const char *passtype,
+   apr_pool_t *pool)
+{
+  svn_auth_cred_ssl_client_cert_pw_t *creds = credentials;
+  apr_hash_t *creds_hash = NULL;
+  const char *config_dir;
+  svn_error_t *err;
+  svn_boolean_t dont_store_passphrase =
+    apr_hash_get(parameters,
+                 SVN_AUTH_PARAM_DONT_STORE_PASSPHRASE,
+                 APR_HASH_KEY_STRING) != NULL;
+  const char *store_plaintext_passphrase =
+    apr_hash_get(parameters,
+                 SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSPHRASE,
+                 APR_HASH_KEY_STRING);
+  svn_boolean_t non_interactive = apr_hash_get(parameters,
+                                               SVN_AUTH_PARAM_NON_INTERACTIVE,
+                                               APR_HASH_KEY_STRING) != NULL;
+  ssl_client_cert_pw_file_provider_baton_t *b = 
+    (ssl_client_cert_pw_file_provider_baton_t *)provider_baton;
+
+  svn_boolean_t no_auth_cache =
+    (! creds->may_save) || (apr_hash_get(parameters,
+                                         SVN_AUTH_PARAM_NO_AUTH_CACHE,
+                                         APR_HASH_KEY_STRING) != NULL);
+
+  *saved = FALSE;
+
+  if (no_auth_cache)
+    return SVN_NO_ERROR;
+
+  config_dir = apr_hash_get(parameters,
+                            SVN_AUTH_PARAM_CONFIG_DIR,
+                            APR_HASH_KEY_STRING);
+  creds_hash = apr_hash_make(pool);
+
+  /* Don't store passphrase in any form if the user has told
+   * us not to do so. */
+  if (! dont_store_passphrase)
+    {
+      svn_boolean_t may_save_passphrase = FALSE;
+
+      /* If the passphrase is going to be stored encrypted, go right
+       * ahead and store it to disk. Else determine whether saving
+       * in plaintext is OK. */
+      if (strcmp(passtype, SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE) == 0)
+        {
+          may_save_passphrase = TRUE;
+        }
+      else
+        {
+          if (svn_cstring_casecmp(store_plaintext_passphrase,
+                                  SVN_CONFIG_ASK) == 0)
+            {
+              if (non_interactive)
+                /* In non-interactive mode, the default behaviour is
+                 * to not store the passphrase */
+                may_save_passphrase = FALSE;
+              else if (b->plaintext_passphrase_prompt_func)
+                {
+                  /* We're interactive, and the client provided a
+                   * prompt callback. So we can ask the user.
+                   *
+                   * Check for a cached answer before prompting. */
+                  svn_boolean_t *cached_answer;
+                  cached_answer = apr_hash_get(b->plaintext_answers,
+                                               realmstring,
+                                               APR_HASH_KEY_STRING);
+                  if (cached_answer)
+                    may_save_passphrase = *cached_answer;
+                  else
+                    {
+                      /* Nothing cached for this realm, prompt the user. */
+                      SVN_ERR((*b->plaintext_passphrase_prompt_func)
+                               (&may_save_passphrase,
+                                realmstring,
+                                b->prompt_baton,
+                                pool));
+
+                      /* Cache the user's answer in case we're called again
+                       * for the same realm.
+                       *
+                       * XXX: Hopefully, our caller has passed us
+                       * a pool that survives across RA sessions!
+                       * We use that pool to cache user answers, and
+                       * we may be called again for the same realm when the
+                       * current RA session is reparented, or when a different
+                       * RA session using the same realm is opened.
+                       * If the pool does not survive until then, caching
+                       * won't work, and for some reason the call to
+                       * apr_hash_set() below may even end up crashing in
+                       * apr_palloc().
+                       */
+                      cached_answer = apr_palloc(pool, sizeof(svn_boolean_t));
+                      *cached_answer = may_save_passphrase;
+                      apr_hash_set(b->plaintext_answers, realmstring,
+                                   APR_HASH_KEY_STRING, cached_answer);
+                    }
+                }
+              else
+                {
+                  may_save_passphrase = FALSE;
+                }
+            }
+          else if (svn_cstring_casecmp(store_plaintext_passphrase,
+                                       SVN_CONFIG_FALSE) == 0)
+            {
+              may_save_passphrase = FALSE;
+            }
+          else if (svn_cstring_casecmp(store_plaintext_passphrase,
+                                       SVN_CONFIG_TRUE) == 0)
+            {
+              may_save_passphrase = TRUE;
+            }
+          else
+            {
+              return svn_error_createf
+                (SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL,
+                 _("Config error: invalid value '%s' for option '%s'"),
+                store_plaintext_passphrase,
+                SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSPHRASE);
+            }
+        }
+
+      if (may_save_passphrase)
+        {
+          *saved = passphrase_set(creds_hash, realmstring,
+                                  NULL, creds->password,
+                                  non_interactive, pool);
+
+          if (*saved && passtype)
+              /* Store the passphrase type with the auth data, so that we
+                 know which provider owns the password. */
+              apr_hash_set(creds_hash, SVN_AUTH__AUTHFILE_PASSTYPE_KEY,
+                           APR_HASH_KEY_STRING,
+                           svn_string_create(passtype, pool));
+
+          /* Save credentials to disk. */
+          err = svn_config_write_auth_data(creds_hash,
+                                           SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
+                                           realmstring, config_dir, pool);
+          svn_error_clear(err);
+          *saved = ! err;
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Get cached (unencrypted) credentials from the ssl client cert password
+ * provider's cache. */
+static svn_error_t *
+ssl_client_cert_pw_file_first_credentials(void **credentials,
+                                          void **iter_baton,
+                                          void *provider_baton,
+                                          apr_hash_t *parameters,
+                                          const char *realmstring,
+                                          apr_pool_t *pool)
+{
+  return svn_auth__ssl_client_cert_pw_file_first_creds_helper
+           (credentials,
+            iter_baton,
+            provider_baton,
+            parameters,
+            realmstring,
+            simple_passphrase_get,
+            SVN_AUTH__SIMPLE_PASSWORD_TYPE,
+            pool);
+}
+
+
+/* Save (unencrypted) credentials to the ssl client cert password provider's
+ * cache. */
+static svn_error_t *
+ssl_client_cert_pw_file_save_credentials(svn_boolean_t *saved,
+                                         void *credentials,
+                                         void *provider_baton,
+                                         apr_hash_t *parameters,
+                                         const char *realmstring,
+                                         apr_pool_t *pool)
+{
+  return svn_auth__ssl_client_cert_pw_file_save_creds_helper
+           (saved, credentials,
+            provider_baton,
+            parameters,
+            realmstring,
+            simple_passphrase_set,
+            SVN_AUTH__SIMPLE_PASSWORD_TYPE,
+            pool);
+}
+
 static const svn_auth_provider_t ssl_client_cert_pw_file_provider = {
   SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
   ssl_client_cert_pw_file_first_credentials,
   NULL,
-  NULL
+  ssl_client_cert_pw_file_save_credentials
 };
 
 
 /*** Public API to SSL file providers. ***/
-void svn_auth_get_ssl_client_cert_pw_file_provider
-  (svn_auth_provider_object_t **provider, apr_pool_t *pool)
+void
+svn_auth_get_ssl_client_cert_pw_file_provider2
+  (svn_auth_provider_object_t **provider,
+   svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func,
+   void* prompt_baton,
+   apr_pool_t *pool)
 {
   svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+  ssl_client_cert_pw_file_provider_baton_t *pb = apr_pcalloc(pool,
+                                                             sizeof(*pb));
+
+  pb->plaintext_passphrase_prompt_func = plaintext_passphrase_prompt_func;
+  pb->prompt_baton = prompt_baton;
+  pb->plaintext_answers = apr_hash_make(pool);
+
   po->vtable = &ssl_client_cert_pw_file_provider;
+  po->provider_baton = pb;
   *provider = po;
 }
 
+void
+svn_auth_get_ssl_client_cert_pw_file_provider
+  (svn_auth_provider_object_t **provider,
+   apr_pool_t *pool)
+{
+  svn_auth_get_ssl_client_cert_pw_file_provider2(provider, NULL, NULL, pool);
+}
+
 
 /*-----------------------------------------------------------------------*/
 /* Prompt provider                                                       */
Index: subversion/libsvn_subr/prompt.c
===================================================================
--- subversion/libsvn_subr/prompt.c	(revision 31532)
+++ subversion/libsvn_subr/prompt.c	(working copy)
@@ -379,37 +379,25 @@
   return SVN_NO_ERROR;
 }
 
-/* This implements 'svn_auth_plaintext_prompt_func_t'. */
-svn_error_t *
-svn_cmdline_auth_plaintext_prompt(svn_boolean_t *may_save_plaintext,
-                                  const char *realmstring,
-                                  void *baton,
-                                  apr_pool_t *pool)
+/* This is a helper for plaintext prompt functions. */
+static svn_error_t *
+plaintext_prompt_helper(svn_boolean_t *may_save_plaintext,
+                        const char *realmstring,
+                        const char *prompt_string,
+                        const char *prompt_text,
+                        void *baton,
+                        apr_pool_t *pool)
 {
   const char *answer = NULL;
   svn_boolean_t answered = FALSE;
-  const char *prompt_string = _("Store password unencrypted (yes/no)? ");
   svn_cmdline_prompt_baton2_t *pb = baton;
   const char *config_path;
   
   SVN_ERR(svn_config_get_user_config_path(&config_path, pb->config_dir,
                                           SVN_CONFIG_CATEGORY_SERVERS, pool));
 
-  SVN_ERR(svn_cmdline_fprintf(stderr, pool,
-  _("-----------------------------------------------------------------------\n"
-    "ATTENTION!  Your password for authentication realm:\n"
-    "\n"
-    "   %s\n"
-    "\n"
-    "can only be stored to disk unencrypted!  You are advised to configure\n"
-    "your system so that Subversion can store passwords encrypted, if\n"
-    "possible.  See the documentation for details.\n"
-    "\n"
-    "You can avoid future appearances of this warning by setting the value\n"
-    "of the 'store-plaintext-passwords' option to either 'yes' or 'no' in\n"
-    "'%s'.\n"
-    "-----------------------------------------------------------------------\n"
-    ), realmstring, config_path));
+  SVN_ERR(svn_cmdline_fprintf(stderr, pool, prompt_text, realmstring,
+                              config_path));
 
   do
     {
@@ -443,6 +431,66 @@
   return SVN_NO_ERROR;
 }
 
+/* This implements 'svn_auth_plaintext_prompt_func_t'. */
+svn_error_t *
+svn_cmdline_auth_plaintext_prompt(svn_boolean_t *may_save_plaintext,
+                                  const char *realmstring,
+                                  void *baton,
+                                  apr_pool_t *pool)
+{
+  const char *prompt_string = _("Store password unencrypted (yes/no)? ");
+  const char *prompt_text =
+  _("-----------------------------------------------------------------------\n"
+    "ATTENTION!  Your password for authentication realm:\n"
+    "\n"
+    "   %s\n"
+    "\n"
+    "can only be stored to disk unencrypted!  You are advised to configure\n"
+    "your system so that Subversion can store passwords encrypted, if\n"
+    "possible.  See the documentation for details.\n"
+    "\n"
+    "You can avoid future appearances of this warning by setting the value\n"
+    "of the 'store-plaintext-passwords' option to either 'yes' or 'no' in\n"
+    "'%s'.\n"
+    "-----------------------------------------------------------------------\n"
+    );
+
+  SVN_ERR(plaintext_prompt_helper(may_save_plaintext, realmstring,
+                                  prompt_string, prompt_text, baton,
+                                  pool));
+  return SVN_NO_ERROR;
+}
+
+/* This implements 'svn_auth_plaintext_passphrase_prompt_func_t'. */
+svn_error_t *
+svn_cmdline_auth_plaintext_passphrase_prompt(svn_boolean_t *may_save_plaintext,
+                                             const char *realmstring,
+                                             void *baton,
+                                             apr_pool_t *pool)
+{
+  const char *prompt_string = _("Store passphrase unencrypted (yes/no)? ");
+  const char *prompt_text =
+  _("-----------------------------------------------------------------------\n"
+    "ATTENTION!  Your passphrase for client certificate:\n"
+    "\n"
+    "   %s\n"
+    "\n"
+    "can only be stored to disk unencrypted!  You are advised to configure\n"
+    "your system so that Subversion can store passphrase encrypted, if\n"
+    "possible.  See the documentation for details.\n"
+    "\n"
+    "You can avoid future appearances of this warning by setting the value\n"
+    "of the 'store-plaintext-passphrase' option to either 'yes' or 'no' in\n"
+    "'%s'.\n"
+    "-----------------------------------------------------------------------\n"
+    );
+
+  SVN_ERR(plaintext_prompt_helper(may_save_plaintext, realmstring,
+                                  prompt_string, prompt_text, baton,
+                                  pool));
+  return SVN_NO_ERROR;
+}
+
 
 /** Generic prompting. **/
 
Index: subversion/libsvn_auth_gnome_keyring/gnome_keyring.c
===================================================================
--- subversion/libsvn_auth_gnome_keyring/gnome_keyring.c	(revision 31532)
+++ subversion/libsvn_auth_gnome_keyring/gnome_keyring.c	(working copy)
@@ -192,3 +192,60 @@
 
   gnome_keyring_init();
 }
+
+/* Get cached encrypted credentials from the ssl client cert password
+ * provider's cache. */
+static svn_error_t *
+gnome_keyring_ssl_client_cert_pw_first_creds(void **credentials,
+                                             void **iter_baton,
+                                             void *provider_baton,
+                                             apr_hash_t *parameters,
+                                             const char *realmstring,
+                                             apr_pool_t *pool)
+{
+  return svn_auth__ssl_client_cert_pw_file_first_creds_helper
+           (credentials,
+            iter_baton, provider_baton,
+            parameters, realmstring,
+            gnome_keyring_password_get,
+            SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE,
+            pool);
+}
+
+/* Save encrypted credentials to the ssl client cert password provider's
+ * cache. */
+static svn_error_t *
+gnome_keyring_ssl_client_cert_pw_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__ssl_client_cert_pw_file_save_creds_helper
+           (saved, credentials,
+            provider_baton, parameters,
+            realmstring,
+            gnome_keyring_password_set,
+            SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE,
+            pool);
+}
+
+static const svn_auth_provider_t gnome_keyring_ssl_client_cert_pw_provider = {
+  SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
+  gnome_keyring_ssl_client_cert_pw_first_creds,
+  NULL,
+  gnome_keyring_ssl_client_cert_pw_save_creds
+};
+
+/* Public API */
+void
+svn_auth_get_gnome_keyring_ssl_client_cert_pw_provider
+    (svn_auth_provider_object_t **provider,
+     apr_pool_t *pool)
+{
+  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+
+  po->vtable = &gnome_keyring_ssl_client_cert_pw_provider;
+  *provider = po;
+}
Index: subversion/include/svn_config.h
===================================================================
--- subversion/include/svn_config.h	(revision 31532)
+++ subversion/include/svn_config.h	(working copy)
@@ -77,6 +77,9 @@
 #define SVN_CONFIG_OPTION_STORE_PASSWORDS           "store-passwords"
 #define SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS "store-plaintext-passwords"
 #define SVN_CONFIG_OPTION_STORE_AUTH_CREDS          "store-auth-creds"
+#define SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP  "store-ssl-client-cert-pp"
+#define SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSPHRASE \
+                                                   "store-plaintext-passphrase"
 
 #define SVN_CONFIG_CATEGORY_CONFIG          "config"
 #define SVN_CONFIG_SECTION_AUTH                 "auth"
@@ -146,9 +149,11 @@
 /* Default values for some options. Should be passed as default values
  * to svn_config_get and friends, instead of hard-coding the defaults in
  * multiple places. */
-#define SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS           TRUE
-#define SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS SVN_CONFIG_ASK
-#define SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS          TRUE
+#define SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS            TRUE
+#define SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS  SVN_CONFIG_ASK
+#define SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS           TRUE
+#define SVN_CONFIG_DEFAULT_OPTION_STORE_PASSPHRASE           TRUE
+#define SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSPHRASE SVN_CONFIG_ASK
 
 /** Read configuration information from the standard sources and merge it
  * into the hash @a *cfg_hash.  If @a config_dir is not NULL it specifies a
Index: subversion/include/svn_auth_dso.h
===================================================================
--- subversion/include/svn_auth_dso.h	(revision 31532)
+++ subversion/include/svn_auth_dso.h	(working copy)
@@ -51,6 +51,25 @@
 
 /**
  * Create and return @a *provider, an authentication provider of type @c
+ * svn_auth_cred_ssl_client_cert_pw_t that gets/sets information from the
+ * user's ~/.subversion configuration directory.  Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_client_get_ssl_client_cert_pw_file_provider(), except
+ * that the password is stored in GNOME Keyring.
+ *
+ * @since New in 1.6
+ * @note This function actually works only on systems with
+ * libsvn_auth_gnome_keyring and GNOME Keyring installed.
+ */
+void
+svn_auth_get_gnome_keyring_ssl_client_cert_pw_provider
+  (svn_auth_provider_object_t **provider,
+   apr_pool_t *pool);
+
+
+/**
+ * Create and return @a *provider, an authentication provider of type @c
  * svn_auth_cred_simple_t that gets/sets information from the user's
  * ~/.subversion configuration directory.  Allocate @a *provider in
  * @a pool.
Index: subversion/include/svn_cmdline.h
===================================================================
--- subversion/include/svn_cmdline.h	(revision 31532)
+++ subversion/include/svn_cmdline.h	(working copy)
@@ -277,6 +277,17 @@
                                   void *baton,
                                   apr_pool_t *pool);
 
+/** An implementation of @c svn_auth_plaintext_passphrase_prompt_func_t that
+ * prompts the user whether storing unencypted passphrase to disk is OK.
+ *
+ * @since New in 1.6.
+ */
+svn_error_t *
+svn_cmdline_auth_plaintext_passphrase_prompt(svn_boolean_t *may_save_plaintext,
+                                             const char *realmstring,
+                                             void *baton,
+                                             apr_pool_t *pool);
+
 /** Initialize auth baton @a ab with the standard set of authentication
  * providers used by the command line client.  @a non_interactive,
  * @a username, @a password, @a config_dir, and @a no_auth_cache are the
Index: subversion/include/private/svn_auth_private.h
===================================================================
--- subversion/include/private/svn_auth_private.h	(revision 31532)
+++ subversion/include/private/svn_auth_private.h	(working copy)
@@ -93,6 +93,38 @@
                                    const char *passtype,
                                    apr_pool_t *pool);
 
+/* Common implementation for ssl_client_cert_pw_file_first_credentials.
+   Uses PARAMETERS, REALMSTRING and the  ssl client passphrase auth provider's
+   passphrase cache to fill the CREDENTIALS. PASSPHRASE_GET is used to obtain
+   the passphrase value. PASSTYPE identifies the type of the cached passphrase.
+   CREDENTIALS are allocated from POOL. */
+svn_error_t *
+svn_auth__ssl_client_cert_pw_file_first_creds_helper
+  (void **credentials,
+   void **iter_baton,
+   void *provider_baton,
+   apr_hash_t *parameters,
+   const char *realmstring,
+   svn_auth__password_get_t passphrase_get,
+   const char *passtype,
+   apr_pool_t *pool);
+
+/* Common implementation for ssl_client_cert_pw_file_save_credentials and
+   Uses PARAMETERS and REALMSTRING to save a set of CREDENTIALS to the ssl
+   client cert auth provider's passphrase cache. PASSPHRASE_SET is used to
+   store the passphrase. PASSTYPE identifies the type of the cached passphrase.
+   Allocates from POOL. */
+svn_error_t *
+svn_auth__ssl_client_cert_pw_file_save_creds_helper
+  (svn_boolean_t *saved,
+   void *credentials,
+   void *provider_baton,
+   apr_hash_t *parameters,
+   const char *realmstring,
+   svn_auth__password_set_t passphrase_set,
+   const char *passtype,
+   apr_pool_t *pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: subversion/include/svn_auth.h
===================================================================
--- subversion/include/svn_auth.h	(revision 31532)
+++ subversion/include/svn_auth.h	(working copy)
@@ -238,6 +238,11 @@
 } svn_auth_cred_ssl_client_cert_t;
 
 
+/** A function returning an SSL client certificate passphrase provider. */
+typedef void (*svn_auth_ssl_client_cert_pw_provider_func_t)
+  (svn_auth_provider_object_t **provider,
+   apr_pool_t *pool);
+
 /** SSL client certificate passphrase credential type.
  *
  * @note The realmstring used with this credential type must be a name that
@@ -500,6 +505,38 @@
    void *baton,
    apr_pool_t *pool);
 
+/** Called only by providers which save passphrase unencrypted.
+ * In this callback, clients should ask the user whether storing
+ * a passphrase for the realm identified by @a realmstring to disk
+ * in plaintext is allowed.
+ *
+ * The answer is returned in @a *may_save_plaintext.
+ * @a baton is an implementation-specific closure.
+ * All allocations should be done in @a pool.
+ *
+ * This callback is called only once per authentication realm,
+ * not once per RA session. This means that clients implementing
+ * this callback must make sure that the pool passed to any
+ * implementation of save_credentials (part of svn_auth_provider_t)
+ * survives across RA sessions.
+ *
+ * If this callback is NULL it is not called.
+ * Client developers are highly encouraged to provide this callback
+ * to ensure their users are made aware of the fact that their passphrase
+ * is going to be stored unencrypted.
+ *
+ * Clients can however set the callback to NULL and set
+ * SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSPHRASE to SVN_CONFIG_FALSE or
+ * SVN_CONFIG_TRUE to enforce a certain behaviour. 
+ *
+ * @since New in 1.6
+ */
+typedef svn_error_t *(*svn_auth_plaintext_passphrase_prompt_func_t)
+  (svn_boolean_t *may_save_plaintext, 
+   const char *realmstring,
+   void *baton,
+   apr_pool_t *pool);
+
 
 /** Initialize an authentication system.
  *
@@ -572,6 +609,18 @@
 #define SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS  SVN_AUTH_PARAM_PREFIX \
                                                   "store-plaintext-passwords"
 
+/** @brief The application doesn't want any providers to save passphrase
+ * to disk. Property value is irrelevant; only property's existence
+ * matters. */
+#define SVN_AUTH_PARAM_DONT_STORE_PASSPHRASE  SVN_AUTH_PARAM_PREFIX \
+                                                 "dont-store-passphrase"
+
+/** @brief Indicates whether providers may save passphrase to disk in
+ * plaintext. Property value can be either SVN_CONFIG_TRUE,
+ * SVN_CONFIG_FALSE, or SVN_CONFIG_ASK. */
+#define SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSPHRASE  SVN_AUTH_PARAM_PREFIX \
+                                                  "store-plaintext-passphrase"
+
 /** @brief The application doesn't want any providers to save credentials
  * to disk. Property value is irrelevant; only property's existence
  * matters. */
@@ -832,12 +881,29 @@
 
 
 /** Create and return @a *provider, an authentication provider of type @c
- * svn_auth_cred_ssl_client_cert_pw_t, allocated in @a pool.
+ * svn_auth_cred_ssl_client_cert_pw_t that gets/sets information from the user's
+ * ~/.subversion configuration directory.
  *
- * @a *provider retrieves its credentials from the configuration
- * mechanism.  The returned credential is used when a loaded client
- * certificate is protected by a passphrase.
+ * If the provider is going to save the passphrase unencrypted,
+ * it calls @a plaintext_passphrase_prompt_func before saving the
+ * passphrase.
  *
+ * @a prompt_baton is passed to @a plaintext_passphrase_prompt_func.
+ *
+ * Allocate @a *provider in @a pool.
+ *
+ * @since New in 1.6.
+ */
+void svn_auth_get_ssl_client_cert_pw_file_provider2
+  (svn_auth_provider_object_t **provider,
+   svn_auth_plaintext_passphrase_prompt_func_t plaintext_passphrase_prompt_func,
+   void* prompt_baton,
+   apr_pool_t *pool);
+
+/** Like svn_auth_get_simple_provider2, but without the ability to
+ * call the svn_auth_plaintext_passphrase_prompt_func_t callback.
+ *
+ * @deprecated Provided for backwards compatibility with the 1.5 API.
  * @since New in 1.4.
  */
 void svn_auth_get_ssl_client_cert_pw_file_provider
Index: subversion/libsvn_ra_neon/session.c
===================================================================
--- subversion/libsvn_ra_neon/session.c	(revision 31532)
+++ subversion/libsvn_ra_neon/session.c	(working copy)
@@ -290,6 +290,10 @@
 
           if (ne_ssl_clicert_decrypt(clicert, pw_creds->password) == 0)
             {
+              error = svn_auth_save_credentials(state, pool);
+              if (error)
+                svn_error_clear(error);
+
               /* Success */
               ok = TRUE;
               break;



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic