Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(33)

Side by Side Diff: subversion/libsvn_subr/simple_providers.c

Issue 989: kwallet final branch SVN Base: http://svn.collab.net/repos/svn/trunk
Patch Set: Created 3 months, 2 weeks ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * simple_providers.c: providers for SVN_AUTH_CRED_SIMPLE 2 * simple_providers.c: providers for SVN_AUTH_CRED_SIMPLE
3 * 3 *
4 * ==================================================================== 4 * ====================================================================
5 * Copyright (c) 2000-2004 CollabNet. All rights reserved. 5 * Copyright (c) 2003-2006, 2008 CollabNet. All rights reserved.
6 * 6 *
7 * This software is licensed as described in the file COPYING, which 7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms 8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html. 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 10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option. 11 * newer version instead, at your option.
12 * 12 *
13 * This software consists of voluntary contributions made by many 13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision 14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/. 15 * history and logs, available at http://subversion.tigris.org/.
16 * ==================================================================== 16 * ====================================================================
17 */ 17 */
18 18
19 /* ==================================================================== */ 19 /* ==================================================================== */
20 20
21 21
22 22
23 /*** Includes. ***/ 23 /*** Includes. ***/
24 24
25 #include <apr_pools.h> 25 #include <apr_pools.h>
26 #include "svn_auth.h" 26 #include "svn_auth.h"
27 #include "svn_error.h" 27 #include "svn_error.h"
28 #include "svn_utf.h" 28 #include "svn_utf.h"
29 #include "svn_config.h" 29 #include "svn_config.h"
30 #include "svn_user.h" 30 #include "svn_user.h"
31
32 #include "private/svn_auth_private.h"
31 33
32 #include "svn_private_config.h" 34 #include "svn_private_config.h"
33 35
34 /*-----------------------------------------------------------------------*/ 36 /*-----------------------------------------------------------------------*/
35 /* File provider */ 37 /* File provider */
36 /*-----------------------------------------------------------------------*/ 38 /*-----------------------------------------------------------------------*/
37 39
38 /* The keys that will be stored on disk */ 40 /* The keys that will be stored on disk */
39 #define SVN_AUTH__AUTHFILE_USERNAME_KEY "username" 41 #define SVN_AUTH__AUTHFILE_USERNAME_KEY "username"
40 #define SVN_AUTH__AUTHFILE_PASSWORD_KEY "password" 42 #define SVN_AUTH__AUTHFILE_PASSWORD_KEY "password"
41 #define SVN_AUTH__AUTHFILE_PASSTYPE_KEY "passtype" 43 #define SVN_AUTH__AUTHFILE_PASSTYPE_KEY "passtype"
42 44
43 /* If you add a password type for a provider which stores 45 /* If you add a password type for a provider which stores
44 * passwords on disk in encrypted form, remember to update 46 * passwords on disk in encrypted form, remember to update
45 * simple_save_creds_helper. Otherwise it will be assumed 47 * svn_auth__simple_save_creds_helper. Otherwise it will be
46 * that your provider stores passwords in plaintext. */ 48 * assumed that your provider stores passwords in plaintext. */
47 #define SVN_AUTH__SIMPLE_PASSWORD_TYPE "simple" 49 #define SVN_AUTH__SIMPLE_PASSWORD_TYPE "simple"
48 #define SVN_AUTH__WINCRYPT_PASSWORD_TYPE "wincrypt" 50 #define SVN_AUTH__WINCRYPT_PASSWORD_TYPE "wincrypt"
49 #define SVN_AUTH__KEYCHAIN_PASSWORD_TYPE "keychain" 51 #define SVN_AUTH__KEYCHAIN_PASSWORD_TYPE "keychain"
52 #define SVN_AUTH__KWALLET_PASSWORD_TYPE "kwallet"
sussman 2008/05/15 15:14:41 Uhoh, this same constant is defined in kwallet.cpp
50 53
51 /* Baton type for the simple provider. */ 54 /* Baton type for the simple provider. */
52 typedef struct 55 typedef struct
53 { 56 {
54 svn_auth_plaintext_prompt_func_t plaintext_prompt_func; 57 svn_auth_plaintext_prompt_func_t plaintext_prompt_func;
55 void *prompt_baton; 58 void *prompt_baton;
56 /* We cache the user's answer to the plaintext prompt, keyed 59 /* We cache the user's answer to the plaintext prompt, keyed
57 * by realm, in case we'll be called multiple times for the 60 * by realm, in case we'll be called multiple times for the
58 * same realm. */ 61 * same realm. */
59 apr_hash_t *plaintext_answers; 62 apr_hash_t *plaintext_answers;
60 } simple_provider_baton_t; 63 } simple_provider_baton_t;
61 64
62 65
63 /* A function that stores PASSWORD (or some encrypted version thereof) 66 /* Implementation of svn_auth__password_get_t that retrieves
64 either directly in CREDS, or externally using REALMSTRING and USERNAME 67 the plaintext password from CREDS. */
65 as keys into the external store. If NON_INTERACTIVE is set, the user
66 must not be involved in the storage process. POOL is used for any
67 necessary allocation. */
68 typedef svn_boolean_t (*password_set_t)(apr_hash_t *creds,
69 const char *realmstring,
70 const char *username,
71 const char *password,
72 svn_boolean_t non_interactive,
73 apr_pool_t *pool);
74
75 /* A function that stores in *PASSWORD (potentially after decrypting it)
76 the user's password. It might be obtained directly from CREDS, or
77 from an external store, using REALMSTRING and USERNAME as keys.
78 If NON_INTERACTIVE is set, the user must not be involved in the
79 retrieval process. POOL is used for any necessary allocation. */
80 typedef svn_boolean_t (*password_get_t)(const char **password,
81 apr_hash_t *creds,
82 const char *realmstring,
83 const char *username,
84 svn_boolean_t non_interactive,
85 apr_pool_t *pool);
86
87
88
89 /* Implementation of password_get_t that retrieves the plaintext password
90 from CREDS. */
91 static svn_boolean_t 68 static svn_boolean_t
92 simple_password_get(const char **password, 69 simple_password_get(const char **password,
93 apr_hash_t *creds, 70 apr_hash_t *creds,
94 const char *realmstring, 71 const char *realmstring,
95 const char *username, 72 const char *username,
96 svn_boolean_t non_interactive, 73 svn_boolean_t non_interactive,
97 apr_pool_t *pool) 74 apr_pool_t *pool)
98 { 75 {
99 svn_string_t *str; 76 svn_string_t *str;
100 str = apr_hash_get(creds, SVN_AUTH__AUTHFILE_PASSWORD_KEY, 77 str = apr_hash_get(creds, SVN_AUTH__AUTHFILE_PASSWORD_KEY,
101 APR_HASH_KEY_STRING); 78 APR_HASH_KEY_STRING);
102 if (str && str->data) 79 if (str && str->data)
103 { 80 {
104 *password = str->data; 81 *password = str->data;
105 return TRUE; 82 return TRUE;
106 } 83 }
107 return FALSE; 84 return FALSE;
108 } 85 }
109 86
110 /* Implementation of password_set_t that store the plaintext password 87 /* Implementation of svn_auth__password_set_t that stores
111 in CREDS. */ 88 the plaintext password in CREDS. */
112 static svn_boolean_t 89 static svn_boolean_t
113 simple_password_set(apr_hash_t *creds, 90 simple_password_set(apr_hash_t *creds,
114 const char *realmstring, 91 const char *realmstring,
115 const char *username, 92 const char *username,
116 const char *password, 93 const char *password,
117 svn_boolean_t non_interactive, 94 svn_boolean_t non_interactive,
118 apr_pool_t *pool) 95 apr_pool_t *pool)
119 { 96 {
120 apr_hash_set(creds, SVN_AUTH__AUTHFILE_PASSWORD_KEY, APR_HASH_KEY_STRING, 97 apr_hash_set(creds, SVN_AUTH__AUTHFILE_PASSWORD_KEY, APR_HASH_KEY_STRING,
121 svn_string_create(password, pool)); 98 svn_string_create(password, pool));
122 return TRUE; 99 return TRUE;
123 } 100 }
124 101
125 /* Common implementation for simple_first_creds and 102 /* Common implementation for simple_first_creds and
126 windows_simple_first_creds. Uses PARAMETERS, REALMSTRING and the 103 windows_simple_first_creds. Uses PARAMETERS, REALMSTRING and the
127 simple auth provider's username and password cache to fill a set of 104 simple auth provider's username and password cache to fill a set of
128 CREDENTIALS. PASSWORD_GET is used to obtain the password value. 105 CREDENTIALS. PASSWORD_GET is used to obtain the password value.
129 PASSTYPE identifies the type of the cached password. CREDENTIALS are 106 PASSTYPE identifies the type of the cached password. CREDENTIALS are
130 allocated from POOL. */ 107 allocated from POOL. */
131 static svn_error_t * 108 svn_error_t *
132 simple_first_creds_helper(void **credentials, 109 svn_auth__simple_first_creds_helper(void **credentials,
133 void **iter_baton, 110 void **iter_baton,
134 void *provider_baton, 111 void *provider_baton,
135 apr_hash_t *parameters, 112 apr_hash_t *parameters,
136 const char *realmstring, 113 const char *realmstring,
137 password_get_t password_get, 114 svn_auth__password_get_t password_get,
138 const char *passtype, 115 const char *passtype,
139 apr_pool_t *pool) 116 apr_pool_t *pool)
140 { 117 {
141 const char *config_dir = apr_hash_get(parameters, 118 const char *config_dir = apr_hash_get(parameters,
142 SVN_AUTH_PARAM_CONFIG_DIR, 119 SVN_AUTH_PARAM_CONFIG_DIR,
143 APR_HASH_KEY_STRING); 120 APR_HASH_KEY_STRING);
144 const char *username = apr_hash_get(parameters, 121 const char *username = apr_hash_get(parameters,
145 SVN_AUTH_PARAM_DEFAULT_USERNAME, 122 SVN_AUTH_PARAM_DEFAULT_USERNAME,
146 APR_HASH_KEY_STRING); 123 APR_HASH_KEY_STRING);
147 const char *password = apr_hash_get(parameters, 124 const char *password = apr_hash_get(parameters,
148 SVN_AUTH_PARAM_DEFAULT_PASSWORD, 125 SVN_AUTH_PARAM_DEFAULT_PASSWORD,
149 APR_HASH_KEY_STRING); 126 APR_HASH_KEY_STRING);
150 svn_boolean_t non_interactive = apr_hash_get(parameters, 127 svn_boolean_t non_interactive = apr_hash_get(parameters,
151 SVN_AUTH_PARAM_NON_INTERACTIVE, 128 SVN_AUTH_PARAM_NON_INTERACTIVE,
152 APR_HASH_KEY_STRING) != NULL; 129 APR_HASH_KEY_STRING) != NULL;
153 130
154 svn_boolean_t may_save = username || password; 131 svn_boolean_t may_save = username || password;
155 svn_error_t *err; 132 svn_error_t *err;
156 133
157 /* If we don't have a username and a password yet, we try the auth cache */ 134 /* If we don't have a username and a password yet, we try the auth cache */
158 if (! (username && password)) 135 if (! (username && password))
159 { 136 {
160 apr_hash_t *creds_hash = NULL; 137 apr_hash_t *creds_hash = NULL;
161 138
162 /* Try to load credentials from a file on disk, based on the 139 /* Try to load credentials from a file on disk, based on the
163 realmstring. Don't throw an error, though: if something went 140 realmstring. Don't throw an error, though: if something went
164 wrong reading the file, no big deal. What really matters is that 141 wrong reading the file, no big deal. What really matters is that
165 we failed to get the creds, so allow the auth system to try the 142 we failed to get the creds, so allow the auth system to try the
166 next provider. */ 143 next provider. */
167 err = svn_config_read_auth_data(&creds_hash, SVN_AUTH_CRED_SIMPLE, 144 err = svn_config_read_auth_data(&creds_hash, SVN_AUTH_CRED_SIMPLE,
168 realmstring, config_dir, pool); 145 realmstring, config_dir, pool);
169 svn_error_clear(err); 146 svn_error_clear(err);
170 if (! err && creds_hash) 147 if (! err && creds_hash)
171 { 148 {
172 svn_string_t *str; 149 svn_string_t *str;
173 if (! username) 150 if (! username)
174 { 151 {
175 str = apr_hash_get(creds_hash, 152 str = apr_hash_get(creds_hash,
176 SVN_AUTH__AUTHFILE_USERNAME_KEY, 153 SVN_AUTH__AUTHFILE_USERNAME_KEY,
177 APR_HASH_KEY_STRING); 154 APR_HASH_KEY_STRING);
178 if (str && str->data) 155 if (str && str->data)
179 username = str->data; 156 username = str->data;
180 } 157 }
181 158
182 if (! password) 159 if (! password)
183 { 160 {
184 svn_boolean_t have_passtype; 161 svn_boolean_t have_passtype;
185 /* The password type in the auth data must match the 162 /* The password type in the auth data must match the
186 mangler's type, otherwise the password must be 163 mangler's type, otherwise the password must be
187 interpreted by another provider. */ 164 interpreted by another provider. */
188 str = apr_hash_get(creds_hash, 165 str = apr_hash_get(creds_hash,
189 SVN_AUTH__AUTHFILE_PASSTYPE_KEY, 166 SVN_AUTH__AUTHFILE_PASSTYPE_KEY,
190 APR_HASH_KEY_STRING); 167 APR_HASH_KEY_STRING);
191 have_passtype = (str && str->data); 168 have_passtype = (str && str->data);
192 if (have_passtype && passtype 169 if (have_passtype && passtype
193 && 0 != strcmp(str->data, passtype)) 170 && 0 != strcmp(str->data, passtype))
194 password = NULL; 171 password = NULL;
195 else 172 else
196 { 173 {
197 if (!password_get(&password, creds_hash, realmstring, 174 if (!password_get(&password, creds_hash, realmstring,
198 username, non_interactive, pool)) 175 username, non_interactive, pool))
199 password = NULL; 176 password = NULL;
200 177
201 /* If the auth data didn't contain a password type, 178 /* If the auth data didn't contain a password type,
202 force a write to upgrade the format of the auth 179 force a write to upgrade the format of the auth
203 data file. */ 180 data file. */
204 if (password && passtype && !have_passtype) 181 if (password && passtype && !have_passtype)
205 may_save = TRUE; 182 may_save = TRUE;
206 } 183 }
207 } 184 }
208 } 185 }
209 } 186 }
210 187
211 /* Ask the OS for the username if we have a password but no 188 /* Ask the OS for the username if we have a password but no
212 username. */ 189 username. */
213 if (password && ! username) 190 if (password && ! username)
214 username = svn_user_get_name(pool); 191 username = svn_user_get_name(pool);
215 192
216 if (username && password) 193 if (username && password)
217 { 194 {
218 svn_auth_cred_simple_t *creds = apr_pcalloc(pool, sizeof(*creds)); 195 svn_auth_cred_simple_t *creds = apr_pcalloc(pool, sizeof(*creds));
219 creds->username = username; 196 creds->username = username;
220 creds->password = password; 197 creds->password = password;
221 creds->may_save = may_save; 198 creds->may_save = may_save;
222 *credentials = creds; 199 *credentials = creds;
223 } 200 }
224 else 201 else
225 *credentials = NULL; 202 *credentials = NULL;
226 203
227 *iter_baton = NULL; 204 *iter_baton = NULL;
228 205
229 return SVN_NO_ERROR; 206 return SVN_NO_ERROR;
230 } 207 }
231 208
232 209
233 /* Common implementation for simple_save_creds and 210 /* Common implementation for simple_save_creds and
234 windows_simple_save_creds. Uses PARAMETERS and REALMSTRING to save 211 windows_simple_save_creds. Uses PARAMETERS and REALMSTRING to save
235 a set of CREDENTIALS to the simple auth provider's username and 212 a set of CREDENTIALS to the simple auth provider's username and
236 password cache. PASSWORD_SET is used to store the password. 213 password cache. PASSWORD_SET is used to store the password.
237 PASSTYPE identifies the type of the cached password. Allocates from POOL. */ 214 PASSTYPE identifies the type of the cached password. Allocates from POOL. */
238 static svn_error_t * 215 svn_error_t *
239 simple_save_creds_helper(svn_boolean_t *saved, 216 svn_auth__simple_save_creds_helper(svn_boolean_t *saved,
240 void *credentials, 217 void *credentials,
241 void *provider_baton, 218 void *provider_baton,
242 apr_hash_t *parameters, 219 apr_hash_t *parameters,
243 const char *realmstring, 220 const char *realmstring,
244 password_set_t password_set, 221 svn_auth__password_set_t password_set,
245 const char *passtype, 222 const char *passtype,
246 apr_pool_t *pool) 223 apr_pool_t *pool)
247 { 224 {
248 svn_auth_cred_simple_t *creds = credentials; 225 svn_auth_cred_simple_t *creds = credentials;
249 apr_hash_t *creds_hash = NULL; 226 apr_hash_t *creds_hash = NULL;
250 const char *config_dir; 227 const char *config_dir;
251 svn_error_t *err; 228 svn_error_t *err;
252 svn_boolean_t dont_store_passwords = 229 svn_boolean_t dont_store_passwords =
253 apr_hash_get(parameters, 230 apr_hash_get(parameters,
254 SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, 231 SVN_AUTH_PARAM_DONT_STORE_PASSWORDS,
255 APR_HASH_KEY_STRING) != NULL; 232 APR_HASH_KEY_STRING) != NULL;
256 const char *store_plaintext_passwords = 233 const char *store_plaintext_passwords =
257 apr_hash_get(parameters, 234 apr_hash_get(parameters,
258 SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS, 235 SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
259 APR_HASH_KEY_STRING); 236 APR_HASH_KEY_STRING);
260 svn_boolean_t non_interactive = apr_hash_get(parameters, 237 svn_boolean_t non_interactive = apr_hash_get(parameters,
261 SVN_AUTH_PARAM_NON_INTERACTIVE, 238 SVN_AUTH_PARAM_NON_INTERACTIVE,
262 APR_HASH_KEY_STRING) != NULL; 239 APR_HASH_KEY_STRING) != NULL;
263 simple_provider_baton_t *b = (simple_provider_baton_t *)provider_baton; 240 simple_provider_baton_t *b = (simple_provider_baton_t *)provider_baton;
264 241
265 svn_boolean_t no_auth_cache = 242 svn_boolean_t no_auth_cache =
266 (! creds->may_save) || (apr_hash_get(parameters, 243 (! creds->may_save) || (apr_hash_get(parameters,
267 SVN_AUTH_PARAM_NO_AUTH_CACHE, 244 SVN_AUTH_PARAM_NO_AUTH_CACHE,
268 APR_HASH_KEY_STRING) != NULL); 245 APR_HASH_KEY_STRING) != NULL);
269 246
270 *saved = FALSE; 247 *saved = FALSE;
271 248
272 if (no_auth_cache) 249 if (no_auth_cache)
273 return SVN_NO_ERROR; 250 return SVN_NO_ERROR;
274 251
275 config_dir = apr_hash_get(parameters, 252 config_dir = apr_hash_get(parameters,
276 SVN_AUTH_PARAM_CONFIG_DIR, 253 SVN_AUTH_PARAM_CONFIG_DIR,
277 APR_HASH_KEY_STRING); 254 APR_HASH_KEY_STRING);
278 255
279 /* Put the username into the credentials hash. */ 256 /* Put the username into the credentials hash. */
280 creds_hash = apr_hash_make(pool); 257 creds_hash = apr_hash_make(pool);
281 apr_hash_set(creds_hash, SVN_AUTH__AUTHFILE_USERNAME_KEY, 258 apr_hash_set(creds_hash, SVN_AUTH__AUTHFILE_USERNAME_KEY,
282 APR_HASH_KEY_STRING, 259 APR_HASH_KEY_STRING,
283 svn_string_create(creds->username, pool)); 260 svn_string_create(creds->username, pool));
284 261
285 /* Don't store passwords in any form if the user has told 262 /* Don't store passwords in any form if the user has told
286 * us not to do so. */ 263 * us not to do so. */
287 if (! dont_store_passwords) 264 if (! dont_store_passwords)
288 { 265 {
289 svn_boolean_t may_save_password = FALSE; 266 svn_boolean_t may_save_password = FALSE;
290 267
291 /* If the password is going to be stored encrypted, go right 268 /* If the password is going to be stored encrypted, go right
292 * ahead and store it to disk. Else determine whether saving 269 * ahead and store it to disk. Else determine whether saving
293 * in plaintext is OK. */ 270 * in plaintext is OK. */
294 if (strcmp(passtype, SVN_AUTH__WINCRYPT_PASSWORD_TYPE) == 0 271 if (strcmp(passtype, SVN_AUTH__WINCRYPT_PASSWORD_TYPE) == 0
295 || strcmp(passtype, SVN_AUTH__KEYCHAIN_PASSWORD_TYPE) == 0) 272 || strcmp(passtype, SVN_AUTH__KEYCHAIN_PASSWORD_TYPE) == 0
273 || strcmp(passtype, SVN_AUTH__KWALLET_PASSWORD_TYPE) == 0)
sussman 2008/05/15 15:14:41 This isn't your fault, Arfrever, but I worry about
296 { 274 {
297 may_save_password = TRUE; 275 may_save_password = TRUE;
298 } 276 }
299 else 277 else
300 { 278 {
301 if (svn_cstring_casecmp(store_plaintext_passwords, 279 if (svn_cstring_casecmp(store_plaintext_passwords,
302 SVN_CONFIG_ASK) == 0) 280 SVN_CONFIG_ASK) == 0)
303 { 281 {
304 if (non_interactive) 282 if (non_interactive)
305 /* In non-interactive mode, the default behaviour is 283 /* In non-interactive mode, the default behaviour is
306 * to not store the password, because it is usually 284 * to not store the password, because it is usually
307 * passed on the command line. */ 285 * passed on the command line. */
308 may_save_password = FALSE; 286 may_save_password = FALSE;
309 else if (b->plaintext_prompt_func) 287 else if (b->plaintext_prompt_func)
310 { 288 {
311 /* We're interactive, and the client provided a 289 /* We're interactive, and the client provided a
312 * prompt callback. So we can ask the user. 290 * prompt callback. So we can ask the user.
313 * 291 *
314 * Check for a cached answer before prompting. */ 292 * Check for a cached answer before prompting. */
315 svn_boolean_t *cached_answer; 293 svn_boolean_t *cached_answer;
316 cached_answer = apr_hash_get(b->plaintext_answers, 294 cached_answer = apr_hash_get(b->plaintext_answers,
317 realmstring, 295 realmstring,
318 APR_HASH_KEY_STRING); 296 APR_HASH_KEY_STRING);
319 if (cached_answer) 297 if (cached_answer)
320 may_save_password = *cached_answer; 298 may_save_password = *cached_answer;
321 else 299 else
322 { 300 {
323 /* Nothing cached for this realm, prompt the user. */ 301 /* Nothing cached for this realm, prompt the user. */
324 SVN_ERR((*b->plaintext_prompt_func)(&may_save_password, 302 SVN_ERR((*b->plaintext_prompt_func)(&may_save_password,
325 realmstring, 303 realmstring,
326 b->prompt_baton, 304 b->prompt_baton,
327 pool)); 305 pool));
328 306
329 /* Cache the user's answer in case we're called again 307 /* Cache the user's answer in case we're called again
330 * for the same realm. 308 * for the same realm.
331 * 309 *
332 * XXX: Hopefully, our caller has passed us 310 * XXX: Hopefully, our caller has passed us
333 * a pool that survives across RA sessions! 311 * a pool that survives across RA sessions!
334 * We use that pool to cache user answers, and 312 * We use that pool to cache user answers, and
335 * we may be called again for the same realm when the 313 * we may be called again for the same realm when the
336 * current RA session is reparented, or when a different 314 * current RA session is reparented, or when a different
337 * RA session using the same realm is opened. 315 * RA session using the same realm is opened.
338 * If the pool does not survive until then, caching 316 * If the pool does not survive until then, caching
339 * won't work, and for some reason the call to 317 * won't work, and for some reason the call to
340 * apr_hash_set() below may even end up crashing in 318 * apr_hash_set() below may even end up crashing in
341 * apr_palloc(). 319 * apr_palloc().
342 */ 320 */
343 cached_answer = apr_palloc(pool, sizeof(svn_boolean_t)); 321 cached_answer = apr_palloc(pool, sizeof(svn_boolean_t));
344 *cached_answer = may_save_password; 322 *cached_answer = may_save_password;
345 apr_hash_set(b->plaintext_answers, realmstring, 323 apr_hash_set(b->plaintext_answers, realmstring,
346 APR_HASH_KEY_STRING, cached_answer); 324 APR_HASH_KEY_STRING, cached_answer);
347 } 325 }
348 } 326 }
349 else 327 else
350 { 328 {
351 /* TODO: We might want to default to not storing if the 329 /* TODO: We might want to default to not storing if the
352 * prompt callback is NULL, i.e. have may_save_password 330 * prompt callback is NULL, i.e. have may_save_password
353 * default to FALSE here, in order to force clients to 331 * default to FALSE here, in order to force clients to
354 * implement the callback. 332 * implement the callback.
355 * 333 *
356 * This would change the semantics of old API though. 334 * This would change the semantics of old API though.
357 * 335 *
358 * So for now, clients that don't implement the callback 336 * So for now, clients that don't implement the callback
359 * and provide no explicit value for 337 * and provide no explicit value for
360 * SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS 338 * SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS
361 * cause unencrypted passwords to be stored by default. 339 * cause unencrypted passwords to be stored by default.
362 * Needless to say, our own client is sane, but who knows 340 * Needless to say, our own client is sane, but who knows
363 * what other clients are doing. 341 * what other clients are doing.
364 */ 342 */
365 may_save_password = TRUE; 343 may_save_password = TRUE;
366 } 344 }
367 } 345 }
368 else if (svn_cstring_casecmp(store_plaintext_passwords, 346 else if (svn_cstring_casecmp(store_plaintext_passwords,
369 SVN_CONFIG_FALSE) == 0) 347 SVN_CONFIG_FALSE) == 0)
370 { 348 {
371 may_save_password = FALSE; 349 may_save_password = FALSE;
372 } 350 }
373 else if (svn_cstring_casecmp(store_plaintext_passwords, 351 else if (svn_cstring_casecmp(store_plaintext_passwords,
374 SVN_CONFIG_TRUE) == 0) 352 SVN_CONFIG_TRUE) == 0)
375 { 353 {
376 may_save_password = TRUE; 354 may_save_password = TRUE;
377 } 355 }
378 else 356 else
379 { 357 {
380 return svn_error_createf 358 return svn_error_createf
381 (SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL, 359 (SVN_ERR_RA_DAV_INVALID_CONFIG_VALUE, NULL,
382 _("Config error: invalid value '%s' for option '%s'"), 360 _("Config error: invalid value '%s' for option '%s'"),
383 store_plaintext_passwords, 361 store_plaintext_passwords,
384 SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS); 362 SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS);
385 } 363 }
386 } 364 }
387 365
388 if (may_save_password) 366 if (may_save_password)
389 { 367 {
390 *saved = password_set(creds_hash, realmstring, 368 *saved = password_set(creds_hash, realmstring,
391 creds->username, creds->password, 369 creds->username, creds->password,
392 non_interactive, pool); 370 non_interactive, pool);
393 if (*saved && passtype) 371 if (*saved && passtype)
394 /* Store the password type with the auth data, so that we 372 /* Store the password type with the auth data, so that we
395 know which provider owns the password. */ 373 know which provider owns the password. */
396 apr_hash_set(creds_hash, SVN_AU