diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
commit | cf46733632c7279a9fd0fe6ce26f9185a4ae82a9 (patch) | |
tree | da27775a2161723ef342e91af41a8b51fedef405 /subversion/libsvn_subr/auth.c | |
parent | bb0ef45f7c46b0ae221b26265ef98a768c33f820 (diff) | |
download | subversion-tarball-master.tar.gz |
subversion-1.9.7HEADsubversion-1.9.7master
Diffstat (limited to 'subversion/libsvn_subr/auth.c')
-rw-r--r-- | subversion/libsvn_subr/auth.c | 317 |
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; +} |