You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/02/07 18:29:44 UTC
svn commit: r1443615 - in /subversion/trunk/subversion: include/svn_auth.h
libsvn_subr/auth.c libsvn_subr/auth.h libsvn_subr/config_auth.c
libsvn_subr/simple_providers.c tests/libsvn_subr/auth-test.c
Author: rhuijben
Date: Thu Feb 7 17:29:44 2013
New Revision: 1443615
URL: http://svn.apache.org/viewvc?rev=1443615&view=rev
Log:
Resolve issue #2775, by providing an api that allows removing cached
credentials for our api users.
As our credentials are keyed by 'realm' and the exact format
is provider specific I added a simple iterator over the cached
credentials, so a client can provide a UI on top, or simply guess
which ones to delete by checking if they contain a specific url.
* subversion/include/svn_auth.h
(svn_auth_cleanup_callback): New typedef.
(svn_auth_cleanup_walk): New function.
* subversion/libsvn_subr/auth.c
(includes): Add auth.h
(svn_auth_cleanup_walk): New function.
* subversion/libsvn_subr/auth.h
(svn_auth__file_path): New function.
(svn_auth__simple_cleanup_walk): New function.
* subversion/libsvn_subr/config_auth.c
(auth_file_path): Rename to ...
(svn_auth__file_path): ... this and make library public.
(svn_config_read_auth_data): Update caller.
(svn_config_write_auth_data): Update caller.
* subversion/libsvn_subr/simple_providers.c
(includes): Add several.
(svn_auth__simple_cleanup_walk): New function.
* subversion/tests/libsvn_subr/auth-test.c
(includes): Add svn_auth_private.h.
(cleanup_callback): New function.
(test_auth_clear): Extend to verify the credential is really gone.
Added:
subversion/trunk/subversion/libsvn_subr/auth.h (with props)
Modified:
subversion/trunk/subversion/include/svn_auth.h
subversion/trunk/subversion/libsvn_subr/auth.c
subversion/trunk/subversion/libsvn_subr/config_auth.c
subversion/trunk/subversion/libsvn_subr/simple_providers.c
subversion/trunk/subversion/tests/libsvn_subr/auth-test.c
Modified: subversion/trunk/subversion/include/svn_auth.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_auth.h?rev=1443615&r1=1443614&r2=1443615&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_auth.h (original)
+++ subversion/trunk/subversion/include/svn_auth.h Thu Feb 7 17:29:44 2013
@@ -775,6 +775,39 @@ svn_auth_get_simple_provider2(
void *prompt_baton,
apr_pool_t *pool);
+/** Callback for svn_auth_cleanup_walk.
+ *
+ * Called for each credential to allow selectively removing credentials.
+ *
+ * @a cred_kind and @realm specify the key of the credential (see
+ * svn_auth_first_credentials()).
+ *
+ * @a provider specifies which provider currently holds the credential.
+ *
+ * Before returning set @a *delete_cred to TRUE to remove the credential from
+ * the cache.
+ *
+ * @since New in 1.8.
+ */
+typedef svn_error_t * (*svn_auth_cleanup_callback)(svn_boolean_t *delete_cred,
+ void *cleanup_baton,
+ const char *cred_kind,
+ const char *realmstring,
+ const char *provider,
+ apr_pool_t *scratch_pool);
+
+/** Call @a cleanup with information describing each currently cached
+ * credential (in providers that support iterating). If the callback
+ * confirms that the credential should be deleted, delete it.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_auth_cleanup_walk(svn_auth_baton_t *auth_baton,
+ svn_auth_cleanup_callback cleanup,
+ void *cleanup_baton,
+ apr_pool_t *scratch_pool);
+
/** Like svn_auth_get_simple_provider2, but without the ability to
* call the svn_auth_plaintext_prompt_func_t callback, and the provider
* always assumes that it is allowed to store the password in plaintext.
Modified: subversion/trunk/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/auth.c?rev=1443615&r1=1443614&r2=1443615&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/auth.c (original)
+++ subversion/trunk/subversion/libsvn_subr/auth.c Thu Feb 7 17:29:44 2013
@@ -35,6 +35,8 @@
#include "svn_dso.h"
#include "svn_version.h"
+#include "auth.h"
+
/* AN OVERVIEW
===========
@@ -619,3 +621,20 @@ svn_auth_get_platform_specific_client_pr
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_auth_cleanup_walk(svn_auth_baton_t *baton,
+ svn_auth_cleanup_callback cleanup,
+ void *cleanup_baton,
+ apr_pool_t *scratch_pool)
+{
+
+ if (apr_hash_get(baton->tables, SVN_AUTH_CRED_SIMPLE, APR_HASH_KEY_STRING))
+ {
+ SVN_ERR(svn_auth__simple_cleanup_walk(baton, cleanup, cleanup_baton,
+ baton->creds_cache, scratch_pool));
+ }
+ /* ### Maybe add support for other providers? */
+
+ return SVN_NO_ERROR;
+}
Added: subversion/trunk/subversion/libsvn_subr/auth.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/auth.h?rev=1443615&view=auto
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/auth.h (added)
+++ subversion/trunk/subversion/libsvn_subr/auth.h Thu Feb 7 17:29:44 2013
@@ -0,0 +1,47 @@
+/*
+ * auth.h : shared stuff internal to the subr library.
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ */
+
+#ifndef SVN_SUBR_AUTH_H
+#define SVN_SUBR_AUTH_H
+
+/* Helper for svn_config_{read|write}_auth_data. Return a path to a
+ file within ~/.subversion/auth/ that holds CRED_KIND credentials
+ within REALMSTRING. If no path is available *PATH will be set to
+ NULL. */
+svn_error_t *
+svn_auth__file_path(const char **path,
+ const char *cred_kind,
+ const char *realmstring,
+ const char *config_dir,
+ apr_pool_t *pool);
+
+/* Implementation of svn_auth_cleanup_walk() for the "simple" provider */
+svn_error_t *
+svn_auth__simple_cleanup_walk(svn_auth_baton_t *baton,
+ svn_auth_cleanup_callback cleanup,
+ void *cleanup_baton,
+ apr_hash_t *creds_cache,
+ apr_pool_t *scratch_pool);
+
+
+#endif
Propchange: subversion/trunk/subversion/libsvn_subr/auth.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/trunk/subversion/libsvn_subr/config_auth.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/config_auth.c?rev=1443615&r1=1443614&r2=1443615&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/config_auth.c (original)
+++ subversion/trunk/subversion/libsvn_subr/config_auth.c Thu Feb 7 17:29:44 2013
@@ -35,12 +35,12 @@
file within ~/.subversion/auth/ that holds CRED_KIND credentials
within REALMSTRING. If no path is available *PATH will be set to
NULL. */
-static svn_error_t *
-auth_file_path(const char **path,
- const char *cred_kind,
- const char *realmstring,
- const char *config_dir,
- apr_pool_t *pool)
+svn_error_t *
+svn_auth__file_path(const char **path,
+ const char *cred_kind,
+ const char *realmstring,
+ const char *config_dir,
+ apr_pool_t *pool)
{
const char *authdir_path, *hexname;
svn_checksum_t *checksum;
@@ -81,8 +81,8 @@ svn_config_read_auth_data(apr_hash_t **h
*hash = NULL;
- SVN_ERR(auth_file_path(&auth_path, cred_kind, realmstring, config_dir,
- pool));
+ SVN_ERR(svn_auth__file_path(&auth_path, cred_kind, realmstring, config_dir,
+ pool));
if (! auth_path)
return SVN_NO_ERROR;
@@ -118,8 +118,8 @@ svn_config_write_auth_data(apr_hash_t *h
svn_stream_t *stream;
const char *auth_path;
- SVN_ERR(auth_file_path(&auth_path, cred_kind, realmstring, config_dir,
- pool));
+ SVN_ERR(svn_auth__file_path(&auth_path, cred_kind, realmstring, config_dir,
+ pool));
if (! auth_path)
return svn_error_create(SVN_ERR_NO_AUTH_FILE_PATH, NULL,
_("Unable to locate auth file"));
Modified: subversion/trunk/subversion/libsvn_subr/simple_providers.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/simple_providers.c?rev=1443615&r1=1443614&r2=1443615&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/simple_providers.c (original)
+++ subversion/trunk/subversion/libsvn_subr/simple_providers.c Thu Feb 7 17:29:44 2013
@@ -29,6 +29,9 @@
#include <apr_pools.h>
#include "svn_auth.h"
+#include "svn_dirent_uri.h"
+#include "svn_hash.h"
+#include "svn_pools.h"
#include "svn_error.h"
#include "svn_utf.h"
#include "svn_config.h"
@@ -37,6 +40,8 @@
#include "private/svn_auth_private.h"
#include "svn_private_config.h"
+
+#include "auth.h"
/*-----------------------------------------------------------------------*/
/* File provider */
@@ -520,6 +525,135 @@ simple_save_creds(svn_boolean_t *saved,
pool);
}
+svn_error_t *
+svn_auth__simple_cleanup_walk(svn_auth_baton_t *baton,
+ svn_auth_cleanup_callback cleanup,
+ void *cleanup_baton,
+ apr_hash_t *creds_cache,
+ apr_pool_t *scratch_pool)
+{
+ const char *config_dir;
+ svn_boolean_t no_auth_cache;
+ int i;
+ apr_pool_t *iterpool;
+
+ const char *cred_kinds[] =
+ {
+ SVN_AUTH_CRED_SIMPLE,
+ SVN_AUTH_CRED_USERNAME,
+ SVN_AUTH_CRED_SSL_CLIENT_CERT,
+ SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
+ SVN_AUTH_CRED_SSL_SERVER_TRUST,
+ NULL
+ };
+
+ config_dir = svn_auth_get_parameter(baton, SVN_AUTH_PARAM_CONFIG_DIR);
+ no_auth_cache = (svn_auth_get_parameter(baton, SVN_AUTH_PARAM_NO_AUTH_CACHE)
+ != NULL);
+
+ if ((! config_dir) || no_auth_cache)
+ {
+ /* Can't locate the cache to clear */
+ return SVN_NO_ERROR;
+ }
+
+ iterpool = svn_pool_create(scratch_pool);
+ for (i = 0; cred_kinds[i]; i++)
+ {
+ const char *item_path;
+ const char *dir_path;
+ apr_hash_t *nodes;
+ svn_error_t *err;
+ apr_pool_t *itempool;
+ apr_hash_index_t *hi;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_auth__file_path(&item_path, cred_kinds[i], "!", config_dir,
+ iterpool));
+
+ dir_path = svn_dirent_dirname(item_path, iterpool);
+
+ err = svn_io_get_dirents3(&nodes, dir_path, TRUE, iterpool, iterpool);
+
+ if (err)
+ {
+ if (!APR_STATUS_IS_ENOENT(err->apr_err)
+ && !SVN__APR_STATUS_IS_ENOTDIR(err->apr_err))
+ return svn_error_trace(err);
+
+ svn_error_clear(err);
+ continue;
+ }
+
+ itempool = svn_pool_create(iterpool);
+ for (hi = apr_hash_first(iterpool, nodes); hi; hi = apr_hash_next(hi))
+ {
+ svn_io_dirent2_t *dirent = svn__apr_hash_index_val(hi);
+ const char *item_path;
+ svn_error_t *err;
+ svn_stream_t *stream;
+ apr_hash_t *file_data;
+
+ if (dirent->kind != svn_node_file)
+ continue;
+
+ svn_pool_clear(itempool);
+
+ item_path = svn_dirent_join(dir_path, svn__apr_hash_index_key(hi),
+ itempool);
+
+ err = svn_stream_open_readonly(&stream, item_path, itempool, itempool);
+ if (err)
+ {
+ /* Ignore this file. There are no credentials in it anyway */
+ svn_error_clear(err);
+ continue;
+ }
+
+ file_data = apr_hash_make(itempool);
+ err = svn_hash_read2(file_data, stream, SVN_HASH_TERMINATOR, itempool);
+ err = svn_error_compose_create(err, svn_stream_close(stream));
+ if (err)
+ {
+ /* Ignore this file. There are no credentials in it anyway */
+ svn_error_clear(err);
+ continue;
+ }
+
+ {
+ const svn_string_t *realm = svn_hash_gets(file_data, SVN_CONFIG_REALMSTRING_KEY);
+ svn_boolean_t delete_file = FALSE;
+
+ if (! realm)
+ continue; /* Not an auth file */
+
+ SVN_ERR(cleanup(&delete_file, cleanup_baton, cred_kinds[i], realm->data,
+ SVN_AUTH_CRED_SIMPLE, itempool));
+
+ if (delete_file)
+ {
+ /* Delete from the credential hash */
+ const char *cache_key = apr_pstrcat(itempool,
+ cred_kinds[0],
+ ":",
+ realm->data,
+ (char *)NULL);
+
+ svn_hash_sets(creds_cache, cache_key, NULL);
+
+ /* And the file on disk */
+ SVN_ERR(svn_io_remove_file2(item_path, TRUE, itempool));
+ }
+ }
+ }
+ }
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
+
static const svn_auth_provider_t simple_provider = {
SVN_AUTH_CRED_SIMPLE,
simple_first_creds,
@@ -721,7 +855,6 @@ simple_prompt_next_creds(void **credenti
! no_auth_cache, pool);
}
-
static const svn_auth_provider_t simple_prompt_provider = {
SVN_AUTH_CRED_SIMPLE,
simple_prompt_first_creds,
Modified: subversion/trunk/subversion/tests/libsvn_subr/auth-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/auth-test.c?rev=1443615&r1=1443614&r2=1443615&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/auth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/auth-test.c Thu Feb 7 17:29:44 2013
@@ -26,6 +26,7 @@
#include "svn_private_config.h"
#include "../svn_test.h"
+#include "private/svn_auth_private.h"
static svn_error_t *
test_platform_specific_auth_providers(apr_pool_t *pool)
@@ -207,6 +208,26 @@ test_platform_specific_auth_providers(ap
return SVN_NO_ERROR;
}
+/* Helper for test_auth_clear(). Implements svn_auth_cleanup_callback */
+static svn_error_t *
+cleanup_callback(svn_boolean_t *delete_cred,
+ void *cleanup_baton,
+ const char *cred_kind,
+ const char *realmstring,
+ const char *provider,
+ apr_pool_t *scratch_pool)
+{
+ if (!strcmp(provider, SVN_AUTH__SIMPLE_PASSWORD_TYPE))
+ return SVN_NO_ERROR;
+
+ SVN_TEST_ASSERT(! strcmp(cred_kind, SVN_AUTH_CRED_SIMPLE));
+ SVN_TEST_ASSERT(! strcmp(realmstring, "<http://my.host> My realm"));
+
+ *delete_cred = TRUE;
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
test_auth_clear(apr_pool_t *pool)
{
@@ -255,9 +276,35 @@ test_auth_clear(apr_pool_t *pool)
SVN_ERR(svn_auth_save_credentials(state, pool));
/* Ok, and now we try to remove the credentials */
+ svn_auth_set_parameter(baton, SVN_AUTH_PARAM_DEFAULT_USERNAME, NULL);
+ svn_auth_set_parameter(baton, SVN_AUTH_PARAM_DEFAULT_PASSWORD, NULL);
+
+ /* Are they still in the baton? */
+ SVN_ERR(svn_auth_first_credentials(&credentials,
+ &state,
+ SVN_AUTH_CRED_SIMPLE,
+ "<http://my.host> My realm",
+ baton,
+ pool));
+
+ SVN_TEST_ASSERT(credentials);
+ creds = credentials;
+ SVN_TEST_ASSERT(! strcmp(creds->username, "jrandom"));
+ SVN_TEST_ASSERT(creds->may_save);
+
+
+ SVN_ERR(svn_auth_cleanup_walk(baton,
+ cleanup_callback, NULL,
+ pool));
- /* ### TODO: Implement to resolve issue #2775 */
+ SVN_ERR(svn_auth_first_credentials(&credentials,
+ &state,
+ SVN_AUTH_CRED_SIMPLE,
+ "<http://my.host> My realm",
+ baton,
+ pool));
+ SVN_TEST_ASSERT(! credentials);
return SVN_NO_ERROR;
}
@@ -270,7 +317,13 @@ struct svn_test_descriptor_t test_funcs[
SVN_TEST_NULL,
SVN_TEST_PASS2(test_platform_specific_auth_providers,
"test retrieving platform-specific auth providers"),
+#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
SVN_TEST_PASS2(test_auth_clear,
"test svn_auth_clear()"),
+#else
+ SVN_TEST_WIMP(test_auth_clear,
+ "test svn_auth_clear()",
+ "Needs testing with SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE"),
+#endif
SVN_TEST_NULL
};