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 /* ==================================================================== */
25 #include <apr_pools.h>
27 #include "svn_error.h"
29 #include "svn_config.h"
33 /*-----------------------------------------------------------------------*/
35 /*-----------------------------------------------------------------------*/
37 /* The keys that will be stored on disk */
38 #define SVN_CLIENT__AUTHFILE_USERNAME_KEY "username"
42 /*** Username-only Provider ***/
44 username_first_creds(void **credentials
,
47 apr_hash_t
*parameters
,
48 const char *realmstring
,
51 const char *config_dir
= apr_hash_get(parameters
,
52 SVN_AUTH_PARAM_CONFIG_DIR
,
54 const char *username
= apr_hash_get(parameters
,
55 SVN_AUTH_PARAM_DEFAULT_USERNAME
,
57 svn_boolean_t may_save
= !! username
;
60 /* If we don't have a usename yet, try the auth cache */
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
70 err
= svn_config_read_auth_data(&creds_hash
, SVN_AUTH_CRED_USERNAME
,
71 realmstring
, config_dir
, pool
);
73 if (! err
&& creds_hash
)
75 svn_string_t
*str
= apr_hash_get(creds_hash
,
76 SVN_CLIENT__AUTHFILE_USERNAME_KEY
,
83 /* If that failed, ask the OS for the username */
85 username
= svn_user_get_name(pool
);
89 svn_auth_cred_simple_t
*creds
= apr_pcalloc(pool
, sizeof(*creds
));
90 creds
->username
= username
;
91 creds
->may_save
= may_save
;
104 username_save_creds(svn_boolean_t
*saved
,
106 void *provider_baton
,
107 apr_hash_t
*parameters
,
108 const char *realmstring
,
111 svn_auth_cred_simple_t
*creds
= credentials
;
112 apr_hash_t
*creds_hash
= NULL
;
113 const char *config_dir
;
118 if (! creds
->may_save
)
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
,
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
);
139 static const svn_auth_provider_t username_provider
= {
140 SVN_AUTH_CRED_USERNAME
,
141 username_first_creds
,
149 svn_auth_get_username_provider(svn_auth_provider_object_t
**provider
,
152 svn_auth_provider_object_t
*po
= apr_pcalloc(pool
, sizeof(*po
));
154 po
->vtable
= &username_provider
;
159 /*-----------------------------------------------------------------------*/
160 /* Prompt provider */
161 /*-----------------------------------------------------------------------*/
163 /* Baton type for username-only prompting. */
166 svn_auth_username_prompt_func_t prompt_func
;
169 /* how many times to re-prompt after the first one fails */
171 } username_prompt_provider_baton_t
;
174 /* Iteration baton type for username-only prompting. */
177 /* how many times we've reprompted */
180 } username_prompt_iter_baton_t
;
183 /*** Helper Functions ***/
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
,
193 const char *def_username
= NULL
;
197 /* If we're allowed to check for default usernames, do so. */
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.
211 *cred_p
= apr_palloc(pool
, sizeof(**cred_p
));
212 (*cred_p
)->username
= apr_pstrdup(pool
, def_username
);
213 (*cred_p
)->may_save
= TRUE
;
217 SVN_ERR(pb
->prompt_func(cred_p
, pb
->prompt_baton
, realmstring
,
225 /* Our first attempt will use any default username passed
226 in, and prompt for the remaining stuff. */
228 username_prompt_first_creds(void **credentials_p
,
230 void *provider_baton
,
231 apr_hash_t
*parameters
,
232 const char *realmstring
,
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
));
246 *iter_baton
= ibaton
;
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. */
256 username_prompt_next_creds(void **credentials_p
,
258 void *provider_baton
,
259 apr_hash_t
*parameters
,
260 const char *realmstring
,
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
;
277 SVN_ERR(prompt_for_username_creds
278 ((svn_auth_cred_username_t
**) credentials_p
, pb
,
279 parameters
, realmstring
, FALSE
, ! no_auth_cache
, pool
));
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
,
295 svn_auth_get_username_prompt_provider
296 (svn_auth_provider_object_t
**provider
,
297 svn_auth_username_prompt_func_t prompt_func
,
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
;