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 19:50:55 UTC

svn commit: r1368622 - in /subversion/branches/master-passphrase/subversion: include/ libsvn_subr/ tests/libsvn_subr/

Author: cmpilato
Date: Thu Aug  2 17:50:54 2012
New Revision: 1368622

URL: http://svn.apache.org/viewvc?rev=1368622&view=rev
Log:
On the 'master-passphrase' branch, introduce flexibility on how master
passphrases are acquired for use with the encrypted store by
introducing a parallel auth baton/subsystem for this purpose.
(Fortunately, this didn't require code duplication, which would have
been a non-starter for me.)

Intended next step:  see if the GPG-Agent can remember a master
passphrase so that prompting needn't (always) occur.

* subversion/include/svn_auth.h
  (SVN_AUTH_CRED_MASTER_PASSPHRASE): New #define.
  (svn_auth_cred_master_passphrase_t): New structure type.
  (svn_auth_master_passphrase_prompt_func_t): New prompt function type.
  (svn_auth_get_master_passphrase_prompt_provider): New function.

* subversion/libsvn_subr/auth_store.h
  (svn_auth__master_passphrase_fetch_t): Remove as unused.
  (svn_auth__pathetic_store_get): Swap a simple secret-fetching
    callback function for a whole parallel auth subsystem used to
    fetch (possibly cached) master passphrases.
  (svn_auth__pathetic_store_create, svn_auth__pathetic_store_reencrypt):
    New functions.

* subversion/libsvn_subr/cmdline.c
  (open_auth_store): Add 'no_auth_cache' and 'non_interactive'
    parameters.  Build a parallel auth subsystem for master passphrase
    handling when dealing with an encrypted auth store.
  (svn_cmdline_create_auth_baton): Delay opening the auth store until
    other configuration parameters have been investigated.

* subversion/libsvn_subr/masterpass_providers.c
  New file with the guts of a master-passphrase-providing auth system
  plugin.

* subversion/libsvn_subr/pathetic_auth_store.c
  (pathetic_auth_store_baton_t): Lose 'secret_func' and 'secret_baton',
    and pick up a 'secret_auth_baton'.
  (write_auth_store): Add 'create' flag and handling.
  (create_auth_store, set_cred_hash): Update calls to write_auth_store().
  (acquire_secret): New helper function.
  (pathetic_store_open): Reduce the scope of this function a bit,
    disallowing store creation, and offloading secret acquisition to
    acquire_secret().
  (svn_auth__pathetic_store_get): Lose 'secret_func' and
    'secret_baton' parameters, and add 'secret_auth_baton'.  Update
    associated structure members accordingly.
  (svn_auth__pathetic_store_create, svn_auth__pathetic_store_reencrypt):
    New functions (the latter of which is near-empty-bodied).

* subversion/include/svn_cmdline.h,
* subversion/libsvn_subr/prompt.c
  (svn_cmdline_auth_master_passphrase_prompt): Rework as an
    svn_auth_master_passphrase_prompt_func_t implementation.

* subversion/tests/libsvn_subr/crypto-test.c
  (fetch_secret): Morph this into a master-passphrase prompt callback
    function.
  (get_master_passphrase_auth_baton): New helper function.
  (create_ephemeral_auth_store, test_auth_store_basic): Tweak in
    accordance with the changes made to interfaces.


Added:
    subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c   (with props)
Modified:
    subversion/branches/master-passphrase/subversion/include/svn_auth.h
    subversion/branches/master-passphrase/subversion/include/svn_cmdline.h
    subversion/branches/master-passphrase/subversion/libsvn_subr/auth_store.h
    subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c
    subversion/branches/master-passphrase/subversion/libsvn_subr/pathetic_auth_store.c
    subversion/branches/master-passphrase/subversion/libsvn_subr/prompt.c
    subversion/branches/master-passphrase/subversion/tests/libsvn_subr/crypto-test.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=1368622&r1=1368621&r2=1368622&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_auth.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_auth.h Thu Aug  2 17:50:54 2012
@@ -34,6 +34,7 @@
 
 #include "svn_types.h"
 #include "svn_config.h"
+#include "svn_string.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -339,6 +340,44 @@ typedef struct svn_auth_cred_ssl_server_
   apr_uint32_t accepted_failures;
 } svn_auth_cred_ssl_server_trust_t;
 
+/** Master passphrase credential type.
+ *
+ * @note The realmstring used with this credential type should make it
+ * possible for the user to identify that this Subversion-wide master
+ * passphrase.
+ *
+ * The following auth parameters are available to the providers:
+ *
+ * - @c SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG (@c svn_config_t*)
+ * - @c SVN_AUTH_PARAM_CONFIG_CATEGORY_SERVERS (@c svn_config_t*)
+ *
+ * The following optional auth parameters are relevant to the providers:
+ *
+ * - @c SVN_AUTH_PARAM_NO_AUTH_CACHE (@c void*)
+ *
+ * @since New in 1.8.
+ */
+#define SVN_AUTH_CRED_MASTER_PASSPHRASE "svn.master-passphrase"
+
+/** @c SVN_AUTH_CRED_MASTER_PASSPHRASE credentials.
+ *
+ * @since New in 1.8.
+ */
+typedef struct svn_auth_cred_master_passphrase_t
+{
+  /** Master passphrase: this is the SHA-1 digest (as a counted
+      string, not a pretty-printed C-string) of the user-supplied
+      passphrase.  Subversion doesn't want the actual passphrase! */
+  const svn_string_t *passphrase;
+
+  /** Indicates if the credentials may be saved (to disk). For
+   * example, a GUI prompt implementation with a remember password
+   * checkbox shall set @a may_save to TRUE if the checkbox is
+   * checked.
+   */
+  svn_boolean_t may_save;
+} svn_auth_cred_master_passphrase_t;
+
 
 
 /** Credential-constructing prompt functions. **/
@@ -519,6 +558,29 @@ typedef svn_error_t *(*svn_auth_plaintex
   void *baton,
   apr_pool_t *pool);
 
+
+/** Set @a *creds_p by prompting the user, allocating @a *creds_p in @a
+ * pool.  @a baton is an implementation-specific closure.  @a
+ * realmstring is a string identifying the encrypted authentication
+ * store whose master passphrase is required, and can be used in the
+ * prompt string.
+ *
+ * If @a may_save is FALSE, the auth system does not allow the
+ * credentials to be saved (to disk).  A prompt function shall not ask
+ * the user if the credentials shall be saved if @a may_save is FALSE.
+ * For example, a GUI client with a "Remember passphrase" checkbox
+ * would grey out (disable) the checkbox if @a may_save is FALSE.
+ *
+ * @since New in 1.8.
+ */
+typedef svn_error_t *(*svn_auth_master_passphrase_prompt_func_t)(
+  svn_auth_cred_master_passphrase_t **creds_p,
+  void *baton,
+  const char *realmstring,
+  svn_boolean_t may_save,
+  apr_pool_t *pool);
+
+
 
 /** Initialize an authentication system.
  *
@@ -1248,6 +1310,25 @@ svn_auth_get_ssl_client_cert_pw_prompt_p
   apr_pool_t *pool);
 
 
+/** 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 by using the @a prompt_func
+ * and @a prompt_baton.  The returned credential is used to unlock
+ * Subversion's encrypted authentication credential store.  The prompt
+ * will be retried @a retry_limit times. For infinite retries, set @a
+ * retry_limit to value less than 0.
+ *
+ * @since New in 1.4.
+ */
+void svn_auth_get_master_passphrase_prompt_provider(
+  svn_auth_provider_object_t **provider,
+  svn_auth_master_passphrase_prompt_func_t prompt_func,
+  void *prompt_baton,
+  int retry_limit,
+  apr_pool_t *pool);
+
+  
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/master-passphrase/subversion/include/svn_cmdline.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/svn_cmdline.h?rev=1368622&r1=1368621&r2=1368622&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_cmdline.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_cmdline.h Thu Aug  2 17:50:54 2012
@@ -316,17 +316,19 @@ svn_cmdline_auth_plaintext_passphrase_pr
                                              apr_pool_t *pool);
 
 
-/** An implementation of @c svn_auth__master_passphrase_fetch_t that
- * prompts the user for the master passphrase which protects an
+/** An implementation of @c svn_auth_master_passphrase_prompt_func_t
+ * that prompts the user for the master passphrase which protects an
  * encrypted authentication store.
  *
  * @since New in 1.8.
  */
 svn_error_t *
-svn_cmdline_auth_master_passphrase_prompt(const svn_string_t **secret,
-                                          void *baton, 
-                                          apr_pool_t *result_pool,
-                                          apr_pool_t *scratch_pool);
+svn_cmdline_auth_master_passphrase_prompt(
+  svn_auth_cred_master_passphrase_t **creds_p,
+  void *baton,
+  const char *realmstring,
+  svn_boolean_t may_save,
+  apr_pool_t *scratch_pool);
 
 
 /** Set @a *ab to an authentication baton allocated from @a pool and

Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/auth_store.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/auth_store.h?rev=1368622&r1=1368621&r2=1368622&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/auth_store.h (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/auth_store.h Thu Aug  2 17:50:54 2012
@@ -200,39 +200,60 @@ svn_auth__store_iterate_creds(svn_auth__
 
 /*** Pathetic Encrypted Authentication Store ***/
 
-/* Callback type used to fetch a master passphrase for unlocking an
-   encrypted auth store. */
-typedef svn_error_t *(*svn_auth__master_passphrase_fetch_t)(
-  const svn_string_t **secret,
-  void *baton, 
-  apr_pool_t *result_pool,
-  apr_pool_t *scratch_pool);
-
 /* Set *AUTH_STORE_P to an object which describes the encrypted
    authentication credential store located at AUTH_STORE_PATH.
 
    CRYPTO_CTX is the cryptographic context which the store will use
    for related functionality.
 
-   Use SECRET_FUNC/SECRET_BATON to acquire the master passphrase used
-   to encrypt the sensitive contents of the store.  When creating the
-   store it is registered with the store as-is, but when opening a
-   previously existing store, it is validated against the passphrase
-   self-checking information in the store itself.  Return
-   SVN_ERR_AUTHN_FAILED if the secret provided by SECRET_FUNC does not
-   validate against an existing store's checktext.
+   Use the providers registered with SECRET_AUTH_BATON to acquire the
+   master passphrase used to encrypt the sensitive contents of the
+   store.  When creating the store it is registered with the store
+   as-is, but when opening a previously existing store, it is
+   validated against the passphrase self-checking information in the
+   store itself.  Return SVN_ERR_AUTHN_FAILED if the secret provided
+   by SECRET_FUNC does not validate against an existing store's
+   checktext.
+
+   NOTE: An auth store opened via this interface will error out if
+   asked to "create" its persistent details via
+   svn_auth__store_open(create=TRUE).  Use
+   svn_auth__pathetic_store_create() for that purpose.
 
    ### TODO:  This is expected to be experimental code! ###
 */
 svn_error_t *
 svn_auth__pathetic_store_get(svn_auth__store_t **auth_store_p,
                              const char *auth_store_path,
+                             svn_auth_baton_t *secret_auth_baton,
                              svn_crypto__ctx_t *crypto_ctx,
-                             svn_auth__master_passphrase_fetch_t secret_func,
-                             void *secret_baton,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool);
 
+/* Create an encrypted authentication store at AUTH_STORE_PATH, using
+   CRYPTO_CTX and an initial master passphrase of SECRET.  */
+svn_error_t *
+svn_auth__pathetic_store_create(const char *auth_store_path,
+                                svn_crypto__ctx_t *crypto_ctx,
+                                const svn_string_t *secret,
+                                apr_pool_t *scratch_pool);
+
+/* Re-encrypt the contents of the authentication store located at
+   AUTH_STORE_PATH using NEW_SECRET as the new master passphrase.
+   OLD_SECRET is the current master passphrase.
+
+   CRYPTO_CTX is the cryptographic context which the store will use
+   for related functionality.
+
+   Return SVN_ERR_AUTHN_FAILED if OLD_SECRET does not validate against
+   an existing store's checktext.  */
+svn_error_t *
+svn_auth__pathetic_store_reencrypt(const char *auth_store_path,
+                                   svn_crypto__ctx_t *crypto_ctx,
+                                   const svn_string_t *old_secret,
+                                   const svn_string_t *new_secret,
+                                   apr_pool_t *scratch_pool);
+
 
 
 /*** Runtime-config-based Authentication Store (aka, "the old way") ***/

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=1368622&r1=1368621&r2=1368622&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c Thu Aug  2 17:50:54 2012
@@ -452,6 +452,8 @@ static svn_error_t *
 open_auth_store(svn_auth__store_t **auth_store_p,
                 const char *config_dir,
                 svn_boolean_t use_master_password,
+                svn_boolean_t no_auth_cache,
+                svn_boolean_t non_interactive,
                 svn_cmdline_prompt_baton2_t *pb,
                 apr_pool_t *pool)
 {
@@ -460,16 +462,40 @@ open_auth_store(svn_auth__store_t **auth
   if (use_master_password)
     {
       svn_crypto__ctx_t *crypto_ctx;
-      const char *auth_config_path;
+      const char *auth_config_path, *auth_db_path;
+      svn_auth_baton_t *mp_ab;
+      svn_auth_provider_object_t *provider;
+      apr_array_header_t *mp_providers;
+
+      SVN_ERR(svn_config_get_user_config_path(&auth_config_path, config_dir,
+                                              SVN_CONFIG__AUTH_SUBDIR, pool));
+      auth_db_path = svn_path_join(auth_config_path, "pathetic.db", pool);
+
+      /* Build an authentication baton with the relevant master
+         passphrase providers. */
+      mp_providers = apr_array_make(pool, 1, 
+                                    sizeof(svn_auth_provider_object_t *));
+      if (! non_interactive)
+        {
+          svn_auth_get_master_passphrase_prompt_provider(
+              &provider, svn_cmdline_auth_master_passphrase_prompt,
+              pb, 3, pool);
+          APR_ARRAY_PUSH(mp_providers, svn_auth_provider_object_t *) = provider;
+        }
+      svn_auth_open(&mp_ab, mp_providers, pool);
+
+      if (no_auth_cache)
+        svn_auth_set_parameter(mp_ab, SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
+      if (non_interactive)
+        svn_auth_set_parameter(mp_ab, SVN_AUTH_PARAM_NON_INTERACTIVE, "");
+      if (config_dir)
+        svn_auth_set_parameter(mp_ab, SVN_AUTH_PARAM_CONFIG_DIR, config_dir);
 
       SVN_ERR(svn_config_get_user_config_path(&auth_config_path, config_dir,
                                               SVN_CONFIG__AUTH_SUBDIR, pool));
       SVN_ERR(svn_crypto__context_create(&crypto_ctx, pool));
-      SVN_ERR(svn_auth__pathetic_store_get(
-                  &auth_store,
-                  svn_path_join(auth_config_path, "pathetic.db", pool),
-                  crypto_ctx, svn_cmdline_auth_master_passphrase_prompt,
-                  pb, pool, pool));
+      SVN_ERR(svn_auth__pathetic_store_get(&auth_store, auth_db_path,
+                                           mp_ab, crypto_ctx, pool, pool));
     }
   else
     {
@@ -619,11 +645,6 @@ svn_cmdline_create_auth_baton(svn_auth_b
     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD,
                            auth_password);
 
-  /* Open the appropriate auth store, and cache it in the auth baton. */
-  SVN_ERR(open_auth_store(&auth_store, config_dir, use_master_password,
-                          pb, pool));
-  svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_AUTH_STORE, auth_store);
-
   /* Same with the --non-interactive option. */
   if (non_interactive)
     svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_NON_INTERACTIVE, "");
@@ -661,6 +682,13 @@ svn_cmdline_create_auth_baton(svn_auth_b
                          &svn_cmdline__auth_gnome_keyring_unlock_prompt);
 #endif /* SVN_HAVE_GNOME_KEYRING */
 
+  /* Open the appropriate auth store, and cache it in the auth baton. */
+  SVN_ERR(open_auth_store(&auth_store, config_dir, use_master_password,
+                          (no_auth_cache || ! store_auth_creds_val),
+                          non_interactive, pb, pool));
+  svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_AUTH_STORE, auth_store);
+
+
   return SVN_NO_ERROR;
 }
 

Added: subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c?rev=1368622&view=auto
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c (added)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c Thu Aug  2 17:50:54 2012
@@ -0,0 +1,151 @@
+/*
+ * masterpass_providers.c: providers for SVN_AUTH_CRED_MASTER_PASSPHRASE
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+
+#include <apr_pools.h>
+
+#include "svn_auth.h"
+#include "svn_error.h"
+#include "svn_config.h"
+#include "svn_string.h"
+#include "auth_store.h"
+
+#include "private/svn_auth_private.h"
+
+#include "svn_private_config.h"
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Prompt provider                                                       */
+/*-----------------------------------------------------------------------*/
+
+/* Baton type for master passphrase prompting. */
+typedef struct master_passphrase_prompt_provider_baton_t
+{
+  /* Prompting function/baton pair. */
+  svn_auth_master_passphrase_prompt_func_t prompt_func;
+  void *prompt_baton;
+
+  /* How many times to re-prompt? */
+  int retry_limit;
+
+} master_passphrase_prompt_provider_baton_t;
+
+
+/* Iteration baton. */
+typedef struct master_passphrase_prompt_iter_baton_t
+{
+  /* The original provider baton */
+  master_passphrase_prompt_provider_baton_t *pb;
+
+  /* The original realmstring */
+  const char *realmstring;
+
+  /* How many times have we reprompted? */
+  int retries;
+
+} master_passphrase_prompt_iter_baton_t;
+
+
+static svn_error_t *
+master_passphrase_prompt_first_cred(void **credentials_p,
+                                    void **iter_baton,
+                                    void *provider_baton,
+                                    apr_hash_t *parameters,
+                                    const char *realmstring,
+                                    apr_pool_t *pool)
+{
+  master_passphrase_prompt_provider_baton_t *pb = provider_baton;
+  master_passphrase_prompt_iter_baton_t *ib = apr_pcalloc(pool, sizeof(*ib));
+  const char *no_auth_cache = apr_hash_get(parameters,
+                                           SVN_AUTH_PARAM_NO_AUTH_CACHE,
+                                           APR_HASH_KEY_STRING);
+
+  SVN_ERR(pb->prompt_func((svn_auth_cred_master_passphrase_t **)
+                          credentials_p, pb->prompt_baton, realmstring,
+                          ! no_auth_cache, pool));
+
+  ib->pb = pb;
+  ib->realmstring = apr_pstrdup(pool, realmstring);
+  ib->retries = 0;
+  *iter_baton = ib;
+
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+master_passphrase_prompt_next_cred(void **credentials_p,
+                                   void *iter_baton,
+                                   void *provider_baton,
+                                   apr_hash_t *parameters,
+                                   const char *realmstring,
+                                   apr_pool_t *pool)
+{
+  master_passphrase_prompt_iter_baton_t *ib = iter_baton;
+  const char *no_auth_cache = apr_hash_get(parameters,
+                                           SVN_AUTH_PARAM_NO_AUTH_CACHE,
+                                           APR_HASH_KEY_STRING);
+
+  if ((ib->pb->retry_limit >= 0) && (ib->retries >= ib->pb->retry_limit))
+    {
+      /* Give up and go on to the next provider. */
+      *credentials_p = NULL;
+      return SVN_NO_ERROR;
+    }
+  ib->retries++;
+
+  return ib->pb->prompt_func((svn_auth_cred_master_passphrase_t **)
+                             credentials_p, ib->pb->prompt_baton,
+                             ib->realmstring, ! no_auth_cache, pool);
+}
+
+
+static const svn_auth_provider_t master_passphrase_prompt_provider = {
+  SVN_AUTH_CRED_MASTER_PASSPHRASE,
+  master_passphrase_prompt_first_cred,
+  master_passphrase_prompt_next_cred,
+  NULL
+};
+
+
+void svn_auth_get_master_passphrase_prompt_provider(
+  svn_auth_provider_object_t **provider,
+  svn_auth_master_passphrase_prompt_func_t prompt_func,
+  void *prompt_baton,
+  int retry_limit,
+  apr_pool_t *pool)
+{
+  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+  master_passphrase_prompt_provider_baton_t *pb =
+    apr_palloc(pool, sizeof(*pb));
+
+  pb->prompt_func = prompt_func;
+  pb->prompt_baton = prompt_baton;
+  pb->retry_limit = retry_limit;
+
+  po->vtable = &master_passphrase_prompt_provider;
+  po->provider_baton = pb;
+  *provider = po;
+}

Propchange: subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c
------------------------------------------------------------------------------
    svn:mime-type = text/x-csrc

Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/pathetic_auth_store.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/pathetic_auth_store.c?rev=1368622&r1=1368621&r2=1368622&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/pathetic_auth_store.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/pathetic_auth_store.c Thu Aug  2 17:50:54 2012
@@ -63,10 +63,8 @@ typedef struct pathetic_auth_store_baton
   /* Cryptographic context. */
   svn_crypto__ctx_t *crypto_ctx;
 
-  /* Callback/baton for fetching the master passphrase (aka crypto
-     secret). */
-  svn_auth__master_passphrase_fetch_t secret_func;
-  void *secret_baton;
+  /* Auth baton for the master passphrase ("secret") acquisition system. */
+  svn_auth_baton_t *secret_auth_baton;
 
   /* Crypto secret (may be NULL if not yet provided). */
   const svn_string_t *secret;
@@ -155,6 +153,7 @@ read_auth_store(pathetic_auth_store_bato
    (because there's no configuration directory provided), do nothing.  */
 static svn_error_t *
 write_auth_store(pathetic_auth_store_baton_t *auth_store,
+                 svn_boolean_t create,
                  apr_pool_t *scratch_pool)
 {
   apr_file_t *authfile = NULL;
@@ -162,12 +161,14 @@ write_auth_store(pathetic_auth_store_bat
   apr_hash_t *hash = apr_hash_make(scratch_pool);
   apr_hash_index_t *hi;
   const svn_string_t *str;
+  apr_int32_t open_flags = (APR_WRITE | APR_TRUNCATE | APR_BUFFERED);
 
   SVN_ERR_ASSERT(auth_store->checktext_skel);
 
-  SVN_ERR_W(svn_io_file_open(&authfile, auth_store->path,
-                             (APR_WRITE | APR_CREATE | APR_TRUNCATE
-                              | APR_BUFFERED),
+  if (create)
+    open_flags |= APR_CREATE;
+
+  SVN_ERR_W(svn_io_file_open(&authfile, auth_store->path, open_flags,
                              APR_OS_DEFAULT, scratch_pool),
             _("Unable to open auth file for writing"));
 
@@ -215,6 +216,8 @@ create_auth_store(pathetic_auth_store_ba
   const svn_string_t *ciphertext, *iv, *salt;
   const char *checktext;
 
+  SVN_ERR_ASSERT(auth_store->secret);
+
   SVN_ERR(svn_crypto__generate_secret_checktext(&ciphertext, &iv,
                                                 &salt, &checktext,
                                                 auth_store->crypto_ctx,
@@ -236,7 +239,7 @@ create_auth_store(pathetic_auth_store_ba
                     auth_store->checktext_skel);
 
   auth_store->realmstring_skels = apr_hash_make(auth_store->pool);
-  SVN_ERR(write_auth_store(auth_store, scratch_pool));
+  SVN_ERR(write_auth_store(auth_store, TRUE, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -337,77 +340,108 @@ set_cred_hash(struct pathetic_auth_store
   apr_hash_set(auth_store->realmstring_skels, key,
                APR_HASH_KEY_STRING, realmstring_skel);
 
-  SVN_ERR(write_auth_store(auth_store, scratch_pool));
+  SVN_ERR(write_auth_store(auth_store, FALSE, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
-
-/*** svn_auth__store_t Callback Functions ***/
 
-/* Implements svn_auth__store_cb_open_t. */
 static svn_error_t *
-pathetic_store_open(void *baton,
-                    svn_boolean_t create,
-                    apr_pool_t *scratch_pool)
+acquire_secret(pathetic_auth_store_baton_t *auth_store,
+               svn_boolean_t verify,
+               apr_pool_t *scratch_pool)
 {
-  pathetic_auth_store_baton_t *auth_store = baton;
-  svn_error_t *err;
-  svn_skel_t *cipher_skel, *iv_skel, *salt_skel, *check_skel;
-  svn_boolean_t valid_secret;
+  void *creds;
+  svn_auth_iterstate_t *iterstate;
 
-  SVN_ERR(auth_store->secret_func(&(auth_store->secret),
-                                  auth_store->secret_baton,
-                                  auth_store->pool,
-                                  scratch_pool));
+  if (auth_store->secret)
+    return SVN_NO_ERROR;
 
-  err = read_auth_store(auth_store, scratch_pool);
-  if (err)
+  if (! auth_store->secret_auth_baton)
+    return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+                            _("Can't get master password"));
+
+  SVN_ERR(svn_auth_first_credentials(&creds, &iterstate,
+                                     SVN_AUTH_CRED_MASTER_PASSPHRASE,
+                                     "Pathetic Encrypted Auth Store",
+                                     auth_store->secret_auth_baton,
+                                     scratch_pool));
+  if (!creds)
+    {
+      return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+                              _("Can't get master password"));
+    }
+  while (creds)
     {
-      if (err->apr_err == SVN_ERR_NODE_NOT_FOUND)
+      svn_boolean_t valid_secret;
+      const svn_string_t *passphrase =
+        ((svn_auth_cred_master_passphrase_t *) creds)->passphrase;
+
+      if (verify)
         {
-          if (create)
-            {
-              svn_error_clear(err);
-              return svn_error_trace(create_auth_store(auth_store,
-                                                       scratch_pool));
-            }
-          else
-            {
-              return err;
-            }
+          svn_skel_t *cipher_skel, *iv_skel, *salt_skel, *check_skel;
+
+          SVN_ERR_ASSERT(auth_store->checktext_skel);
+
+          cipher_skel = auth_store->checktext_skel->children;
+          iv_skel = auth_store->checktext_skel->children->next;
+          salt_skel = auth_store->checktext_skel->children->next->next;
+          check_skel = auth_store->checktext_skel->children->next->next->next;
+          
+          SVN_ERR(svn_crypto__verify_secret(
+                      &valid_secret, auth_store->crypto_ctx, passphrase,
+                      svn_string_ncreate(cipher_skel->data,
+                                         cipher_skel->len,
+                                         scratch_pool),
+                      svn_string_ncreate(iv_skel->data,
+                                         iv_skel->len,
+                                         scratch_pool),
+                      svn_string_ncreate(salt_skel->data,
+                                         salt_skel->len,
+                                         scratch_pool),
+                      apr_pstrmemdup(scratch_pool,
+                                     check_skel->data,
+                                     check_skel->len),
+                      scratch_pool));
         }
       else
         {
-          return err;
+          valid_secret = TRUE;
+        }
+
+      if (valid_secret)
+        {
+          auth_store->secret = svn_string_dup(passphrase, auth_store->pool);
+          break;
         }
+
+      SVN_ERR(svn_auth_next_credentials(&creds, iterstate, scratch_pool));
     }
-                            
-  cipher_skel = auth_store->checktext_skel->children;
-  iv_skel     = auth_store->checktext_skel->children->next;
-  salt_skel   = auth_store->checktext_skel->children->next->next;
-  check_skel  = auth_store->checktext_skel->children->next->next->next;
-
-  SVN_ERR(svn_crypto__verify_secret(&valid_secret,
-                                    auth_store->crypto_ctx,
-                                    auth_store->secret,
-                                    svn_string_ncreate(cipher_skel->data,
-                                                       cipher_skel->len,
-                                                       scratch_pool),
-                                    svn_string_ncreate(iv_skel->data,
-                                                       iv_skel->len,
-                                                       scratch_pool),
-                                    svn_string_ncreate(salt_skel->data,
-                                                       salt_skel->len,
-                                                       scratch_pool),
-                                    apr_pstrmemdup(scratch_pool,
-                                                   check_skel->data,
-                                                   check_skel->len),
-                                    scratch_pool));
-  if (! valid_secret)
-    return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
-                            _("Invalid secret; unable to open "
-                              "encrypted store"));
+  if (!creds)
+    {
+      return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+                              _("Invalid master passphrase; unable to open "
+                                "encrypted store"));
+    }
+
+  SVN_ERR(svn_auth_save_credentials(iterstate, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+
+
+/*** svn_auth__store_t Callback Functions ***/
+
+/* Implements svn_auth__store_cb_open_t. */
+static svn_error_t *
+pathetic_store_open(void *baton,
+                    svn_boolean_t create,
+                    apr_pool_t *scratch_pool)
+{
+  pathetic_auth_store_baton_t *auth_store = baton;
+
+  SVN_ERR(read_auth_store(auth_store, scratch_pool));
+  SVN_ERR(acquire_secret(auth_store, TRUE, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -474,16 +508,15 @@ pathetic_store_set_cred_hash(svn_boolean
 svn_error_t *
 svn_auth__pathetic_store_get(svn_auth__store_t **auth_store_p,
                              const char *auth_store_path,
+                             svn_auth_baton_t *secret_auth_baton,
                              svn_crypto__ctx_t *crypto_ctx,
-                             svn_auth__master_passphrase_fetch_t secret_func,
-                             void *secret_baton,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
 {
   svn_auth__store_t *auth_store;
   pathetic_auth_store_baton_t *pathetic_store;
 
-  SVN_ERR_ASSERT(secret_func);
+  SVN_ERR_ASSERT(secret_auth_baton);
 
   if (! svn_crypto__is_available())
     return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
@@ -493,8 +526,7 @@ svn_auth__pathetic_store_get(svn_auth__s
   pathetic_store->pool = result_pool;
   pathetic_store->path = apr_pstrdup(result_pool, auth_store_path);
   pathetic_store->crypto_ctx = crypto_ctx;
-  pathetic_store->secret_func = secret_func;
-  pathetic_store->secret_baton = secret_baton;
+  pathetic_store->secret_auth_baton = secret_auth_baton;
 
   SVN_ERR(svn_auth__store_create(&auth_store, result_pool));
   SVN_ERR(svn_auth__store_set_baton(auth_store, pathetic_store));
@@ -511,3 +543,41 @@ svn_auth__pathetic_store_get(svn_auth__s
 }
 
 
+svn_error_t *
+svn_auth__pathetic_store_create(const char *auth_store_path,
+                                svn_crypto__ctx_t *crypto_ctx,
+                                const svn_string_t *secret,
+                                apr_pool_t *scratch_pool)
+{
+  pathetic_auth_store_baton_t *pathetic_store;
+
+  if (! svn_crypto__is_available())
+    return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                            _("Encrypted auth store feature not available"));
+
+  pathetic_store = apr_pcalloc(scratch_pool, sizeof(*pathetic_store));
+  pathetic_store->pool = scratch_pool;
+  pathetic_store->path = apr_pstrdup(scratch_pool, auth_store_path);
+  pathetic_store->crypto_ctx = crypto_ctx;
+  pathetic_store->secret = secret;
+  
+  SVN_ERR(create_auth_store(pathetic_store, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_auth__pathetic_store_reencrypt(const char *auth_store_path,
+                                   svn_crypto__ctx_t *crypto_ctx,
+                                   const svn_string_t *old_secret,
+                                   const svn_string_t *new_secret,
+                                   apr_pool_t *scratch_pool)
+{
+  if (! svn_crypto__is_available())
+    return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                            _("Encrypted auth store feature not available"));
+
+  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                          _("Feature no worky yet"));
+}

Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/prompt.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/prompt.c?rev=1368622&r1=1368621&r2=1368622&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/prompt.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/prompt.c Thu Aug  2 17:50:54 2012
@@ -498,17 +498,20 @@ svn_cmdline_auth_plaintext_passphrase_pr
 }
 
 
-/* This implements 'svn_auth__master_passphrase_fetch_t'. */
+/* This implements 'svn_auth_master_passphrase_prompt_func_t'. */
 svn_error_t *
-svn_cmdline_auth_master_passphrase_prompt(const svn_string_t **secret,
-                                          void *baton, 
-                                          apr_pool_t *result_pool,
-                                          apr_pool_t *scratch_pool)
+svn_cmdline_auth_master_passphrase_prompt(
+  svn_auth_cred_master_passphrase_t **creds_p,
+  void *baton,
+  const char *realmstring,
+  svn_boolean_t may_save,
+  apr_pool_t *scratch_pool)
 {
   const char *response;
   int response_len;
   svn_cmdline_prompt_baton2_t *pb = baton;
   svn_checksum_t *checksum;
+  svn_auth_cred_master_passphrase_t *creds;
 
   SVN_ERR(prompt(&response, _("Enter master passphrase: "),
                  TRUE, pb, scratch_pool));
@@ -516,9 +519,11 @@ svn_cmdline_auth_master_passphrase_promp
   SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1,
                        response, response_len, scratch_pool));
   memset((void *)response, 0, response_len);
-  *secret = svn_string_ncreate((const char *)checksum->digest,
-                               svn_checksum_size(checksum),
-                               result_pool);
+  creds = apr_pcalloc(scratch_pool, sizeof(*creds));
+  creds->passphrase = svn_string_ncreate((const char *)checksum->digest,
+                                         svn_checksum_size(checksum),
+                                         scratch_pool);
+  *creds_p = creds;
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/master-passphrase/subversion/tests/libsvn_subr/crypto-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/tests/libsvn_subr/crypto-test.c?rev=1368622&r1=1368621&r2=1368622&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/tests/libsvn_subr/crypto-test.c (original)
+++ subversion/branches/master-passphrase/subversion/tests/libsvn_subr/crypto-test.c Thu Aug  2 17:50:54 2012
@@ -78,14 +78,35 @@ encrypt_decrypt(svn_crypto__ctx_t *ctx,
 }
 
 
-/* Implements `svn_auth__master_passphrase_fetch_t' */
+/* Implements `svn_auth_master_passphrase_prompt_func_t' */
 static svn_error_t *
-fetch_secret(const svn_string_t **secret,
+fetch_secret(svn_auth_cred_master_passphrase_t **cred_p,
              void *baton,
-             apr_pool_t *result_pool,
-             apr_pool_t *scratch_pool)
+             const char *realmstring,
+             svn_boolean_t may_save,
+             apr_pool_t *pool)
 {
-  *secret = svn_string_dup(baton, result_pool);
+  svn_auth_cred_master_passphrase_t *cred = apr_pcalloc(pool, sizeof(*cred));
+  cred->passphrase = svn_string_dup(baton, pool);
+  *cred_p = cred;
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+get_master_passphrase_auth_baton(svn_auth_baton_t **auth_baton,
+                                 const svn_string_t *secret,
+                                 apr_pool_t *pool)
+{
+  svn_auth_provider_object_t *provider;
+  apr_array_header_t *mp_providers = apr_array_make(pool, 1, sizeof(provider));
+  
+  /* Build an authentication baton with a single master passphrase provider. */
+  svn_auth_get_master_passphrase_prompt_provider(&provider, fetch_secret,
+                                                 (void *)secret, 0, pool);
+  APR_ARRAY_PUSH(mp_providers, svn_auth_provider_object_t *) = provider;
+  svn_auth_open(auth_baton, mp_providers, pool);
+
   return SVN_NO_ERROR;
 }
 
@@ -101,15 +122,19 @@ create_ephemeral_auth_store(svn_auth__st
                             const svn_string_t *secret,
                             apr_pool_t *pool)
 {
+  svn_auth_baton_t *auth_baton;
+  
   SVN_ERR(svn_io_open_uniquely_named(NULL, auth_store_path, NULL,
                                      "auth_store", NULL,
                                      svn_io_file_del_on_pool_cleanup,
                                      pool, pool));
   SVN_ERR(svn_io_remove_file2(*auth_store_path, TRUE, pool));
+  SVN_ERR(svn_auth__pathetic_store_create(*auth_store_path, crypto_ctx,
+                                          secret, pool));
+  SVN_ERR(get_master_passphrase_auth_baton(&auth_baton, secret, pool));
   SVN_ERR(svn_auth__pathetic_store_get(auth_store_p, *auth_store_path,
-                                       crypto_ctx, fetch_secret, 
-                                       (void *)secret, pool, pool));
-  SVN_ERR(svn_auth__store_open(*auth_store_p, TRUE, pool));
+                                       auth_baton, crypto_ctx, pool, pool));
+  SVN_ERR(svn_auth__store_open(*auth_store_p, FALSE, pool));
   return SVN_NO_ERROR;
 }
 
@@ -218,6 +243,7 @@ test_auth_store_basic(apr_pool_t *pool)
   svn_crypto__ctx_t *ctx;
   svn_auth__store_t *auth_store;
   const char *auth_store_path;
+  svn_auth_baton_t *auth_baton;
   const svn_string_t *secret = svn_string_create("My Secret", pool);
   const svn_string_t *bad_secret = svn_string_create("Not My Secret", pool);
 
@@ -231,16 +257,16 @@ test_auth_store_basic(apr_pool_t *pool)
 
   /* Close and reopen the auth store. */
   SVN_ERR(svn_auth__store_close(auth_store, pool));
-  SVN_ERR(svn_auth__pathetic_store_get(&auth_store, auth_store_path, ctx,
-                                       fetch_secret, (void *)secret,
-                                       pool, pool));
+  SVN_ERR(get_master_passphrase_auth_baton(&auth_baton, secret, pool));
+  SVN_ERR(svn_auth__pathetic_store_get(&auth_store, auth_store_path,
+                                       auth_baton, ctx, pool, pool));
   SVN_ERR(svn_auth__store_open(auth_store, FALSE, pool));
 
   /* Close and reopen the auth store with a bogus secret. */
   SVN_ERR(svn_auth__store_close(auth_store, pool));
-  SVN_ERR(svn_auth__pathetic_store_get(&auth_store, auth_store_path, ctx,
-                                       fetch_secret, (void *)bad_secret,
-                                       pool, pool));
+  SVN_ERR(get_master_passphrase_auth_baton(&auth_baton, bad_secret, pool));
+  SVN_ERR(svn_auth__pathetic_store_get(&auth_store, auth_store_path,
+                                       auth_baton, ctx, pool, pool));
   err = svn_auth__store_open(auth_store, FALSE, pool);
   if (! err)
     return svn_error_create(SVN_ERR_TEST_FAILED, NULL,