| OLD | NEW |
|---|---|
| 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 |