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/03/23 19:16:04 UTC
svn commit: r1304538 - in /subversion/branches/master-passphrase/subversion:
include/svn_auth.h libsvn_subr/auth.c libsvn_subr/config_file.c
svn/changepassword-cmd.c svn/cl.h svn/main.c
Author: cmpilato
Date: Fri Mar 23 18:16:04 2012
New Revision: 1304538
URL: http://svn.apache.org/viewvc?rev=1304538&view=rev
Log:
On the 'master-passphrase' branch, add an 'svn changepassword'
subcommand and the beginnings of some functional support thereof.
* subversion/include/svn_auth.h
(SVN_AUTH_CRED_MASTER_PASSPHRASE): New credential type #define.
(svn_auth_cred_master_passphrase_t): New credential type structure.
Currently unused.
(SVN_AUTH_TEMP_USE_FAUX_PASSPHRASE, SVN_AUTH_TEMP_MASTER_PASSPHRASE):
Temporary #defines used while playing with this implementation to
ensure a fixed passphrase is in place.
(svn_auth_master_passphrase_get, svn_auth_master_passphrase_set): Public
functions for getting and setting, respectively, the master passphrase.
(SVN_AUTH_PARAM_DEFAULT_MASTER_PASSPHRASE): New auth baton parameter
key #define.
* subversion/libsvn_subr/config_file.c
(ensure_auth_dirs): Ensure that the 'svn.masterpassphrase' authn
directory gets created.
* subversion/libsvn_subr/auth.c
(AUTHN_MASTER_PASS_KNOWN_TEXT, AUTHN_FAUX_REALMSTRING, AUTHN_CHECKTEXT_KEY,
AUTHN_PASSTYPE_KEY): New local #defines.
(encrypt_text, decrypt_text): New helper functions.
(svn_auth_master_passphrase_get, svn_auth_master_passphrase_set): Public
functions for getting and setting, respectively, the master passphrase.
* subversion/svn/changepassword-cmd.c
New source file, containing svn_cl__changepassword() implementation.
* subversion/svn/cl.h
(svn_cl__changepassword): New function prototype.
* subversion/svn/main.c
(svn_cl__options): Generalize the usage message for --remove a bit.
(svn_cl__cmd_table): Add record for new "changepassword" subcommand.
Added:
subversion/branches/master-passphrase/subversion/svn/changepassword-cmd.c (with props)
Modified:
subversion/branches/master-passphrase/subversion/include/svn_auth.h
subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c
subversion/branches/master-passphrase/subversion/libsvn_subr/config_file.c
subversion/branches/master-passphrase/subversion/svn/cl.h
subversion/branches/master-passphrase/subversion/svn/main.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=1304538&r1=1304537&r2=1304538&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_auth.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_auth.h Fri Mar 23 18:16:04 2012
@@ -340,6 +340,58 @@ typedef struct svn_auth_cred_ssl_server_
} svn_auth_cred_ssl_server_trust_t;
+/** Master passphrase credential type.
+ *
+ * This is a special type of credential used locally only, not as part
+ * of any server-related challenge.
+ *
+ * The following auth parameters are available to the providers:
+ *
+ * - @c SVN_AUTH_PARAM_CONFIG_CATEGORY_SERVERS (@c svn_config_t*)
+ * - @c SVN_AUTH_PARAM_SERVER_GROUP (@c char*)
+ *
+ * The following optional auth parameters are relevant to the providers:
+ *
+ * - @c SVN_AUTH_PARAM_NO_AUTH_CACHE (@c void*)
+ */
+#define SVN_AUTH_CRED_MASTER_PASSPHRASE "svn.masterpassphrase"
+
+typedef struct svn_auth_cred_master_passphrase_t
+{
+ /** Master passphrase */
+ const char *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;
+
+/* Temporary support for a hard-coded master passphrase. (Truth told,
+ cmpilato just doesn't feel like implementing prompting providers
+ and stuff just yet.) */
+#define SVN_AUTH_TEMP_USE_FAUX_PASSPHRASE 1
+#define SVN_AUTH_TEMP_MASTER_PASSPHRASE "mypass"
+
+/* Set *PASSPHRASE to the master passphrase for authentication
+ credentials stored in the runtime configuration associated with
+ AUTH_BATON, allocated from RESULT_POOL. Use SCRATCH_POOL for
+ temporary allocations. */
+svn_error_t *
+svn_auth_master_passphrase_get(const char **passphrase,
+ svn_auth_baton_t *auth_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Set the master passphrase for authentication credentials stored in the
+ runtime configuration associated with AUTH_BATON to NEW_PASSPHRASE
+ (which may be NULL to remove an existing passphrase). Use
+ SCRATCH_POOL for necessary allocation. */
+svn_error_t *
+svn_auth_master_passphrase_set(svn_auth_baton_t *auth_baton,
+ const char *new_passphrase,
+ apr_pool_t *scratch_pool);
+
/** Credential-constructing prompt functions. **/
@@ -577,6 +629,12 @@ svn_auth_get_parameter(svn_auth_baton_t
#define SVN_AUTH_PARAM_DEFAULT_PASSWORD SVN_AUTH_PARAM_PREFIX "password"
/** @} */
+/** @brief Cached value of the master passphrase.
+ * @since New in 1.7.
+ */
+#define SVN_AUTH_PARAM_DEFAULT_MASTER_PASSPHRASE SVN_AUTH_PARAM_PREFIX \
+ "master-passphrase"
+
/** @brief The application doesn't want any providers to prompt
* users. Property value is irrelevant; only property's existence
* matters. */
Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c?rev=1304538&r1=1304537&r2=1304538&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c Fri Mar 23 18:16:04 2012
@@ -33,6 +33,7 @@
#include "svn_config.h"
#include "svn_private_config.h"
#include "svn_dso.h"
+#include "svn_base64.h"
#include "svn_version.h"
/* AN OVERVIEW
@@ -659,3 +660,192 @@ svn_auth_get_platform_specific_client_pr
return SVN_NO_ERROR;
}
+
+
+/*** Master Passphrase ***/
+
+#define AUTHN_MASTER_PASS_KNOWN_TEXT "Subversion"
+#define AUTHN_FAUX_REALMSTRING "localhost.localdomain"
+#define AUTHN_CHECKTEXT_KEY "checktext"
+#define AUTHN_PASSTYPE_KEY "passtype"
+
+
+/* Use SECRET to encrypt TEXT, returning the result (allocated from
+ RESULT_POOL) in *CRYPT_TEXT. Use SCRATCH_POOL for temporary
+ allocations. */
+static svn_error_t *
+encrypt_text(const svn_string_t **crypt_text,
+ const svn_string_t *text,
+ const char *secret,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ /* ### FIXME! This a mindless temporary implementation, offering
+ all the security and privacy of a glass bathroom! ***/
+
+ SVN_ERR_ASSERT(text && text->data);
+ SVN_ERR_ASSERT(secret);
+
+ *crypt_text = svn_base64_encode_string2(svn_string_createf(scratch_pool,
+ "%s+%s",
+ text->data,
+ secret),
+ FALSE, result_pool);
+ return SVN_NO_ERROR;
+}
+
+
+/* Use SECRET to decrypt CRYPT_TEXT, returning the result (allocated
+ from RESULT_POOL) in *TEXT. Use SCRATCH_POOL for temporary
+ allocations. */
+static svn_error_t *
+decrypt_text(const svn_string_t **text,
+ const svn_string_t *crypt_text,
+ const char *secret,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ /* ### FIXME! This a mindless temporary implementation, offering
+ all the security and privacy of a glass bathroom! ***/
+
+ const svn_string_t *work_text;
+ int secret_len, text_len;
+
+ SVN_ERR_ASSERT(crypt_text && crypt_text->data);
+ SVN_ERR_ASSERT(secret);
+
+ secret_len = strlen(secret);
+ work_text = svn_base64_decode_string(crypt_text, scratch_pool);
+ if (work_text->len < (secret_len + 1))
+ return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+ "Invalid master passphrase.");
+ text_len = work_text->len - secret_len - 1;
+ if (work_text->data[text_len] != '+')
+ return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+ "Invalid master passphrase.");
+ if (strcmp(work_text->data + text_len + 1, secret) != 0)
+ return svn_error_create(SVN_ERR_AUTHN_FAILED, NULL,
+ "Invalid master passphrase.");
+ *text = svn_string_ncreate(work_text->data,
+ work_text->len - secret_len - 1,
+ result_pool);
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_auth_master_passphrase_get(const char **passphrase,
+ svn_auth_baton_t *auth_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_t *creds_hash;
+ const svn_string_t *check_text;
+ const char *config_dir = apr_hash_get(auth_baton->parameters,
+ SVN_AUTH_PARAM_CONFIG_DIR,
+ APR_HASH_KEY_STRING);
+#ifdef SVN_AUTH_TEMP_USE_FAUX_PASSPHRASE
+ const char *default_passphrase = SVN_AUTH_TEMP_MASTER_PASSPHRASE;
+#else
+ const char *default_passphrase =
+ apr_hash_get(auth_baton->parameters,
+ SVN_AUTH_PARAM_DEFAULT_MASTER_PASSPHRASE,
+ APR_HASH_KEY_STRING);
+#endif
+
+ /* Read the existing passphrase storage record so we can validate
+ any master passphrase we have or fetch. If there's no check text,
+ we must assume that there's no global master passphrase set, so
+ we'll just return that fact. */
+ SVN_ERR(svn_config_read_auth_data(&creds_hash,
+ SVN_AUTH_CRED_MASTER_PASSPHRASE,
+ AUTHN_FAUX_REALMSTRING, config_dir,
+ scratch_pool));
+ check_text = apr_hash_get(creds_hash, AUTHN_CHECKTEXT_KEY,
+ APR_HASH_KEY_STRING);
+ if (! check_text)
+ {
+ *passphrase = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ /* If there's a default passphrase, verify that it matches the
+ stored known-text. */
+ if (default_passphrase)
+ {
+ const svn_string_t *crypt_text;
+ SVN_ERR(encrypt_text(&crypt_text,
+ svn_string_create(AUTHN_MASTER_PASS_KNOWN_TEXT,
+ scratch_pool),
+ default_passphrase, scratch_pool, scratch_pool));
+ if (svn_string_compare(crypt_text, check_text))
+ {
+ *passphrase = apr_pstrdup(result_pool, default_passphrase);
+ return SVN_NO_ERROR;
+ }
+ default_passphrase = NULL;
+ }
+
+ /* We do not yet know the master passphrase, so we need to consult
+ the providers. */
+ /* ### TODO ### */
+
+ default_passphrase = NULL;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_auth_master_passphrase_set(svn_auth_baton_t *auth_baton,
+ const char *new_passphrase,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_t *creds_hash;
+ const char *config_dir = apr_hash_get(auth_baton->parameters,
+ SVN_AUTH_PARAM_CONFIG_DIR,
+ APR_HASH_KEY_STRING);
+ const char *old_passphrase;
+ const svn_string_t *old_check_text, *new_check_text;
+
+ /* First, fetch the existing passphrase. */
+ SVN_ERR(svn_auth_master_passphrase_get(&old_passphrase, auth_baton,
+ scratch_pool, scratch_pool));
+
+ /* Now, read the existing passphrase storage record and grab the
+ current checkidentify. */
+ SVN_ERR(svn_config_read_auth_data(&creds_hash,
+ SVN_AUTH_CRED_MASTER_PASSPHRASE,
+ AUTHN_FAUX_REALMSTRING, config_dir,
+ scratch_pool));
+ old_check_text = apr_hash_get(creds_hash, AUTHN_CHECKTEXT_KEY,
+ APR_HASH_KEY_STRING);
+
+ SVN_ERR(svn_config_write_auth_data(creds_hash,
+ SVN_AUTH_CRED_MASTER_PASSPHRASE,
+ AUTHN_FAUX_REALMSTRING, config_dir,
+ scratch_pool));
+
+ if (new_passphrase)
+ {
+ /* Encrypt the known text with NEW_PASSPHRASE to form the crypttext,
+ and stuff that into the CREDS_HASH. */
+ SVN_ERR(encrypt_text(&new_check_text,
+ svn_string_create(AUTHN_MASTER_PASS_KNOWN_TEXT,
+ scratch_pool),
+ new_passphrase, scratch_pool, scratch_pool));
+ apr_hash_set(creds_hash, AUTHN_CHECKTEXT_KEY,
+ APR_HASH_KEY_STRING, new_check_text);
+ }
+ else
+ {
+ apr_hash_set(creds_hash, AUTHN_CHECKTEXT_KEY, APR_HASH_KEY_STRING, NULL);
+ }
+
+ /* Re-encrypt all stored credentials in light of NEW_PASSPHRASE. */
+ /* ### TODO ### */
+
+ /* Save credentials to disk. */
+ return svn_config_write_auth_data(creds_hash,
+ SVN_AUTH_CRED_MASTER_PASSPHRASE,
+ AUTHN_FAUX_REALMSTRING, config_dir,
+ scratch_pool);
+}
Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/config_file.c?rev=1304538&r1=1304537&r2=1304538&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/config_file.c Fri Mar 23 18:16:04 2012
@@ -504,6 +504,7 @@ ensure_auth_dirs(const char *path,
/* If a provider exists that wants to store credentials in
~/.subversion, a subdirectory for the cred_kind must exist. */
+ ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_MASTER_PASSPHRASE, pool);
ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SIMPLE, pool);
ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_USERNAME, pool);
ensure_auth_subdir(auth_dir, SVN_AUTH_CRED_SSL_SERVER_TRUST, pool);
Added: subversion/branches/master-passphrase/subversion/svn/changepassword-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/svn/changepassword-cmd.c?rev=1304538&view=auto
==============================================================================
--- subversion/branches/master-passphrase/subversion/svn/changepassword-cmd.c (added)
+++ subversion/branches/master-passphrase/subversion/svn/changepassword-cmd.c Fri Mar 23 18:16:04 2012
@@ -0,0 +1,70 @@
+/*
+ * changepassword-cmd.c -- Associate (or deassociate) a master password
+ * with the local authentication credential cache.
+ *
+ * ====================================================================
+ * 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 "svn_client.h"
+#include "svn_error.h"
+#include "svn_auth.h"
+
+#include "cl.h"
+
+
+
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__changepassword(apr_getopt_t *os,
+ void *baton,
+ apr_pool_t *pool)
+{
+ svn_cl__cmd_baton_t *cmd_baton = baton;
+ svn_cl__opt_state_t *opt_state = cmd_baton->opt_state;
+ svn_auth_baton_t *auth_baton = cmd_baton->ctx->auth_baton;
+ apr_array_header_t *args;
+ const char *new_password = NULL;
+
+ SVN_ERR(svn_opt_parse_all_args(&args, os, pool));
+
+ /* If we're not removing changepasswords, then our only argument should
+ be the new password; otherwise, there should be no arguments. */
+ if (! opt_state->remove)
+ {
+ if (args->nelts < 1)
+ return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
+ if (args->nelts > 1)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
+#ifdef SVN_AUTH_TEMP_USE_FAUX_PASSPHRASE
+ new_password = SVN_AUTH_TEMP_MASTER_PASSPHRASE;
+#else
+ new_password = APR_ARRAY_IDX(args, 0, const char *);
+#endif
+ }
+ else
+ {
+ if (args->nelts > 0)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
+ }
+
+ SVN_ERR(svn_auth_master_passphrase_set(auth_baton, new_password, pool));
+ return SVN_NO_ERROR;
+}
Propchange: subversion/branches/master-passphrase/subversion/svn/changepassword-cmd.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/master-passphrase/subversion/svn/changepassword-cmd.c
------------------------------------------------------------------------------
svn:mime-type = text/x-csrc
Modified: subversion/branches/master-passphrase/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/svn/cl.h?rev=1304538&r1=1304537&r2=1304538&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/svn/cl.h (original)
+++ subversion/branches/master-passphrase/subversion/svn/cl.h Fri Mar 23 18:16:04 2012
@@ -250,6 +250,7 @@ svn_opt_subcommand_t
svn_cl__blame,
svn_cl__cat,
svn_cl__changelist,
+ svn_cl__changepassword,
svn_cl__checkout,
svn_cl__cleanup,
svn_cl__commit,
Modified: subversion/branches/master-passphrase/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/svn/main.c?rev=1304538&r1=1304537&r2=1304538&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/svn/main.c (original)
+++ subversion/branches/master-passphrase/subversion/svn/main.c Fri Mar 23 18:16:04 2012
@@ -283,7 +283,7 @@ const apr_getopt_option_t svn_cl__option
{"limit", 'l', 1, N_("maximum number of log entries")},
{"no-unlock", opt_no_unlock, 0, N_("don't unlock the targets")},
{"summarize", opt_summarize, 0, N_("show a summary of the results")},
- {"remove", opt_remove, 0, N_("remove changelist association")},
+ {"remove", opt_remove, 0, N_("remove an existing association")},
{"changelist", opt_changelist, 1,
N_("operate only on members of changelist ARG")},
{"keep-changelists", opt_keep_changelists, 0,
@@ -445,6 +445,13 @@ const svn_opt_subcommand_desc2_t svn_cl_
" 2. changelist --remove PATH...\n"),
{ 'q', 'R', opt_depth, opt_remove, opt_targets, opt_changelist} },
+ { "changepassword", svn_cl__changepassword, {"chpasswd"}, N_
+ ("Set (or unset) the master password/passphrase used to encrypt locally\n"
+ "cached authentication credentials.\n"
+ "usage: 1. changepassword NEWPASSWORD\n"
+ " 2. changepassword --remove\n"),
+ { 'q', 'R', opt_depth, opt_remove, opt_targets, opt_changelist} },
+
{ "checkout", svn_cl__checkout, {"co"}, N_
("Check out a working copy from a repository.\n"
"usage: checkout URL[@REV]... [PATH]\n"