* subversion/libsvn_subr/validate.c
[svn.git] / subversion / libsvn_subr / username_providers.c
blob9c2a4f63f8579e316200ae1f9dac615a7eb2daeb
1 /*
2 * username_providers.c: providers for SVN_AUTH_CRED_USERNAME
4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
19 /* ==================================================================== */
23 /*** Includes. ***/
25 #include <apr_pools.h>
26 #include "svn_auth.h"
27 #include "svn_error.h"
28 #include "svn_utf.h"
29 #include "svn_config.h"
30 #include "svn_user.h"
33 /*-----------------------------------------------------------------------*/
34 /* File provider */
35 /*-----------------------------------------------------------------------*/
37 /* The keys that will be stored on disk */
38 #define SVN_CLIENT__AUTHFILE_USERNAME_KEY "username"
42 /*** Username-only Provider ***/
43 static svn_error_t *
44 username_first_creds(void **credentials,
45 void **iter_baton,
46 void *provider_baton,
47 apr_hash_t *parameters,
48 const char *realmstring,
49 apr_pool_t *pool)
51 const char *config_dir = apr_hash_get(parameters,
52 SVN_AUTH_PARAM_CONFIG_DIR,
53 APR_HASH_KEY_STRING);
54 const char *username = apr_hash_get(parameters,
55 SVN_AUTH_PARAM_DEFAULT_USERNAME,
56 APR_HASH_KEY_STRING);
57 svn_boolean_t may_save = !! username;
58 svn_error_t *err;
60 /* If we don't have a usename yet, try the auth cache */
61 if (! username)
63 apr_hash_t *creds_hash = NULL;
65 /* Try to load credentials from a file on disk, based on the
66 realmstring. Don't throw an error, though: if something went
67 wrong reading the file, no big deal. What really matters is that
68 we failed to get the creds, so allow the auth system to try the
69 next provider. */
70 err = svn_config_read_auth_data(&creds_hash, SVN_AUTH_CRED_USERNAME,
71 realmstring, config_dir, pool);
72 svn_error_clear(err);
73 if (! err && creds_hash)
75 svn_string_t *str = apr_hash_get(creds_hash,
76 SVN_CLIENT__AUTHFILE_USERNAME_KEY,
77 APR_HASH_KEY_STRING);
78 if (str && str->data)
79 username = str->data;
83 /* If that failed, ask the OS for the username */
84 if (! username)
85 username = svn_user_get_name(pool);
87 if (username)
89 svn_auth_cred_simple_t *creds = apr_pcalloc(pool, sizeof(*creds));
90 creds->username = username;
91 creds->may_save = may_save;
92 *credentials = creds;
94 else
95 *credentials = NULL;
97 *iter_baton = NULL;
99 return SVN_NO_ERROR;
103 static svn_error_t *
104 username_save_creds(svn_boolean_t *saved,
105 void *credentials,
106 void *provider_baton,
107 apr_hash_t *parameters,
108 const char *realmstring,
109 apr_pool_t *pool)
111 svn_auth_cred_simple_t *creds = credentials;
112 apr_hash_t *creds_hash = NULL;
113 const char *config_dir;
114 svn_error_t *err;
116 *saved = FALSE;
118 if (! creds->may_save)
119 return SVN_NO_ERROR;
121 config_dir = apr_hash_get(parameters,
122 SVN_AUTH_PARAM_CONFIG_DIR,
123 APR_HASH_KEY_STRING);
125 /* Put the credentials in a hash and save it to disk */
126 creds_hash = apr_hash_make(pool);
127 apr_hash_set(creds_hash, SVN_CLIENT__AUTHFILE_USERNAME_KEY,
128 APR_HASH_KEY_STRING,
129 svn_string_create(creds->username, pool));
130 err = svn_config_write_auth_data(creds_hash, SVN_AUTH_CRED_USERNAME,
131 realmstring, config_dir, pool);
132 svn_error_clear(err);
133 *saved = ! err;
135 return SVN_NO_ERROR;
139 static const svn_auth_provider_t username_provider = {
140 SVN_AUTH_CRED_USERNAME,
141 username_first_creds,
142 NULL,
143 username_save_creds
147 /* Public API */
148 void
149 svn_auth_get_username_provider(svn_auth_provider_object_t **provider,
150 apr_pool_t *pool)
152 svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
154 po->vtable = &username_provider;
155 *provider = po;
159 /*-----------------------------------------------------------------------*/
160 /* Prompt provider */
161 /*-----------------------------------------------------------------------*/
163 /* Baton type for username-only prompting. */
164 typedef struct
166 svn_auth_username_prompt_func_t prompt_func;
167 void *prompt_baton;
169 /* how many times to re-prompt after the first one fails */
170 int retry_limit;
171 } username_prompt_provider_baton_t;
174 /* Iteration baton type for username-only prompting. */
175 typedef struct
177 /* how many times we've reprompted */
178 int retries;
180 } username_prompt_iter_baton_t;
183 /*** Helper Functions ***/
184 static svn_error_t *
185 prompt_for_username_creds(svn_auth_cred_username_t **cred_p,
186 username_prompt_provider_baton_t *pb,
187 apr_hash_t *parameters,
188 const char *realmstring,
189 svn_boolean_t first_time,
190 svn_boolean_t may_save,
191 apr_pool_t *pool)
193 const char *def_username = NULL;
195 *cred_p = NULL;
197 /* If we're allowed to check for default usernames, do so. */
198 if (first_time)
199 def_username = apr_hash_get(parameters,
200 SVN_AUTH_PARAM_DEFAULT_USERNAME,
201 APR_HASH_KEY_STRING);
203 /* If we have defaults, just build the cred here and return it.
205 * ### I do wonder why this is here instead of in a separate
206 * ### 'defaults' provider that would run before the prompt
207 * ### provider... Hmmm.
209 if (def_username)
211 *cred_p = apr_palloc(pool, sizeof(**cred_p));
212 (*cred_p)->username = apr_pstrdup(pool, def_username);
213 (*cred_p)->may_save = TRUE;
215 else
217 SVN_ERR(pb->prompt_func(cred_p, pb->prompt_baton, realmstring,
218 may_save, pool));
221 return SVN_NO_ERROR;
225 /* Our first attempt will use any default username passed
226 in, and prompt for the remaining stuff. */
227 static svn_error_t *
228 username_prompt_first_creds(void **credentials_p,
229 void **iter_baton,
230 void *provider_baton,
231 apr_hash_t *parameters,
232 const char *realmstring,
233 apr_pool_t *pool)
235 username_prompt_provider_baton_t *pb = provider_baton;
236 username_prompt_iter_baton_t *ibaton = apr_pcalloc(pool, sizeof(*ibaton));
237 const char *no_auth_cache = apr_hash_get(parameters,
238 SVN_AUTH_PARAM_NO_AUTH_CACHE,
239 APR_HASH_KEY_STRING);
241 SVN_ERR(prompt_for_username_creds
242 ((svn_auth_cred_username_t **) credentials_p, pb,
243 parameters, realmstring, TRUE, ! no_auth_cache, pool));
245 ibaton->retries = 0;
246 *iter_baton = ibaton;
248 return SVN_NO_ERROR;
252 /* Subsequent attempts to fetch will ignore the default username
253 value, and simply re-prompt for the username, up to a maximum of
254 ib->pb->retry_limit. */
255 static svn_error_t *
256 username_prompt_next_creds(void **credentials_p,
257 void *iter_baton,
258 void *provider_baton,
259 apr_hash_t *parameters,
260 const char *realmstring,
261 apr_pool_t *pool)
263 username_prompt_iter_baton_t *ib = iter_baton;
264 username_prompt_provider_baton_t *pb = provider_baton;
265 const char *no_auth_cache = apr_hash_get(parameters,
266 SVN_AUTH_PARAM_NO_AUTH_CACHE,
267 APR_HASH_KEY_STRING);
269 if (ib->retries >= pb->retry_limit)
271 /* give up, go on to next provider. */
272 *credentials_p = NULL;
273 return SVN_NO_ERROR;
275 ib->retries++;
277 SVN_ERR(prompt_for_username_creds
278 ((svn_auth_cred_username_t **) credentials_p, pb,
279 parameters, realmstring, FALSE, ! no_auth_cache, pool));
281 return SVN_NO_ERROR;
285 static const svn_auth_provider_t username_prompt_provider = {
286 SVN_AUTH_CRED_USERNAME,
287 username_prompt_first_creds,
288 username_prompt_next_creds,
289 NULL,
293 /* Public API */
294 void
295 svn_auth_get_username_prompt_provider
296 (svn_auth_provider_object_t **provider,
297 svn_auth_username_prompt_func_t prompt_func,
298 void *prompt_baton,
299 int retry_limit,
300 apr_pool_t *pool)
302 svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
303 username_prompt_provider_baton_t *pb = apr_pcalloc(pool, sizeof(*pb));
305 pb->prompt_func = prompt_func;
306 pb->prompt_baton = prompt_baton;
307 pb->retry_limit = retry_limit;
309 po->vtable = &username_prompt_provider;
310 po->provider_baton = pb;
311 *provider = po;