1251881Speter/* 2251881Speter * auth.c: authentication support functions for Subversion 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter#include <apr_pools.h> 26251881Speter#include <apr_tables.h> 27251881Speter#include <apr_strings.h> 28251881Speter 29251881Speter#include "svn_hash.h" 30251881Speter#include "svn_types.h" 31251881Speter#include "svn_string.h" 32251881Speter#include "svn_error.h" 33251881Speter#include "svn_auth.h" 34251881Speter#include "svn_config.h" 35251881Speter#include "svn_private_config.h" 36251881Speter#include "svn_dso.h" 37251881Speter#include "svn_version.h" 38251881Speter#include "private/svn_dep_compat.h" 39251881Speter 40251881Speter#include "auth.h" 41251881Speter 42251881Speter/* AN OVERVIEW 43251881Speter =========== 44251881Speter 45251881Speter A good way to think of this machinery is as a set of tables. 46251881Speter 47251881Speter - Each type of credentials selects a single table. 48251881Speter 49251881Speter - In a given table, each row is a 'provider' capable of returning 50251881Speter the same type of credentials. Each column represents a 51251881Speter provider's repeated attempts to provide credentials. 52251881Speter 53251881Speter 54251881Speter Fetching Credentials from Providers 55251881Speter ----------------------------------- 56251881Speter 57251881Speter When the caller asks for a particular type of credentials, the 58251881Speter machinery in this file walks over the appropriate table. It starts 59251881Speter with the first provider (first row), and calls first_credentials() 60251881Speter to get the first set of credentials (first column). If the caller 61251881Speter is unhappy with the credentials, then each subsequent call to 62251881Speter next_credentials() traverses the row from left to right. If the 63251881Speter provider returns error at any point, then we go to the next provider 64251881Speter (row). We continue this way until every provider fails, or 65251881Speter until the client is happy with the returned credentials. 66251881Speter 67251881Speter Note that the caller cannot see the table traversal, and thus has 68251881Speter no idea when we switch providers. 69251881Speter 70251881Speter 71251881Speter Storing Credentials with Providers 72251881Speter ---------------------------------- 73251881Speter 74251881Speter When the server has validated a set of credentials, and when 75251881Speter credential caching is enabled, we have the chance to store those 76251881Speter credentials for later use. The provider which provided the working 77251881Speter credentials is the first one given the opportunity to (re)cache 78251881Speter those credentials. Its save_credentials() function is invoked with 79251881Speter the working credentials. If that provider reports that it 80251881Speter successfully stored the credentials, we're done. Otherwise, we 81251881Speter walk the providers (rows) for that type of credentials in order 82251881Speter from the top of the table, allowing each in turn the opportunity to 83251881Speter store the credentials. When one reports that it has done so 84251881Speter successfully -- or when we run out of providers (rows) to try -- 85251881Speter the table walk ends. 86251881Speter*/ 87251881Speter 88251881Speter 89251881Speter 90251881Speter/* This effectively defines a single table. Every provider in this 91251881Speter array returns the same kind of credentials. */ 92251881Spetertypedef struct provider_set_t 93251881Speter{ 94251881Speter /* ordered array of svn_auth_provider_object_t */ 95251881Speter apr_array_header_t *providers; 96251881Speter 97251881Speter} provider_set_t; 98251881Speter 99251881Speter 100251881Speter/* The main auth baton. */ 101251881Speterstruct svn_auth_baton_t 102251881Speter{ 103251881Speter /* a collection of tables. maps cred_kind -> provider_set */ 104251881Speter apr_hash_t *tables; 105251881Speter 106251881Speter /* the pool I'm allocated in. */ 107251881Speter apr_pool_t *pool; 108251881Speter 109251881Speter /* run-time parameters needed by providers. */ 110251881Speter apr_hash_t *parameters; 111251881Speter 112251881Speter /* run-time credentials cache. */ 113251881Speter apr_hash_t *creds_cache; 114251881Speter 115251881Speter}; 116251881Speter 117251881Speter/* Abstracted iteration baton */ 118251881Speterstruct svn_auth_iterstate_t 119251881Speter{ 120251881Speter provider_set_t *table; /* the table being searched */ 121251881Speter int provider_idx; /* the current provider (row) */ 122251881Speter svn_boolean_t got_first; /* did we get the provider's first creds? */ 123251881Speter void *provider_iter_baton; /* the provider's own iteration context */ 124251881Speter const char *realmstring; /* The original realmstring passed in */ 125251881Speter const char *cache_key; /* key to use in auth_baton's creds_cache */ 126251881Speter svn_auth_baton_t *auth_baton; /* the original auth_baton. */ 127251881Speter}; 128251881Speter 129251881Speter 130251881Speter 131251881Spetervoid 132251881Spetersvn_auth_open(svn_auth_baton_t **auth_baton, 133251881Speter const apr_array_header_t *providers, 134251881Speter apr_pool_t *pool) 135251881Speter{ 136251881Speter svn_auth_baton_t *ab; 137251881Speter svn_auth_provider_object_t *provider; 138251881Speter int i; 139251881Speter 140251881Speter /* Build the auth_baton. */ 141251881Speter ab = apr_pcalloc(pool, sizeof(*ab)); 142251881Speter ab->tables = apr_hash_make(pool); 143251881Speter ab->parameters = apr_hash_make(pool); 144251881Speter ab->creds_cache = apr_hash_make(pool); 145251881Speter ab->pool = pool; 146251881Speter 147251881Speter /* Register each provider in order. Providers of different 148251881Speter credentials will be automatically sorted into different tables by 149251881Speter register_provider(). */ 150251881Speter for (i = 0; i < providers->nelts; i++) 151251881Speter { 152251881Speter provider_set_t *table; 153251881Speter provider = APR_ARRAY_IDX(providers, i, svn_auth_provider_object_t *); 154251881Speter 155251881Speter /* Add it to the appropriate table in the auth_baton */ 156251881Speter table = svn_hash_gets(ab->tables, provider->vtable->cred_kind); 157251881Speter if (! table) 158251881Speter { 159251881Speter table = apr_pcalloc(pool, sizeof(*table)); 160251881Speter table->providers 161251881Speter = apr_array_make(pool, 1, sizeof(svn_auth_provider_object_t *)); 162251881Speter 163251881Speter svn_hash_sets(ab->tables, provider->vtable->cred_kind, table); 164251881Speter } 165251881Speter APR_ARRAY_PUSH(table->providers, svn_auth_provider_object_t *) 166251881Speter = provider; 167251881Speter } 168251881Speter 169251881Speter *auth_baton = ab; 170251881Speter} 171251881Speter 172251881Speter 173251881Speter 174251881Spetervoid 175251881Spetersvn_auth_set_parameter(svn_auth_baton_t *auth_baton, 176251881Speter const char *name, 177251881Speter const void *value) 178251881Speter{ 179251881Speter svn_hash_sets(auth_baton->parameters, name, value); 180251881Speter} 181251881Speter 182251881Speterconst void * 183251881Spetersvn_auth_get_parameter(svn_auth_baton_t *auth_baton, 184251881Speter const char *name) 185251881Speter{ 186251881Speter return svn_hash_gets(auth_baton->parameters, name); 187251881Speter} 188251881Speter 189251881Speter 190251881Speter/* Return the key used to address the in-memory cache of auth 191251881Speter credentials of type CRED_KIND and associated with REALMSTRING. */ 192251881Speterstatic const char * 193251881Spetermake_cache_key(const char *cred_kind, 194251881Speter const char *realmstring, 195251881Speter apr_pool_t *pool) 196251881Speter{ 197251881Speter return apr_pstrcat(pool, cred_kind, ":", realmstring, (char *)NULL); 198251881Speter} 199251881Speter 200251881Spetersvn_error_t * 201251881Spetersvn_auth_first_credentials(void **credentials, 202251881Speter svn_auth_iterstate_t **state, 203251881Speter const char *cred_kind, 204251881Speter const char *realmstring, 205251881Speter svn_auth_baton_t *auth_baton, 206251881Speter apr_pool_t *pool) 207251881Speter{ 208251881Speter int i = 0; 209251881Speter provider_set_t *table; 210251881Speter svn_auth_provider_object_t *provider = NULL; 211251881Speter void *creds = NULL; 212251881Speter void *iter_baton = NULL; 213251881Speter svn_boolean_t got_first = FALSE; 214251881Speter svn_auth_iterstate_t *iterstate; 215251881Speter const char *cache_key; 216251881Speter 217251881Speter /* Get the appropriate table of providers for CRED_KIND. */ 218251881Speter table = svn_hash_gets(auth_baton->tables, cred_kind); 219251881Speter if (! table) 220251881Speter return svn_error_createf(SVN_ERR_AUTHN_NO_PROVIDER, NULL, 221251881Speter _("No provider registered for '%s' credentials"), 222251881Speter cred_kind); 223251881Speter 224251881Speter /* First, see if we have cached creds in the auth_baton. */ 225251881Speter cache_key = make_cache_key(cred_kind, realmstring, pool); 226251881Speter creds = svn_hash_gets(auth_baton->creds_cache, cache_key); 227251881Speter if (creds) 228251881Speter { 229251881Speter got_first = FALSE; 230251881Speter } 231251881Speter else 232251881Speter /* If not, find a provider that can give "first" credentials. */ 233251881Speter { 234251881Speter /* Find a provider that can give "first" credentials. */ 235251881Speter for (i = 0; i < table->providers->nelts; i++) 236251881Speter { 237251881Speter provider = APR_ARRAY_IDX(table->providers, i, 238251881Speter svn_auth_provider_object_t *); 239251881Speter SVN_ERR(provider->vtable->first_credentials(&creds, &iter_baton, 240251881Speter provider->provider_baton, 241251881Speter auth_baton->parameters, 242251881Speter realmstring, 243251881Speter auth_baton->pool)); 244251881Speter 245251881Speter if (creds != NULL) 246251881Speter { 247251881Speter got_first = TRUE; 248251881Speter break; 249251881Speter } 250251881Speter } 251251881Speter } 252251881Speter 253251881Speter if (! creds) 254251881Speter *state = NULL; 255251881Speter else 256251881Speter { 257251881Speter /* Build an abstract iteration state. */ 258251881Speter iterstate = apr_pcalloc(pool, sizeof(*iterstate)); 259251881Speter iterstate->table = table; 260251881Speter iterstate->provider_idx = i; 261251881Speter iterstate->got_first = got_first; 262251881Speter iterstate->provider_iter_baton = iter_baton; 263251881Speter iterstate->realmstring = apr_pstrdup(pool, realmstring); 264251881Speter iterstate->cache_key = cache_key; 265251881Speter iterstate->auth_baton = auth_baton; 266251881Speter *state = iterstate; 267251881Speter 268251881Speter /* Put the creds in the cache */ 269251881Speter svn_hash_sets(auth_baton->creds_cache, 270251881Speter apr_pstrdup(auth_baton->pool, cache_key), 271251881Speter creds); 272251881Speter } 273251881Speter 274251881Speter *credentials = creds; 275251881Speter 276251881Speter return SVN_NO_ERROR; 277251881Speter} 278251881Speter 279251881Speter 280251881Spetersvn_error_t * 281251881Spetersvn_auth_next_credentials(void **credentials, 282251881Speter svn_auth_iterstate_t *state, 283251881Speter apr_pool_t *pool) 284251881Speter{ 285251881Speter svn_auth_baton_t *auth_baton = state->auth_baton; 286251881Speter svn_auth_provider_object_t *provider; 287251881Speter provider_set_t *table = state->table; 288251881Speter void *creds = NULL; 289251881Speter 290251881Speter /* Continue traversing the table from where we left off. */ 291251881Speter for (/* no init */; 292251881Speter state->provider_idx < table->providers->nelts; 293251881Speter state->provider_idx++) 294251881Speter { 295251881Speter provider = APR_ARRAY_IDX(table->providers, 296251881Speter state->provider_idx, 297251881Speter svn_auth_provider_object_t *); 298251881Speter if (! state->got_first) 299251881Speter { 300251881Speter SVN_ERR(provider->vtable->first_credentials( 301251881Speter &creds, &(state->provider_iter_baton), 302251881Speter provider->provider_baton, auth_baton->parameters, 303251881Speter state->realmstring, auth_baton->pool)); 304251881Speter state->got_first = TRUE; 305251881Speter } 306251881Speter else if (provider->vtable->next_credentials) 307251881Speter { 308251881Speter SVN_ERR(provider->vtable->next_credentials( 309251881Speter &creds, state->provider_iter_baton, 310251881Speter provider->provider_baton, auth_baton->parameters, 311251881Speter state->realmstring, auth_baton->pool)); 312251881Speter } 313251881Speter 314251881Speter if (creds != NULL) 315251881Speter { 316251881Speter /* Put the creds in the cache */ 317251881Speter svn_hash_sets(auth_baton->creds_cache, state->cache_key, creds); 318251881Speter break; 319251881Speter } 320251881Speter 321251881Speter state->got_first = FALSE; 322251881Speter } 323251881Speter 324251881Speter *credentials = creds; 325251881Speter 326251881Speter return SVN_NO_ERROR; 327251881Speter} 328251881Speter 329251881Speter 330251881Spetersvn_error_t * 331251881Spetersvn_auth_save_credentials(svn_auth_iterstate_t *state, 332251881Speter apr_pool_t *pool) 333251881Speter{ 334251881Speter int i; 335251881Speter svn_auth_provider_object_t *provider; 336251881Speter svn_boolean_t save_succeeded = FALSE; 337251881Speter const char *no_auth_cache; 338251881Speter svn_auth_baton_t *auth_baton; 339251881Speter void *creds; 340251881Speter 341251881Speter if (! state || state->table->providers->nelts <= state->provider_idx) 342251881Speter return SVN_NO_ERROR; 343251881Speter 344251881Speter auth_baton = state->auth_baton; 345251881Speter creds = svn_hash_gets(state->auth_baton->creds_cache, state->cache_key); 346251881Speter if (! creds) 347251881Speter return SVN_NO_ERROR; 348251881Speter 349251881Speter /* Do not save the creds if SVN_AUTH_PARAM_NO_AUTH_CACHE is set */ 350251881Speter no_auth_cache = svn_hash_gets(auth_baton->parameters, 351251881Speter SVN_AUTH_PARAM_NO_AUTH_CACHE); 352251881Speter if (no_auth_cache) 353251881Speter return SVN_NO_ERROR; 354251881Speter 355251881Speter /* First, try to save the creds using the provider that produced them. */ 356251881Speter provider = APR_ARRAY_IDX(state->table->providers, 357251881Speter state->provider_idx, 358251881Speter svn_auth_provider_object_t *); 359251881Speter if (provider->vtable->save_credentials) 360251881Speter SVN_ERR(provider->vtable->save_credentials(&save_succeeded, 361251881Speter creds, 362251881Speter provider->provider_baton, 363251881Speter auth_baton->parameters, 364251881Speter state->realmstring, 365251881Speter pool)); 366251881Speter if (save_succeeded) 367251881Speter return SVN_NO_ERROR; 368251881Speter 369251881Speter /* Otherwise, loop from the top of the list, asking every provider 370251881Speter to attempt a save. ### todo: someday optimize so we don't 371251881Speter necessarily start from the top of the list. */ 372251881Speter for (i = 0; i < state->table->providers->nelts; i++) 373251881Speter { 374251881Speter provider = APR_ARRAY_IDX(state->table->providers, i, 375251881Speter svn_auth_provider_object_t *); 376251881Speter if (provider->vtable->save_credentials) 377251881Speter SVN_ERR(provider->vtable->save_credentials 378251881Speter (&save_succeeded, creds, 379251881Speter provider->provider_baton, 380251881Speter auth_baton->parameters, 381251881Speter state->realmstring, 382251881Speter pool)); 383251881Speter 384251881Speter if (save_succeeded) 385251881Speter break; 386251881Speter } 387251881Speter 388251881Speter /* ### notice that at the moment, if no provider can save, there's 389251881Speter no way the caller will know. */ 390251881Speter 391251881Speter return SVN_NO_ERROR; 392251881Speter} 393251881Speter 394251881Speter 395251881Spetersvn_error_t * 396251881Spetersvn_auth_forget_credentials(svn_auth_baton_t *auth_baton, 397251881Speter const char *cred_kind, 398251881Speter const char *realmstring, 399251881Speter apr_pool_t *scratch_pool) 400251881Speter{ 401251881Speter SVN_ERR_ASSERT((cred_kind && realmstring) || (!cred_kind && !realmstring)); 402251881Speter 403251881Speter /* If we have a CRED_KIND and REALMSTRING, we clear out just the 404251881Speter cached item (if any). Otherwise, empty the whole hash. */ 405251881Speter if (cred_kind) 406251881Speter { 407251881Speter svn_hash_sets(auth_baton->creds_cache, 408251881Speter make_cache_key(cred_kind, realmstring, scratch_pool), 409251881Speter NULL); 410251881Speter } 411251881Speter else 412251881Speter { 413251881Speter apr_hash_clear(auth_baton->creds_cache); 414251881Speter } 415251881Speter 416251881Speter return SVN_NO_ERROR; 417251881Speter} 418251881Speter 419251881Speter 420251881Spetersvn_auth_ssl_server_cert_info_t * 421251881Spetersvn_auth_ssl_server_cert_info_dup 422251881Speter (const svn_auth_ssl_server_cert_info_t *info, apr_pool_t *pool) 423251881Speter{ 424251881Speter svn_auth_ssl_server_cert_info_t *new_info 425251881Speter = apr_palloc(pool, sizeof(*new_info)); 426251881Speter 427251881Speter *new_info = *info; 428251881Speter 429251881Speter new_info->hostname = apr_pstrdup(pool, new_info->hostname); 430251881Speter new_info->fingerprint = apr_pstrdup(pool, new_info->fingerprint); 431251881Speter new_info->valid_from = apr_pstrdup(pool, new_info->valid_from); 432251881Speter new_info->valid_until = apr_pstrdup(pool, new_info->valid_until); 433251881Speter new_info->issuer_dname = apr_pstrdup(pool, new_info->issuer_dname); 434251881Speter new_info->ascii_cert = apr_pstrdup(pool, new_info->ascii_cert); 435251881Speter 436251881Speter return new_info; 437251881Speter} 438251881Speter 439251881Spetersvn_error_t * 440251881Spetersvn_auth_get_platform_specific_provider(svn_auth_provider_object_t **provider, 441251881Speter const char *provider_name, 442251881Speter const char *provider_type, 443251881Speter apr_pool_t *pool) 444251881Speter{ 445251881Speter *provider = NULL; 446251881Speter 447251881Speter if (apr_strnatcmp(provider_name, "gnome_keyring") == 0 || 448251881Speter apr_strnatcmp(provider_name, "kwallet") == 0) 449251881Speter { 450251881Speter#if defined(SVN_HAVE_GNOME_KEYRING) || defined(SVN_HAVE_KWALLET) 451251881Speter apr_dso_handle_t *dso; 452251881Speter apr_dso_handle_sym_t provider_function_symbol, version_function_symbol; 453251881Speter const char *library_label, *library_name; 454251881Speter const char *provider_function_name, *version_function_name; 455251881Speter library_name = apr_psprintf(pool, 456251881Speter "libsvn_auth_%s-%d.so.%d", 457251881Speter provider_name, 458251881Speter SVN_VER_MAJOR, SVN_SOVERSION); 459251881Speter library_label = apr_psprintf(pool, "svn_%s", provider_name); 460251881Speter provider_function_name = apr_psprintf(pool, 461251881Speter "svn_auth_get_%s_%s_provider", 462251881Speter provider_name, provider_type); 463251881Speter version_function_name = apr_psprintf(pool, 464251881Speter "svn_auth_%s_version", 465251881Speter provider_name); 466251881Speter SVN_ERR(svn_dso_load(&dso, library_name)); 467251881Speter if (dso) 468251881Speter { 469251881Speter if (apr_dso_sym(&version_function_symbol, 470251881Speter dso, 471251881Speter version_function_name) == 0) 472251881Speter { 473251881Speter svn_version_func_t version_function 474251881Speter = version_function_symbol; 475251881Speter svn_version_checklist_t check_list[2]; 476251881Speter 477251881Speter check_list[0].label = library_label; 478251881Speter check_list[0].version_query = version_function; 479251881Speter check_list[1].label = NULL; 480251881Speter check_list[1].version_query = NULL; 481251881Speter SVN_ERR(svn_ver_check_list(svn_subr_version(), check_list)); 482251881Speter } 483251881Speter if (apr_dso_sym(&provider_function_symbol, 484251881Speter dso, 485251881Speter provider_function_name) == 0) 486251881Speter { 487251881Speter if (strcmp(provider_type, "simple") == 0) 488251881Speter { 489251881Speter svn_auth_simple_provider_func_t provider_function 490251881Speter = provider_function_symbol; 491251881Speter provider_function(provider, pool); 492251881Speter } 493251881Speter else if (strcmp(provider_type, "ssl_client_cert_pw") == 0) 494251881Speter { 495251881Speter svn_auth_ssl_client_cert_pw_provider_func_t provider_function 496251881Speter = provider_function_symbol; 497251881Speter provider_function(provider, pool); 498251881Speter } 499251881Speter } 500251881Speter } 501251881Speter#endif 502251881Speter } 503251881Speter else 504251881Speter { 505251881Speter#if defined(SVN_HAVE_GPG_AGENT) 506251881Speter if (strcmp(provider_name, "gpg_agent") == 0 && 507251881Speter strcmp(provider_type, "simple") == 0) 508251881Speter { 509251881Speter svn_auth_get_gpg_agent_simple_provider(provider, pool); 510251881Speter } 511251881Speter#endif 512251881Speter#ifdef SVN_HAVE_KEYCHAIN_SERVICES 513251881Speter if (strcmp(provider_name, "keychain") == 0 && 514251881Speter strcmp(provider_type, "simple") == 0) 515251881Speter { 516251881Speter svn_auth_get_keychain_simple_provider(provider, pool); 517251881Speter } 518251881Speter else if (strcmp(provider_name, "keychain") == 0 && 519251881Speter strcmp(provider_type, "ssl_client_cert_pw") == 0) 520251881Speter { 521251881Speter svn_auth_get_keychain_ssl_client_cert_pw_provider(provider, pool); 522251881Speter } 523251881Speter#endif 524251881Speter 525251881Speter#if defined(WIN32) && !defined(__MINGW32__) 526251881Speter if (strcmp(provider_name, "windows") == 0 && 527251881Speter strcmp(provider_type, "simple") == 0) 528251881Speter { 529251881Speter svn_auth_get_windows_simple_provider(provider, pool); 530251881Speter } 531251881Speter else if (strcmp(provider_name, "windows") == 0 && 532251881Speter strcmp(provider_type, "ssl_client_cert_pw") == 0) 533251881Speter { 534251881Speter svn_auth_get_windows_ssl_client_cert_pw_provider(provider, pool); 535251881Speter } 536251881Speter else if (strcmp(provider_name, "windows") == 0 && 537251881Speter strcmp(provider_type, "ssl_server_trust") == 0) 538251881Speter { 539251881Speter svn_auth_get_windows_ssl_server_trust_provider(provider, pool); 540251881Speter } 541251881Speter#endif 542251881Speter } 543251881Speter 544251881Speter return SVN_NO_ERROR; 545251881Speter} 546251881Speter 547251881Spetersvn_error_t * 548251881Spetersvn_auth_get_platform_specific_client_providers(apr_array_header_t **providers, 549251881Speter svn_config_t *config, 550251881Speter apr_pool_t *pool) 551251881Speter{ 552251881Speter svn_auth_provider_object_t *provider; 553251881Speter const char *password_stores_config_option; 554251881Speter apr_array_header_t *password_stores; 555251881Speter int i; 556251881Speter 557251881Speter#define SVN__MAYBE_ADD_PROVIDER(list, p) \ 558251881Speter { if (p) APR_ARRAY_PUSH(list, svn_auth_provider_object_t *) = p; } 559251881Speter 560251881Speter#define SVN__DEFAULT_AUTH_PROVIDER_LIST \ 561251881Speter "gnome-keyring,kwallet,keychain,gpg-agent,windows-cryptoapi" 562251881Speter 563251881Speter *providers = apr_array_make(pool, 12, sizeof(svn_auth_provider_object_t *)); 564251881Speter 565251881Speter /* Fetch the configured list of password stores, and split them into 566251881Speter an array. */ 567251881Speter svn_config_get(config, 568251881Speter &password_stores_config_option, 569251881Speter SVN_CONFIG_SECTION_AUTH, 570251881Speter SVN_CONFIG_OPTION_PASSWORD_STORES, 571251881Speter SVN__DEFAULT_AUTH_PROVIDER_LIST); 572251881Speter password_stores = svn_cstring_split(password_stores_config_option, 573251881Speter " ,", TRUE, pool); 574251881Speter 575251881Speter for (i = 0; i < password_stores->nelts; i++) 576251881Speter { 577251881Speter const char *password_store = APR_ARRAY_IDX(password_stores, i, 578251881Speter const char *); 579251881Speter 580251881Speter /* GNOME Keyring */ 581251881Speter if (apr_strnatcmp(password_store, "gnome-keyring") == 0) 582251881Speter { 583251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 584251881Speter "gnome_keyring", 585251881Speter "simple", 586251881Speter pool)); 587251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 588251881Speter 589251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 590251881Speter "gnome_keyring", 591251881Speter "ssl_client_cert_pw", 592251881Speter pool)); 593251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 594251881Speter } 595251881Speter /* GPG-AGENT */ 596251881Speter else if (apr_strnatcmp(password_store, "gpg-agent") == 0) 597251881Speter { 598251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 599251881Speter "gpg_agent", 600251881Speter "simple", 601251881Speter pool)); 602251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 603251881Speter } 604251881Speter /* KWallet */ 605251881Speter else if (apr_strnatcmp(password_store, "kwallet") == 0) 606251881Speter { 607251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 608251881Speter "kwallet", 609251881Speter "simple", 610251881Speter pool)); 611251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 612251881Speter 613251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 614251881Speter "kwallet", 615251881Speter "ssl_client_cert_pw", 616251881Speter pool)); 617251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 618251881Speter } 619251881Speter /* Keychain */ 620251881Speter else if (apr_strnatcmp(password_store, "keychain") == 0) 621251881Speter { 622251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 623251881Speter "keychain", 624251881Speter "simple", 625251881Speter pool)); 626251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 627251881Speter 628251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 629251881Speter "keychain", 630251881Speter "ssl_client_cert_pw", 631251881Speter pool)); 632251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 633251881Speter } 634251881Speter /* Windows */ 635251881Speter else if (apr_strnatcmp(password_store, "windows-cryptoapi") == 0) 636251881Speter { 637251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 638251881Speter "windows", 639251881Speter "simple", 640251881Speter pool)); 641251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 642251881Speter 643251881Speter SVN_ERR(svn_auth_get_platform_specific_provider(&provider, 644251881Speter "windows", 645251881Speter "ssl_client_cert_pw", 646251881Speter pool)); 647251881Speter SVN__MAYBE_ADD_PROVIDER(*providers, provider); 648251881Speter } 649251881Speter } 650251881Speter 651251881Speter return SVN_NO_ERROR; 652251881Speter} 653