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"
52 #include "svn_pools.h"
53 #include "svn_string.h"
54 #include "svn_version.h"
56 #include "private/svn_auth_private.h"
58 #include "svn_private_config.h"
61 /*-----------------------------------------------------------------------*/
62 /* KWallet simple provider, puts passwords in KWallet */
63 /*-----------------------------------------------------------------------*/
65 static int q_argc = 1;
66 static char q_argv0[] = "svn"; // Build non-const char * from string constant
67 static char *q_argv[] = { q_argv0 };
70 get_application_name(apr_hash_t *parameters,
73 svn_config_t *config =
74 static_cast<svn_config_t *> (apr_hash_get(parameters,
75 SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG,
76 APR_HASH_KEY_STRING));
77 svn_boolean_t svn_application_name_with_pid;
78 svn_config_get_bool(config,
79 &svn_application_name_with_pid,
80 SVN_CONFIG_SECTION_AUTH,
81 SVN_CONFIG_OPTION_KWALLET_SVN_APPLICATION_NAME_WITH_PID,
83 const char *svn_application_name;
84 if (svn_application_name_with_pid)
86 svn_application_name = apr_psprintf(pool, "Subversion [%ld]", long(getpid()));
90 svn_application_name = "Subversion";
92 return svn_application_name;
96 get_wallet_name(apr_hash_t *parameters)
98 svn_config_t *config =
99 static_cast<svn_config_t *> (apr_hash_get(parameters,
100 SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG,
101 APR_HASH_KEY_STRING));
102 const char *wallet_name;
103 svn_config_get(config,
105 SVN_CONFIG_SECTION_AUTH,
106 SVN_CONFIG_OPTION_KWALLET_WALLET,
108 if (strcmp(wallet_name, "") == 0)
110 return KWallet::Wallet::NetworkWallet();
114 return QString::fromUtf8(wallet_name);
122 const char *wid_env_string = getenv("WINDOWID");
129 err = svn_cstring_atoi64(&wid_env, wid_env_string);
131 svn_error_clear(err);
139 /* Forward definition */
141 kwallet_terminate(void *data);
143 static KWallet::Wallet *
144 get_wallet(QString wallet_name,
145 apr_hash_t *parameters)
147 KWallet::Wallet *wallet =
148 static_cast<KWallet::Wallet *> (svn_hash_gets(parameters,
150 if (! wallet && ! svn_hash_gets(parameters, "kwallet-opening-failed"))
152 wallet = KWallet::Wallet::openWallet(wallet_name, get_wid(),
153 KWallet::Wallet::Synchronous);
157 svn_hash_sets(parameters, "kwallet-wallet", wallet);
159 apr_pool_cleanup_register(apr_hash_pool_get(parameters),
160 parameters, kwallet_terminate,
161 apr_pool_cleanup_null);
163 svn_hash_sets(parameters, "kwallet-initialized", "");
167 svn_hash_sets(parameters, "kwallet-opening-failed", "");
174 kwallet_terminate(void *data)
176 apr_hash_t *parameters = static_cast<apr_hash_t *> (data);
177 if (svn_hash_gets(parameters, "kwallet-initialized"))
179 KWallet::Wallet *wallet = get_wallet(NULL, parameters);
181 svn_hash_sets(parameters, "kwallet-wallet", NULL);
182 svn_hash_sets(parameters, "kwallet-initialized", NULL);
187 /* Implementation of svn_auth__password_get_t that retrieves
188 the password from KWallet. */
190 kwallet_password_get(svn_boolean_t *done,
191 const char **password,
193 const char *realmstring,
194 const char *username,
195 apr_hash_t *parameters,
196 svn_boolean_t non_interactive,
199 QString wallet_name = get_wallet_name(parameters);
203 if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
210 if (!KWallet::Wallet::isOpen(wallet_name))
213 /* There is a race here: the wallet was open just now, but will
214 it still be open when we come to use it below? */
217 QCoreApplication *app;
221 app = new QCoreApplication(argc, q_argv);
224 KCmdLineArgs::init(q_argc, q_argv,
225 get_application_name(parameters, pool),
227 ki18n(get_application_name(parameters, pool)),
229 ki18n("Version control system"),
230 KCmdLineArgs::CmdLineArgKDE);
231 KComponentData component_data(KCmdLineArgs::aboutData());
232 QString folder = QString::fromUtf8("Subversion");
234 QString::fromUtf8(username) + "@" + QString::fromUtf8(realmstring);
235 if (! KWallet::Wallet::keyDoesNotExist(wallet_name, folder, key))
237 KWallet::Wallet *wallet = get_wallet(wallet_name, parameters);
240 if (wallet->setFolder(folder))
243 if (wallet->readPassword(key, q_password) == 0)
245 *password = apr_pstrmemdup(pool,
246 q_password.toUtf8().data(),
257 /* Implementation of svn_auth__password_set_t that stores
258 the password in KWallet. */
260 kwallet_password_set(svn_boolean_t *done,
262 const char *realmstring,
263 const char *username,
264 const char *password,
265 apr_hash_t *parameters,
266 svn_boolean_t non_interactive,
269 QString wallet_name = get_wallet_name(parameters);
273 if (! dbus_bus_get(DBUS_BUS_SESSION, NULL))
280 if (!KWallet::Wallet::isOpen(wallet_name))
283 /* There is a race here: the wallet was open just now, but will
284 it still be open when we come to use it below? */
287 QCoreApplication *app;
291 app = new QCoreApplication(argc, q_argv);
294 KCmdLineArgs::init(q_argc, q_argv,
295 get_application_name(parameters, pool),
297 ki18n(get_application_name(parameters, pool)),
299 ki18n("Version control system"),
300 KCmdLineArgs::CmdLineArgKDE);
301 KComponentData component_data(KCmdLineArgs::aboutData());
302 QString q_password = QString::fromUtf8(password);
303 QString folder = QString::fromUtf8("Subversion");
304 KWallet::Wallet *wallet = get_wallet(wallet_name, parameters);
307 if (! wallet->hasFolder(folder))
309 wallet->createFolder(folder);
311 if (wallet->setFolder(folder))
313 QString key = QString::fromUtf8(username) + "@"
314 + QString::fromUtf8(realmstring);
315 if (wallet->writePassword(key, q_password) == 0)
325 /* Get cached encrypted credentials from the simple provider's cache. */
327 kwallet_simple_first_creds(void **credentials,
329 void *provider_baton,
330 apr_hash_t *parameters,
331 const char *realmstring,
334 return svn_auth__simple_creds_cache_get(credentials,
339 kwallet_password_get,
340 SVN_AUTH__KWALLET_PASSWORD_TYPE,
344 /* Save encrypted credentials to the simple provider's cache. */
346 kwallet_simple_save_creds(svn_boolean_t *saved,
348 void *provider_baton,
349 apr_hash_t *parameters,
350 const char *realmstring,
353 return svn_auth__simple_creds_cache_set(saved, credentials,
357 kwallet_password_set,
358 SVN_AUTH__KWALLET_PASSWORD_TYPE,
362 static const svn_auth_provider_t kwallet_simple_provider = {
363 SVN_AUTH_CRED_SIMPLE,
364 kwallet_simple_first_creds,
366 kwallet_simple_save_creds
372 svn_auth_get_kwallet_simple_provider(svn_auth_provider_object_t **provider,
375 svn_auth_provider_object_t *po =
376 static_cast<svn_auth_provider_object_t *> (apr_pcalloc(pool, sizeof(*po)));
378 po->vtable = &kwallet_simple_provider;
384 /*-----------------------------------------------------------------------*/
385 /* KWallet SSL client certificate passphrase provider, */
386 /* puts passphrases in KWallet */
387 /*-----------------------------------------------------------------------*/
389 /* Get cached encrypted credentials from the ssl client cert password
392 kwallet_ssl_client_cert_pw_first_creds(void **credentials,
394 void *provider_baton,
395 apr_hash_t *parameters,
396 const char *realmstring,
399 return svn_auth__ssl_client_cert_pw_cache_get(credentials,
400 iter_baton, provider_baton,
401 parameters, realmstring,
402 kwallet_password_get,
403 SVN_AUTH__KWALLET_PASSWORD_TYPE,
407 /* Save encrypted credentials to the ssl client cert password provider's
410 kwallet_ssl_client_cert_pw_save_creds(svn_boolean_t *saved,
412 void *provider_baton,
413 apr_hash_t *parameters,
414 const char *realmstring,
417 return svn_auth__ssl_client_cert_pw_cache_set(saved, credentials,
418 provider_baton, parameters,
420 kwallet_password_set,
421 SVN_AUTH__KWALLET_PASSWORD_TYPE,
425 static const svn_auth_provider_t kwallet_ssl_client_cert_pw_provider = {
426 SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
427 kwallet_ssl_client_cert_pw_first_creds,
429 kwallet_ssl_client_cert_pw_save_creds
435 svn_auth_get_kwallet_ssl_client_cert_pw_provider
436 (svn_auth_provider_object_t **provider,
439 svn_auth_provider_object_t *po =
440 static_cast<svn_auth_provider_object_t *> (apr_pcalloc(pool, sizeof(*po)));
442 po->vtable = &kwallet_ssl_client_cert_pw_provider;