2 * username_providers.c: providers for SVN_AUTH_CRED_USERNAME
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
24 /* ==================================================================== */
30 #include <apr_pools.h>
33 #include "svn_error.h"
35 #include "svn_config.h"
39 /*-----------------------------------------------------------------------*/
41 /*-----------------------------------------------------------------------*/
43 /*** Username-only Provider ***/
45 username_first_creds(void **credentials,
48 apr_hash_t *parameters,
49 const char *realmstring,
52 const char *config_dir = svn_hash_gets(parameters,
53 SVN_AUTH_PARAM_CONFIG_DIR);
54 const char *username = svn_hash_gets(parameters,
55 SVN_AUTH_PARAM_DEFAULT_USERNAME);
56 svn_boolean_t may_save = !! username;
59 /* If we don't have a usename yet, try the auth cache */
62 apr_hash_t *creds_hash = NULL;
64 /* Try to load credentials from a file on disk, based on the
65 realmstring. Don't throw an error, though: if something went
66 wrong reading the file, no big deal. What really matters is that
67 we failed to get the creds, so allow the auth system to try the
69 err = svn_config_read_auth_data(&creds_hash, SVN_AUTH_CRED_USERNAME,
70 realmstring, config_dir, pool);
72 if (! err && creds_hash)
74 svn_string_t *str = svn_hash_gets(creds_hash,
75 SVN_CONFIG_AUTHN_USERNAME_KEY);
81 /* If that failed, ask the OS for the username */
83 username = svn_user_get_name(pool);
87 svn_auth_cred_simple_t *creds = apr_pcalloc(pool, sizeof(*creds));
88 creds->username = username;
89 creds->may_save = may_save;
102 username_save_creds(svn_boolean_t *saved,
104 void *provider_baton,
105 apr_hash_t *parameters,
106 const char *realmstring,
109 svn_auth_cred_simple_t *creds = credentials;
110 apr_hash_t *creds_hash = NULL;
111 const char *config_dir;
116 if (! creds->may_save)
119 config_dir = svn_hash_gets(parameters, SVN_AUTH_PARAM_CONFIG_DIR);
121 /* Put the credentials in a hash and save it to disk */
122 creds_hash = apr_hash_make(pool);
123 svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_USERNAME_KEY,
124 svn_string_create(creds->username, pool));
125 err = svn_config_write_auth_data(creds_hash, SVN_AUTH_CRED_USERNAME,
126 realmstring, config_dir, pool);
127 svn_error_clear(err);
134 static const svn_auth_provider_t username_provider = {
135 SVN_AUTH_CRED_USERNAME,
136 username_first_creds,
144 svn_auth_get_username_provider(svn_auth_provider_object_t **provider,
147 svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
149 po->vtable = &username_provider;
154 /*-----------------------------------------------------------------------*/
155 /* Prompt provider */
156 /*-----------------------------------------------------------------------*/
158 /* Baton type for username-only prompting. */
159 typedef struct username_prompt_provider_baton_t
161 svn_auth_username_prompt_func_t prompt_func;
164 /* how many times to re-prompt after the first one fails */
166 } username_prompt_provider_baton_t;
169 /* Iteration baton type for username-only prompting. */
170 typedef struct username_prompt_iter_baton_t
172 /* how many times we've reprompted */
175 } username_prompt_iter_baton_t;
178 /*** Helper Functions ***/
180 prompt_for_username_creds(svn_auth_cred_username_t **cred_p,
181 username_prompt_provider_baton_t *pb,
182 apr_hash_t *parameters,
183 const char *realmstring,
184 svn_boolean_t first_time,
185 svn_boolean_t may_save,
188 const char *def_username = NULL;
192 /* If we're allowed to check for default usernames, do so. */
194 def_username = svn_hash_gets(parameters, SVN_AUTH_PARAM_DEFAULT_USERNAME);
196 /* If we have defaults, just build the cred here and return it.
198 * ### I do wonder why this is here instead of in a separate
199 * ### 'defaults' provider that would run before the prompt
200 * ### provider... Hmmm.
204 *cred_p = apr_palloc(pool, sizeof(**cred_p));
205 (*cred_p)->username = apr_pstrdup(pool, def_username);
206 (*cred_p)->may_save = TRUE;
210 SVN_ERR(pb->prompt_func(cred_p, pb->prompt_baton, realmstring,
218 /* Our first attempt will use any default username passed
219 in, and prompt for the remaining stuff. */
221 username_prompt_first_creds(void **credentials_p,
223 void *provider_baton,
224 apr_hash_t *parameters,
225 const char *realmstring,
228 username_prompt_provider_baton_t *pb = provider_baton;
229 username_prompt_iter_baton_t *ibaton = apr_pcalloc(pool, sizeof(*ibaton));
230 const char *no_auth_cache = svn_hash_gets(parameters,
231 SVN_AUTH_PARAM_NO_AUTH_CACHE);
233 SVN_ERR(prompt_for_username_creds
234 ((svn_auth_cred_username_t **) credentials_p, pb,
235 parameters, realmstring, TRUE, ! no_auth_cache, pool));
238 *iter_baton = ibaton;
244 /* Subsequent attempts to fetch will ignore the default username
245 value, and simply re-prompt for the username, up to a maximum of
246 ib->pb->retry_limit. */
248 username_prompt_next_creds(void **credentials_p,
250 void *provider_baton,
251 apr_hash_t *parameters,
252 const char *realmstring,
255 username_prompt_iter_baton_t *ib = iter_baton;
256 username_prompt_provider_baton_t *pb = provider_baton;
257 const char *no_auth_cache = svn_hash_gets(parameters,
258 SVN_AUTH_PARAM_NO_AUTH_CACHE);
260 if ((pb->retry_limit >= 0) && (ib->retries >= pb->retry_limit))
262 /* give up, go on to next provider. */
263 *credentials_p = NULL;
268 return prompt_for_username_creds
269 ((svn_auth_cred_username_t **) credentials_p, pb,
270 parameters, realmstring, FALSE, ! no_auth_cache, pool);
274 static const svn_auth_provider_t username_prompt_provider = {
275 SVN_AUTH_CRED_USERNAME,
276 username_prompt_first_creds,
277 username_prompt_next_creds,
284 svn_auth_get_username_prompt_provider
285 (svn_auth_provider_object_t **provider,
286 svn_auth_username_prompt_func_t prompt_func,
291 svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
292 username_prompt_provider_baton_t *pb = apr_pcalloc(pool, sizeof(*pb));
294 pb->prompt_func = prompt_func;
295 pb->prompt_baton = prompt_baton;
296 pb->retry_limit = retry_limit;
298 po->vtable = &username_prompt_provider;
299 po->provider_baton = pb;