2 * kwallet.cpp: KWallet provider for SVN_AUTH_CRED_*
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 /* ==================================================================== */
34 #include <apr_pools.h>
35 #include <apr_strings.h>
37 #include <dbus/dbus.h>
38 #include <QtCore/QCoreApplication>
39 #include <QtCore/QString>
41 #include <kaboutdata.h>
42 #include <kcmdlineargs.h>
43 #include <kcomponentdata.h>
44 #include <klocalizedstring.h>
48 #include "svn_config.h"
49 #include "svn_error.h"
51 #include "svn_pools.h"
52 #include "svn_string.h"
53 #include "svn_version.h"
55 #include "private/svn_auth_private.h"
57 #include "svn_private_config.h"
60 /*-----------------------------------------------------------------------*/
61 /* KWallet simple provider, puts passwords in KWallet */
62 /*-----------------------------------------------------------------------*/
64 static int q_argc = 1;
65 static char q_argv0[] = "svn"; // Build non-const char * from string constant
66 static char *q_argv[] = { q_argv0 };
69 get_application_name(apr_hash_t *parameters,
72 svn_config_t *config =
73 static_cast<svn_config_t *> (apr_hash_get(parameters,
74 SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG,
75 APR_HASH_KEY_STRING));
76 svn_boolean_t svn_application_name_with_pid;
77 svn_config_get_bool(config,
78 &svn_application_name_with_pid,
79 SVN_CONFIG_SECTION_AUTH,
80 SVN_CONFIG_OPTION_KWALLET_SVN_APPLICATION_NAME_WITH_PID,
82 const char *svn_application_name;
83 if (svn_application_name_with_pid)
85 svn_application_name = apr_psprintf(pool, "Subversion [%ld]", long(getpid()));
89 svn_application_name = "Subversion";
91 return svn_application_name;
95 get_wallet_name(apr_hash_t *parameters)
97 svn_config_t *config =
98 static_cast<svn_config_t *> (apr_hash_get(parameters,
99 SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG,
100 APR_HASH_KEY_STRING));
101 const char *wallet_name;
102 svn_config_get(config,
104 SVN_CONFIG_SECTION_AUTH,
105 SVN_CONFIG_OPTION_KWALLET_WALLET,
107 if (strcmp(wallet_name, "") == 0)
109 return KWallet::Wallet::NetworkWallet();
113 return QString::fromUtf8(wallet_name);
121 const char *wid_env_string = getenv("WINDOWID");
128 err = svn_cstring_atoi64(&wid_env, wid_env_string);
130 svn_error_clear(err);
138 static KWallet::Wallet *
139 get_wallet(QString wallet_name,
140 apr_hash_t *parameters)
142 KWallet::Wallet *wallet =
143 static_cast<KWallet::Wallet *> (apr_hash_get(parameters,
145 APR_HASH_KEY_STRING));
146 if (! wallet && ! apr_hash_get(parameters,
147 "kwallet-opening-failed",
148 APR_HASH_KEY_STRING))
150 wallet = KWallet::Wallet::openWallet(wallet_name, get_wid(),
151 KWallet::Wallet::Synchronous);
155 apr_hash_set(parameters,
162 apr_hash_set(parameters,
163 "kwallet-opening-failed",
171 kwallet_terminate(void *data)
173 apr_hash_t *parameters = static_cast<apr_hash_t *> (data);
174 if (apr_hash_get(parameters, "kwallet-initialized", APR_HASH_KEY_STRING))
176 KWallet::Wallet *wallet = get_wallet(NULL, parameters);
178 apr_hash_set(parameters,
179 "kwallet-initialized",
186 /* Implementation of svn_auth__password_get_t that retrieves
187 the password from KWallet. */
189 kwallet_password_get(svn_boolean_t *done,
190 const char **password,
192 const char *realmstring,
193 const char *username,
194 apr_hash_t *parameters,
195 svn_boolean_t non_interactive,
198 QString wallet_name = get_wallet_name(parameters);
202 if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
209 if (!KWallet::Wallet::isOpen(wallet_name))
212 /* There is a race here: the wallet was open just now, but will
213 it still be open when we come to use it below? */
216 QCoreApplication *app;
220 app = new QCoreApplication(argc, q_argv);
223 KCmdLineArgs::init(q_argc, q_argv,
224 get_application_name(parameters, pool),
226 ki18n(get_application_name(parameters, pool)),
228 ki18n("Version control system"),
229 KCmdLineArgs::CmdLineArgKDE);
230 KComponentData component_data(KCmdLineArgs::aboutData());
231 QString folder = QString::fromUtf8("Subversion");
233 QString::fromUtf8(username) + "@" + QString::fromUtf8(realmstring);
234 if (! KWallet::Wallet::keyDoesNotExist(wallet_name, folder, key))
236 KWallet::Wallet *wallet = get_wallet(wallet_name, parameters);
239 apr_hash_set(parameters,
240 "kwallet-initialized",
243 if (wallet->setFolder(folder))
246 if (wallet->readPassword(key, q_password) == 0)
248 *password = apr_pstrmemdup(pool,
249 q_password.toUtf8().data(),
257 apr_pool_cleanup_register(pool, parameters, kwallet_terminate,
258 apr_pool_cleanup_null);
263 /* Implementation of svn_auth__password_set_t that stores
264 the password in KWallet. */
266 kwallet_password_set(svn_boolean_t *done,
268 const char *realmstring,
269 const char *username,
270 const char *password,
271 apr_hash_t *parameters,
272 svn_boolean_t non_interactive,
275 QString wallet_name = get_wallet_name(parameters);
279 if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
286 if (!KWallet::Wallet::isOpen(wallet_name))
289 /* There is a race here: the wallet was open just now, but will
290 it still be open when we come to use it below? */
293 QCoreApplication *app;
297 app = new QCoreApplication(argc, q_argv);
300 KCmdLineArgs::init(q_argc, q_argv,
301 get_application_name(parameters, pool),
303 ki18n(get_application_name(parameters, pool)),
305 ki18n("Version control system"),
306 KCmdLineArgs::CmdLineArgKDE);
307 KComponentData component_data(KCmdLineArgs::aboutData());
308 QString q_password = QString::fromUtf8(password);
309 QString folder = QString::fromUtf8("Subversion");
310 KWallet::Wallet *wallet = get_wallet(wallet_name, parameters);
313 apr_hash_set(parameters,
314 "kwallet-initialized",
317 if (! wallet->hasFolder(folder))
319 wallet->createFolder(folder);
321 if (wallet->setFolder(folder))
323 QString key = QString::fromUtf8(username) + "@"
324 + QString::fromUtf8(realmstring);
325 if (wallet->writePassword(key, q_password) == 0)
332 apr_pool_cleanup_register(pool, parameters, kwallet_terminate,
333 apr_pool_cleanup_null);
338 /* Get cached encrypted credentials from the simple provider's cache. */
340 kwallet_simple_first_creds(void **credentials,
342 void *provider_baton,
343 apr_hash_t *parameters,
344 const char *realmstring,
347 return svn_auth__simple_creds_cache_get(credentials,
352 kwallet_password_get,
353 SVN_AUTH__KWALLET_PASSWORD_TYPE,
357 /* Save encrypted credentials to the simple provider's cache. */
359 kwallet_simple_save_creds(svn_boolean_t *saved,
361 void *provider_baton,
362 apr_hash_t *parameters,
363 const char *realmstring,
366 return svn_auth__simple_creds_cache_set(saved, credentials,
370 kwallet_password_set,
371 SVN_AUTH__KWALLET_PASSWORD_TYPE,
375 static const svn_auth_provider_t kwallet_simple_provider = {
376 SVN_AUTH_CRED_SIMPLE,
377 kwallet_simple_first_creds,
379 kwallet_simple_save_creds
385 svn_auth_get_kwallet_simple_provider(svn_auth_provider_object_t **provider,
388 svn_auth_provider_object_t *po =
389 static_cast<svn_auth_provider_object_t *> (apr_pcalloc(pool, sizeof(*po)));
391 po->vtable = &kwallet_simple_provider;
397 /*-----------------------------------------------------------------------*/
398 /* KWallet SSL client certificate passphrase provider, */
399 /* puts passphrases in KWallet */
400 /*-----------------------------------------------------------------------*/
402 /* Get cached encrypted credentials from the ssl client cert password
405 kwallet_ssl_client_cert_pw_first_creds(void **credentials,
407 void *provider_baton,
408 apr_hash_t *parameters,
409 const char *realmstring,
412 return svn_auth__ssl_client_cert_pw_cache_get(credentials,
413 iter_baton, provider_baton,
414 parameters, realmstring,
415 kwallet_password_get,
416 SVN_AUTH__KWALLET_PASSWORD_TYPE,
420 /* Save encrypted credentials to the ssl client cert password provider's
423 kwallet_ssl_client_cert_pw_save_creds(svn_boolean_t *saved,
425 void *provider_baton,
426 apr_hash_t *parameters,
427 const char *realmstring,
430 return svn_auth__ssl_client_cert_pw_cache_set(saved, credentials,
431 provider_baton, parameters,
433 kwallet_password_set,
434 SVN_AUTH__KWALLET_PASSWORD_TYPE,
438 static const svn_auth_provider_t kwallet_ssl_client_cert_pw_provider = {
439 SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
440 kwallet_ssl_client_cert_pw_first_creds,
442 kwallet_ssl_client_cert_pw_save_creds
448 svn_auth_get_kwallet_ssl_client_cert_pw_provider
449 (svn_auth_provider_object_t **provider,
452 svn_auth_provider_object_t *po =
453 static_cast<svn_auth_provider_object_t *> (apr_pcalloc(pool, sizeof(*po)));
455 po->vtable = &kwallet_ssl_client_cert_pw_provider;