syncevolution/src/syncevo/UserInterface.cpp
Patrick Ohly 8da86205df password handling: fixed KWallet support, global configuration option
KWallet support was broken: syncevo-dbus-server checked
KDE_FULL_SESSION to determine whether it should use KWallet instead of
GNOME Keyring. That did not work, because the env variable was not set
for D-Bus daemons.

Automatically detecting KDE users is not possible at the
moment. Instead KDE users have to manually set the new "keyring"
global config property to "KDE" (case insensitive) if the
SyncEvolution installation supports both, because GNOME Keyring is the
default to avoid surprises for traditional users. If only KWallet
support is enabled, then this is not necessary.

"GNOME" and "true/false/1/0/yes/no" can also be set. This has the
advantage that keyring usage can be enabled permanently for the
command line in --daemon=no mode; normally keyrings are not used in
that mode because accessing them can bring up UI dialogs.

It also becomes possible to disable keyring usage in syncevo-dbus-server,
something which couldn't be done before.

The --keyring command line option is still supported, as an alias for
"[--sync-property] keyring=<value>". The default value for --keyring
is true, to match the traditional behavior. In contrast to other sync
properties, setting "keyring" does not require an explicit --run
parameter. Again this is done to mirror traditional usage.

Reading a password also (unintentionally) checked all supported
storages while searching for the password. Now it uses exactly
one storage and falls back to asking for the password directly.

The commit itself also cleans up the code a bit (reformatted, fixed
comments). Choosing the right slot in the password signals is done via
a new InitStateTri parameter which contains the "keyring" setting.
Error checking (unsupported keyring string, --keyring=yes and no
keyring enabled) is done in additional slots which run after all the
regular ones.

Parameter parsing for --sync and --keyring were unified. However,
there is the difference that --keyring has an implicit default value
("yes") and never has an additional parameter, in contrast to --sync,
which always is followed by one.

The new CmdlineTest::testKeyring covers different ways of using
--keyring. It relies on actually invoking keyring backends, something
not done by the default SyncContext UI. Therefore
CmdlineSyncClient+KeyringSyncCmdline were moved into libsyncevolution,
to be used by CmdlineTest.
2012-05-30 09:09:00 +02:00

100 lines
3.6 KiB
C++

/*
* Copyright (C) 2012 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <syncevo/UserInterface.h>
#include <syncevo/declarations.h>
SE_BEGIN_CXX
static bool CheckKeyring(const InitStateTri &keyring)
{
// Default slot, registered with higher priority
// than any other keyring backend. If we get here
// no other backend was chosen by the keyring
// property. If it is a string, then the string
// must have been invalid or unsupported.
if (keyring.wasSet() &&
keyring.getValue() == InitStateTri::VALUE_STRING &&
!keyring.get().empty()) {
SE_THROW("Unsupported value for the \"keyring\" property, no such keyring found: " + keyring.get());
}
return false;
}
static bool PreventPlainText(const InitStateTri &keyring,
const std::string &passwordName)
{
// Another slot, called after CheckKeyring when saving.
// Ensures that if keyring was meant to be used and
// couldn't be used, an error is throw instead of
// silently storing as plain text password.
if (keyring.getValue() != InitStateTri::VALUE_FALSE &&
!keyring.get().empty()) {
SE_THROW(StringPrintf("Cannot save %s as requested in %s."
"This SyncEvolution binary was compiled without support for storing "
"passwords in a keyring or wallet, or none of the backends providing that "
"functionality were usable. Either store passwords in your configuration "
"files or enter them interactively on each program run.\n",
passwordName.c_str(),
(keyring.getValue() == InitStateTri::VALUE_TRUE ||
keyring.get().empty()) ? "a secure keyring" :
keyring.get().c_str()));
}
return false;
}
LoadPasswordSignal &GetLoadPasswordSignal()
{
static class Signal : public LoadPasswordSignal {
public:
Signal() {
connect(100, boost::bind(CheckKeyring, _1));
}
} loadPasswordSignal;
return loadPasswordSignal;
}
SavePasswordSignal &GetSavePasswordSignal()
{
static class Signal : public SavePasswordSignal {
public:
Signal() {
connect(100, boost::bind(CheckKeyring, _1));
connect(101, boost::bind(PreventPlainText, _1, _2));
}
} savePasswordSignal;
return savePasswordSignal;
}
void UserInterface::askPasswordAsync(const std::string &passwordName,
const std::string &descr,
const ConfigPasswordKey &key,
const boost::function<void (const std::string &)> &success,
const boost::function<void ()> &failureException)
{
try {
success(askPassword(passwordName, descr, key));
} catch (...) {
failureException();
}
}
SE_END_CXX