summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/auth.c')
-rw-r--r--subversion/libsvn_subr/auth.c317
1 files changed, 289 insertions, 28 deletions
diff --git a/subversion/libsvn_subr/auth.c b/subversion/libsvn_subr/auth.c
index 3c874cf..303c41e 100644
--- a/subversion/libsvn_subr/auth.c
+++ b/subversion/libsvn_subr/auth.c
@@ -37,7 +37,6 @@
#include "svn_version.h"
#include "private/svn_auth_private.h"
#include "private/svn_dep_compat.h"
-#include "private/svn_subr_private.h"
#include "auth.h"
@@ -110,10 +109,10 @@ struct svn_auth_baton_t
/* run-time parameters needed by providers. */
apr_hash_t *parameters;
+ apr_hash_t *slave_parameters;
/* run-time credentials cache. */
apr_hash_t *creds_cache;
-
};
/* Abstracted iteration baton */
@@ -126,6 +125,7 @@ struct svn_auth_iterstate_t
const char *realmstring; /* The original realmstring passed in */
const char *cache_key; /* key to use in auth_baton's creds_cache */
svn_auth_baton_t *auth_baton; /* the original auth_baton. */
+ apr_hash_t *parameters;
};
@@ -143,6 +143,7 @@ svn_auth_open(svn_auth_baton_t **auth_baton,
ab = apr_pcalloc(pool, sizeof(*ab));
ab->tables = apr_hash_make(pool);
ab->parameters = apr_hash_make(pool);
+ /* ab->slave_parameters = NULL; */
ab->creds_cache = apr_hash_make(pool);
ab->pool = pool;
@@ -171,20 +172,44 @@ svn_auth_open(svn_auth_baton_t **auth_baton,
*auth_baton = ab;
}
-
+/* Magic pointer value to allow storing 'NULL' in an apr_hash_t */
+static const void *auth_NULL = NULL;
void
svn_auth_set_parameter(svn_auth_baton_t *auth_baton,
const char *name,
const void *value)
{
- svn_hash_sets(auth_baton->parameters, name, value);
+ if (auth_baton)
+ {
+ if (auth_baton->slave_parameters)
+ {
+ if (!value)
+ value = &auth_NULL;
+
+ svn_hash_sets(auth_baton->slave_parameters, name, value);
+ }
+ else
+ svn_hash_sets(auth_baton->parameters, name, value);
+ }
}
const void *
svn_auth_get_parameter(svn_auth_baton_t *auth_baton,
const char *name)
{
+ const void *value;
+ if (!auth_baton)
+ return NULL;
+ else if (!auth_baton->slave_parameters)
+ return svn_hash_gets(auth_baton->parameters, name);
+
+ value = svn_hash_gets(auth_baton->slave_parameters, name);
+
+ if (value)
+ return (value == &auth_NULL) ? NULL
+ : value;
+
return svn_hash_gets(auth_baton->parameters, name);
}
@@ -196,7 +221,7 @@ make_cache_key(const char *cred_kind,
const char *realmstring,
apr_pool_t *pool)
{
- return apr_pstrcat(pool, cred_kind, ":", realmstring, (char *)NULL);
+ return apr_pstrcat(pool, cred_kind, ":", realmstring, SVN_VA_NULL);
}
svn_error_t *
@@ -215,6 +240,11 @@ svn_auth_first_credentials(void **credentials,
svn_boolean_t got_first = FALSE;
svn_auth_iterstate_t *iterstate;
const char *cache_key;
+ apr_hash_t *parameters;
+
+ if (! auth_baton)
+ return svn_error_create(SVN_ERR_AUTHN_NO_PROVIDER, NULL,
+ _("No authentication providers registered"));
/* Get the appropriate table of providers for CRED_KIND. */
table = svn_hash_gets(auth_baton->tables, cred_kind);
@@ -223,6 +253,26 @@ svn_auth_first_credentials(void **credentials,
_("No provider registered for '%s' credentials"),
cred_kind);
+ if (auth_baton->slave_parameters)
+ {
+ apr_hash_index_t *hi;
+ parameters = apr_hash_copy(pool, auth_baton->parameters);
+
+ for (hi = apr_hash_first(pool, auth_baton->slave_parameters);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *value = apr_hash_this_val(hi);
+
+ if (value == &auth_NULL)
+ value = NULL;
+
+ svn_hash_sets(parameters, apr_hash_this_key(hi), value);
+ }
+ }
+ else
+ parameters = auth_baton->parameters;
+
/* First, see if we have cached creds in the auth_baton. */
cache_key = make_cache_key(cred_kind, realmstring, pool);
creds = svn_hash_gets(auth_baton->creds_cache, cache_key);
@@ -240,7 +290,7 @@ svn_auth_first_credentials(void **credentials,
svn_auth_provider_object_t *);
SVN_ERR(provider->vtable->first_credentials(&creds, &iter_baton,
provider->provider_baton,
- auth_baton->parameters,
+ parameters,
realmstring,
auth_baton->pool));
@@ -253,7 +303,9 @@ svn_auth_first_credentials(void **credentials,
}
if (! creds)
- *state = NULL;
+ {
+ *state = NULL;
+ }
else
{
/* Build an abstract iteration state. */
@@ -265,6 +317,7 @@ svn_auth_first_credentials(void **credentials,
iterstate->realmstring = apr_pstrdup(pool, realmstring);
iterstate->cache_key = cache_key;
iterstate->auth_baton = auth_baton;
+ iterstate->parameters = parameters;
*state = iterstate;
/* Put the creds in the cache */
@@ -301,22 +354,26 @@ svn_auth_next_credentials(void **credentials,
{
SVN_ERR(provider->vtable->first_credentials(
&creds, &(state->provider_iter_baton),
- provider->provider_baton, auth_baton->parameters,
+ provider->provider_baton, state->parameters,
state->realmstring, auth_baton->pool));
state->got_first = TRUE;
}
else if (provider->vtable->next_credentials)
{
- SVN_ERR(provider->vtable->next_credentials(
- &creds, state->provider_iter_baton,
- provider->provider_baton, auth_baton->parameters,
- state->realmstring, auth_baton->pool));
+ SVN_ERR(provider->vtable->next_credentials(&creds,
+ state->provider_iter_baton,
+ provider->provider_baton,
+ state->parameters,
+ state->realmstring,
+ auth_baton->pool));
}
if (creds != NULL)
{
/* Put the creds in the cache */
- svn_hash_sets(auth_baton->creds_cache, state->cache_key, creds);
+ svn_hash_sets(auth_baton->creds_cache,
+ apr_pstrdup(auth_baton->pool, state->cache_key),
+ creds);
break;
}
@@ -349,7 +406,7 @@ svn_auth_save_credentials(svn_auth_iterstate_t *state,
return SVN_NO_ERROR;
/* Do not save the creds if SVN_AUTH_PARAM_NO_AUTH_CACHE is set */
- no_auth_cache = svn_hash_gets(auth_baton->parameters,
+ no_auth_cache = svn_hash_gets(state->parameters,
SVN_AUTH_PARAM_NO_AUTH_CACHE);
if (no_auth_cache)
return SVN_NO_ERROR;
@@ -362,7 +419,7 @@ svn_auth_save_credentials(svn_auth_iterstate_t *state,
SVN_ERR(provider->vtable->save_credentials(&save_succeeded,
creds,
provider->provider_baton,
- auth_baton->parameters,
+ state->parameters,
state->realmstring,
pool));
if (save_succeeded)
@@ -376,12 +433,11 @@ svn_auth_save_credentials(svn_auth_iterstate_t *state,
provider = APR_ARRAY_IDX(state->table->providers, i,
svn_auth_provider_object_t *);
if (provider->vtable->save_credentials)
- SVN_ERR(provider->vtable->save_credentials
- (&save_succeeded, creds,
- provider->provider_baton,
- auth_baton->parameters,
- state->realmstring,
- pool));
+ SVN_ERR(provider->vtable->save_credentials(&save_succeeded, creds,
+ provider->provider_baton,
+ state->parameters,
+ state->realmstring,
+ pool));
if (save_succeeded)
break;
@@ -509,19 +565,19 @@ svn_auth_get_platform_specific_provider(svn_auth_provider_object_t **provider,
if (strcmp(provider_name, "gpg_agent") == 0 &&
strcmp(provider_type, "simple") == 0)
{
- svn_auth_get_gpg_agent_simple_provider(provider, pool);
+ svn_auth__get_gpg_agent_simple_provider(provider, pool);
}
#endif
#ifdef SVN_HAVE_KEYCHAIN_SERVICES
if (strcmp(provider_name, "keychain") == 0 &&
strcmp(provider_type, "simple") == 0)
{
- svn_auth_get_keychain_simple_provider(provider, pool);
+ svn_auth__get_keychain_simple_provider(provider, pool);
}
else if (strcmp(provider_name, "keychain") == 0 &&
strcmp(provider_type, "ssl_client_cert_pw") == 0)
{
- svn_auth_get_keychain_ssl_client_cert_pw_provider(provider, pool);
+ svn_auth__get_keychain_ssl_client_cert_pw_provider(provider, pool);
}
#endif
@@ -529,20 +585,20 @@ svn_auth_get_platform_specific_provider(svn_auth_provider_object_t **provider,
if (strcmp(provider_name, "windows") == 0 &&
strcmp(provider_type, "simple") == 0)
{
- svn_auth_get_windows_simple_provider(provider, pool);
+ svn_auth__get_windows_simple_provider(provider, pool);
}
else if (strcmp(provider_name, "windows") == 0 &&
strcmp(provider_type, "ssl_client_cert_pw") == 0)
{
- svn_auth_get_windows_ssl_client_cert_pw_provider(provider, pool);
+ svn_auth__get_windows_ssl_client_cert_pw_provider(provider, pool);
}
else if (strcmp(provider_name, "windows") == 0 &&
strcmp(provider_type, "ssl_server_trust") == 0)
{
- svn_auth_get_windows_ssl_server_trust_provider(provider, pool);
+ svn_auth__get_windows_ssl_server_trust_provider(provider, pool);
}
else if (strcmp(provider_name, "windows") == 0 &&
- strcmp(provider_type, "ssl_server_authority") == 0)
+ strcmp(provider_type, "ssl_server_authority") == 0)
{
svn_auth__get_windows_ssl_server_authority_provider(provider, pool);
}
@@ -656,5 +712,210 @@ svn_auth_get_platform_specific_client_providers(apr_array_header_t **providers,
}
}
+ /* Windows has two providers without a store to allow easy access to
+ SSL servers. We enable these unconditionally.
+ (This behavior was moved here from svn_cmdline_create_auth_baton()) */
+ SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
+ "windows",
+ "ssl_server_trust",
+ pool));
+ SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+
+ /* The windows ssl authority certificate CRYPTOAPI provider. */
+ SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
+ "windows",
+ "ssl_server_authority",
+ pool));
+
+ SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_auth__make_session_auth(svn_auth_baton_t **session_auth_baton,
+ const svn_auth_baton_t *auth_baton,
+ apr_hash_t *config,
+ const char *server_name,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t store_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
+ svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
+ const char *store_plaintext_passwords
+ = SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS;
+ svn_boolean_t store_pp = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP;
+ const char *store_pp_plaintext
+ = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT;
+ svn_config_t *servers = NULL;
+ const char *server_group = NULL;
+
+ struct svn_auth_baton_t *ab;
+
+ ab = apr_pmemdup(result_pool, auth_baton, sizeof(*ab));
+
+ ab->slave_parameters = apr_hash_make(result_pool);
+
+ /* The 'store-passwords' and 'store-auth-creds' parameters used to
+ * live in SVN_CONFIG_CATEGORY_CONFIG. For backward compatibility,
+ * if values for these parameters have already been set by our
+ * callers, we use those values as defaults.
+ *
+ * Note that we can only catch the case where users explicitly set
+ * "store-passwords = no" or 'store-auth-creds = no".
+ *
+ * However, since the default value for both these options is
+ * currently (and has always been) "yes", users won't know
+ * the difference if they set "store-passwords = yes" or
+ * "store-auth-creds = yes" -- they'll get the expected behaviour.
+ */
+
+ if (svn_auth_get_parameter(ab,
+ SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL)
+ store_passwords = FALSE;
+
+ if (svn_auth_get_parameter(ab,
+ SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL)
+ store_auth_creds = FALSE;
+
+ /* All the svn_auth_set_parameter() calls below this not only affect the
+ to be created ra session, but also all the ra sessions that are already
+ use this auth baton!
+
+ Please try to key things based on the realm string instead of this
+ construct.
+ */
+
+ if (config)
+ {
+ /* Grab the 'servers' config. */
+ servers = svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS);
+ if (servers)
+ {
+ /* First, look in the global section. */
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_passwords, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_PASSWORDS,
+ store_passwords));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_plaintext_passwords, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
+ SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_pp, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
+ store_pp));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_pp_plaintext,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
+ SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT));
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_auth_creds, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
+ store_auth_creds));
+
+ /* Find out where we're about to connect to, and
+ * try to pick a server group based on the destination. */
+ server_group = svn_config_find_group(servers, server_name,
+ SVN_CONFIG_SECTION_GROUPS,
+ scratch_pool);
+
+ if (server_group)
+ {
+ /* Override global auth caching parameters with the ones
+ * for the server group, if any. */
+ SVN_ERR(svn_config_get_bool(servers, &store_auth_creds,
+ server_group,
+ SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
+ store_auth_creds));
+
+ SVN_ERR(svn_config_get_bool(servers, &store_passwords,
+ server_group,
+ SVN_CONFIG_OPTION_STORE_PASSWORDS,
+ store_passwords));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_plaintext_passwords, server_group,
+ SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
+ store_plaintext_passwords));
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_pp,
+ server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
+ store_pp));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_pp_plaintext, server_group,
+ SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
+ store_pp_plaintext));
+ }
+ }
+ }
+
+ /* Save auth caching parameters in the auth parameter hash. */
+ if (! store_passwords)
+ svn_auth_set_parameter(ab,
+ SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");
+
+ svn_auth_set_parameter(ab,
+ SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+ store_plaintext_passwords);
+
+ if (! store_pp)
+ svn_auth_set_parameter(ab,
+ SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP,
+ "");
+
+ svn_auth_set_parameter(ab,
+ SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
+ store_pp_plaintext);
+
+ if (! store_auth_creds)
+ svn_auth_set_parameter(ab,
+ SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
+
+ if (server_group)
+ svn_auth_set_parameter(ab,
+ SVN_AUTH_PARAM_SERVER_GROUP,
+ apr_pstrdup(ab->pool, server_group));
+
+ *session_auth_baton = ab;
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+dummy_first_creds(void **credentials,
+ void **iter_baton,
+ void *provider_baton,
+ apr_hash_t *parameters,
+ const char *realmstring,
+ apr_pool_t *pool)
+{
+ *credentials = NULL;
+ *iter_baton = NULL;
+ return SVN_NO_ERROR;
+}
+
+void
+svn_auth__get_dummmy_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ static const svn_auth_provider_t vtable = {
+ SVN_AUTH_CRED_SIMPLE,
+ dummy_first_creds,
+ NULL, NULL
+ };
+
+ svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+
+ po->vtable = &vtable;
+ *provider = po;
+}