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,