signon 8.54

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

signondaemon.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of signon
3 *
4 * Copyright (C) 2009-2010 Nokia Corporation.
5 * Copyright (C) 2013 Canonical Ltd.
6 *
7 * Contact: Aurel Popirtac <ext-aurel.popirtac@nokia.com>
8 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * version 2.1 as published by the Free Software Foundation.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 */
24
25 extern "C" {
26 #include <sys/socket.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 }
30
31 #define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(4, 0, 0)
32
33 #include <QtDebug>
34 #include <QDir>
35 #include <QDBusConnection>
36 #include <QDBusMessage>
37 #include <QDBusMetaType>
38 #include <QPluginLoader>
39 #include <QProcessEnvironment>
40 #include <QSocketNotifier>
41 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
42 #include <QStandardPaths>
43 #endif
44
45 #include "SignOn/misc.h"
46
47 #include "signondaemon.h"
48 #include "signond-common.h"
49 #include "signontrace.h"
50 #include "signondaemonadaptor.h"
51 #include "signonidentity.h"
52 #include "signonauthsession.h"
53 #include "accesscontrolmanagerhelper.h"
54 #include "backupifadaptor.h"
55
56 #define SIGNON_RETURN_IF_CAM_UNAVAILABLE(_ret_arg_) do { \
57 if (m_pCAMManager && !m_pCAMManager->credentialsSystemOpened()) { \
58 setLastError(internalServerErrName, \
59 internalServerErrStr + \
60 QLatin1String("Could not access Signon " \
61 "Database.")); \
62 return _ret_arg_; \
63 } \
64 } while(0)
65
66 #define BACKUP_DIR_NAME() \
67 (QDir::separator() + QLatin1String("backup"))
68
69 using namespace SignOn;
70
71 namespace SignonDaemonNS {
72
73 /* ---------------------- SignonDaemonConfiguration ---------------------- */
74
75 SignonDaemonConfiguration::SignonDaemonConfiguration():
76 m_pluginsDir(QLatin1String(SIGNOND_PLUGINS_DIR)),
77 m_extensionsDir(QLatin1String(SIGNOND_EXTENSIONS_DIR)),
78 m_camConfiguration(),
79 m_daemonTimeout(0), // 0 = no timeout
80 m_identityTimeout(300),//secs
81 m_authSessionTimeout(300)//secs
82 {}
83
84 SignonDaemonConfiguration::~SignonDaemonConfiguration()
85 {
86 TRACE();
87 }
88
89 /*
90 --- Configuration file template ---
91
92 [General]
93 UseSecureStorage=yes
94 StoragePath=~/.signon/
95 ;0 - fatal, 1 - critical(default), 2 - info/debug
96 LoggingLevel=1
97
98 [SecureStorage]
99 FileSystemName=signonfs
100 Size=8
101 FileSystemType=ext2
102
103 [ObjectTimeouts]
104 IdentityTimeout=300
105 AuthSessionTimeout=300
106 */
107 void SignonDaemonConfiguration::load()
108 {
109 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
110
111 //Daemon configuration file
112
113 QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope,
114 environment.value(QLatin1String("SSO_CONFIG_FILE_DIR"),
115 QLatin1String("/etc")));
116
117 QSettings settings(QLatin1String("signond"));
118
119 int loggingLevel =
120 settings.value(QLatin1String("LoggingLevel"), 1).toInt();
121 setLoggingLevel(loggingLevel);
122
123 QString cfgStoragePath =
124 settings.value(QLatin1String("StoragePath")).toString();
125 if (!cfgStoragePath.isEmpty()) {
126 QString storagePath = QDir(cfgStoragePath).path();
127 m_camConfiguration.setStoragePath(storagePath);
128 } else {
129 QString xdgConfigHome = QLatin1String(qgetenv("XDG_CONFIG_HOME"));
130 if (xdgConfigHome.isEmpty())
131 xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
132 m_camConfiguration.setStoragePath(xdgConfigHome +
133 QLatin1String("/signond"));
134 }
135
136 // Secure storage
137
138 // Support legacy setting "UseSecureStorage"
139 QString useSecureStorage =
140 settings.value(QLatin1String("UseSecureStorage")).toString();
141 if (useSecureStorage == QLatin1String("yes") ||
142 useSecureStorage == QLatin1String("true")) {
143 m_camConfiguration.addSetting(QLatin1String("CryptoManager"),
144 QLatin1String("cryptsetup"));
145 }
146
147 settings.beginGroup(QLatin1String("SecureStorage"));
148
149 QVariantMap storageOptions;
150 foreach (const QString &key, settings.childKeys()) {
151 m_camConfiguration.addSetting(key, settings.value(key));
152 }
153
154 settings.endGroup();
155
156 //Timeouts
157 settings.beginGroup(QLatin1String("ObjectTimeouts"));
158
159 bool isOk = false;
160 uint aux = settings.value(QLatin1String("IdentityTimeout")).toUInt(&isOk);
161 if (isOk)
162 m_identityTimeout = aux;
163
164 aux = settings.value(QLatin1String("AuthSessionTimeout")).toUInt(&isOk);
165 if (isOk)
166 m_authSessionTimeout = aux;
167
168 aux = settings.value(QLatin1String("DaemonTimeout")).toUInt(&isOk);
169 if (isOk)
170 m_daemonTimeout = aux;
171
172 settings.endGroup();
173
174 //Environment variables
175
176 int value = 0;
177 if (environment.contains(QLatin1String("SSO_DAEMON_TIMEOUT"))) {
178 value = environment.value(
179 QLatin1String("SSO_DAEMON_TIMEOUT")).toInt(&isOk);
180 if (value > 0 && isOk) m_daemonTimeout = value;
181 }
182
183 if (environment.contains(QLatin1String("SSO_IDENTITY_TIMEOUT"))) {
184 value = environment.value(
185 QLatin1String("SSO_IDENTITY_TIMEOUT")).toInt(&isOk);
186 if (value > 0 && isOk) m_identityTimeout = value;
187 }
188
189 if (environment.contains(QLatin1String("SSO_AUTHSESSION_TIMEOUT"))) {
190 value = environment.value(
191 QLatin1String("SSO_AUTHSESSION_TIMEOUT")).toInt(&isOk);
192 if (value > 0 && isOk) m_authSessionTimeout = value;
193 }
194
195 if (environment.contains(QLatin1String("SSO_LOGGING_LEVEL"))) {
196 value = environment.value(
197 QLatin1String("SSO_LOGGING_LEVEL")).toInt(&isOk);
198 if (isOk)
199 setLoggingLevel(value);
200 }
201
202 QString logOutput = environment.value(QLatin1String("SSO_LOGGING_OUTPUT"),
203 QLatin1String("syslog"));
204 SignonTrace::initialize(logOutput == QLatin1String("syslog") ?
205 SignonTrace::Syslog : SignonTrace::Stdout);
206
207 if (environment.contains(QLatin1String("SSO_STORAGE_PATH"))) {
208 m_camConfiguration.setStoragePath(
209 environment.value(QLatin1String("SSO_STORAGE_PATH")));
210 }
211
212 if (environment.contains(QLatin1String("SSO_PLUGINS_DIR"))) {
213 m_pluginsDir = environment.value(QLatin1String("SSO_PLUGINS_DIR"));
214 }
215
216 if (environment.contains(QLatin1String("SSO_EXTENSIONS_DIR"))) {
217 m_extensionsDir =
218 environment.value(QLatin1String("SSO_EXTENSIONS_DIR"));
219 }
220
221 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
222 QString runtimeDir =
223 QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
224 #else
225 QString runtimeDir = environment.value(QLatin1String("XDG_RUNTIME_DIR"));
226 #endif
227 if (!runtimeDir.isEmpty()) {
228 QString socketFileName =
229 QString::fromLatin1("%1/" SIGNOND_SOCKET_FILENAME).arg(runtimeDir);
230 QDir socketDir = QFileInfo(socketFileName).absoluteDir();
231 if (!socketDir.exists() && !socketDir.mkpath(socketDir.path())) {
232 BLAME() << "Cannot create socket directory" << socketDir;
233 } else {
234 m_busAddress =
235 QString::fromLatin1("unix:path=%1").arg(socketFileName);
236 }
237 } else {
238 BLAME() << "XDG_RUNTIME_DIR unset, disabling p2p bus";
239 }
240 }
241
242 /* ---------------------- SignonDaemon ---------------------- */
243
244 const QString internalServerErrName = SIGNOND_INTERNAL_SERVER_ERR_NAME;
245 const QString internalServerErrStr = SIGNOND_INTERNAL_SERVER_ERR_STR;
246
247 static int sigFd[2];
248
249 SignonDaemon *SignonDaemon::m_instance = NULL;
250
251 SignonDaemon::SignonDaemon(QObject *parent):
252 QObject(parent),
253 m_configuration(0),
254 m_pCAMManager(0),
255 m_dbusServer(0)
256 {
257 // Files created by signond must be unreadable by "other"
258 umask(S_IROTH | S_IWOTH);
259
260 // Register D-Bus meta types
261 qDBusRegisterMetaType<MethodMap>();
262 qDBusRegisterMetaType<MapList>();
263 }
264
265 SignonDaemon::~SignonDaemon()
266 {
267 ::close(sigFd[0]);
268 ::close(sigFd[1]);
269
270 if (m_backup) {
271 exit(0);
272 }
273
274 SignonAuthSession::stopAllAuthSessions();
275 m_storedIdentities.clear();
276
277 if (m_pCAMManager) {
278 m_pCAMManager->closeCredentialsSystem();
279 delete m_pCAMManager;
280 }
281
282 QDBusConnection sessionConnection = QDBusConnection::sessionBus();
283
284 sessionConnection.unregisterObject(SIGNOND_DAEMON_OBJECTPATH
285 + QLatin1String("/Backup"));
286 sessionConnection.unregisterService(SIGNOND_SERVICE
287 + QLatin1String(".Backup"));
288 if (m_backup == false)
289 {
290 sessionConnection.unregisterObject(SIGNOND_DAEMON_OBJECTPATH);
291 sessionConnection.unregisterService(SIGNOND_SERVICE);
292 }
293
294 delete m_configuration;
295
296 QMetaObject::invokeMethod(QCoreApplication::instance(),
297 "quit",
298 Qt::QueuedConnection);
299 }
300
301 void SignonDaemon::setupSignalHandlers()
302 {
303 if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigFd) != 0)
304 BLAME() << "Couldn't create HUP socketpair";
305
306 m_sigSn = new QSocketNotifier(sigFd[1], QSocketNotifier::Read, this);
307 connect(m_sigSn, SIGNAL(activated(int)),
308 this, SLOT(handleUnixSignal()));
309 }
310
311 void SignonDaemon::signalHandler(int signal)
312 {
313 int ret = ::write(sigFd[0], &signal, sizeof(signal));
314 Q_UNUSED(ret);
315 }
316
317 void SignonDaemon::handleUnixSignal()
318 {
319 m_sigSn->setEnabled(false);
320
321 int signal;
322 int ret = read(sigFd[1], &signal, sizeof(signal));
323 Q_UNUSED(ret);
324
325 TRACE() << "signal received: " << signal;
326
327 switch (signal) {
328 case SIGHUP: {
329 TRACE() << "\n\n SIGHUP \n\n";
330 //todo restart daemon
331 deleteLater();
332
333 // reset the m_instance
334 m_instance = NULL;
335 QMetaObject::invokeMethod(instance(),
336 "init",
337 Qt::QueuedConnection);
338 break;
339 }
340 case SIGTERM: {
341 TRACE() << "\n\n SIGTERM \n\n";
342 //gently stop daemon
343 deleteLater();
344 QMetaObject::invokeMethod(QCoreApplication::instance(),
345 "quit",
346 Qt::QueuedConnection);
347 break;
348 }
349 case SIGINT: {
350 TRACE() << "\n\n SIGINT \n\n";
351 //gently stop daemon
352 deleteLater();
353 QMetaObject::invokeMethod(QCoreApplication::instance(),
354 "quit",
355 Qt::QueuedConnection);
356 break;
357 }
358 default: break;
359 }
360
361 m_sigSn->setEnabled(true);
362 }
363
364 SignonDaemon *SignonDaemon::instance()
365 {
366 if (m_instance != NULL)
367 return m_instance;
368
369 QCoreApplication *app = QCoreApplication::instance();
370
371 if (!app)
372 qFatal("SignonDaemon requires a QCoreApplication instance to be "
373 "constructed first");
374
375 TRACE() << "Creating new daemon instance.";
376 m_instance = new SignonDaemon(app);
377 return m_instance;
378 }
379
380 void SignonDaemon::init()
381 {
382 if (!(m_configuration = new SignonDaemonConfiguration))
383 qWarning("SignonDaemon could not create the configuration object.");
384
385 m_configuration->load();
386
387 if (getuid() != 0) {
388 BLAME() << "Failed to SUID root. Secure storage will not be available.";
389 }
390
391 QCoreApplication *app = QCoreApplication::instance();
392 if (!app)
393 qFatal("SignonDaemon requires a QCoreApplication instance to be "
394 "constructed first");
395
396 setupSignalHandlers();
397 m_backup = app->arguments().contains(QLatin1String("-backup"));
398 m_pCAMManager =
399 new CredentialsAccessManager(m_configuration->camConfiguration());
400
401 /* backup dbus interface */
402 QDBusConnection sessionConnection = QDBusConnection::sessionBus();
403
404 if (!sessionConnection.isConnected()) {
405 QDBusError err = sessionConnection.lastError();
406 TRACE() << "Session connection cannot be established:" <<
407 err.errorString(err.type());
408 TRACE() << err.message();
409
410 qFatal("SignonDaemon requires session bus to start working");
411 }
412
413 QDBusConnection::RegisterOptions registerSessionOptions =
414 QDBusConnection::ExportAdaptors;
415
416 (void)new BackupIfAdaptor(this);
417
418 if (!sessionConnection.registerObject(SIGNOND_DAEMON_OBJECTPATH
419 + QLatin1String("/Backup"),
420 this, registerSessionOptions)) {
421 TRACE() << "Object cannot be registered";
422
423 qFatal("SignonDaemon requires to register backup object");
424 }
425
426 if (!sessionConnection.registerService(SIGNOND_SERVICE +
427 QLatin1String(".Backup"))) {
428 QDBusError err = sessionConnection.lastError();
429 TRACE() << "Service cannot be registered: " <<
430 err.errorString(err.type());
431
432 qFatal("SignonDaemon requires to register backup service");
433 }
434
435 if (m_backup) {
436 TRACE() << "Signond initialized in backup mode.";
437 //skip rest of initialization in backup mode
438 return;
439 }
440
441 /* DBus Service init */
442 QDBusConnection connection = SIGNOND_BUS;
443
444 if (!connection.isConnected()) {
445 QDBusError err = connection.lastError();
446 TRACE() << "Connection cannot be established:" <<
447 err.errorString(err.type());
448 TRACE() << err.message();
449
450 qFatal("SignonDaemon requires DBus to start working");
451 }
452
453 QDBusConnection::RegisterOptions registerOptions =
454 QDBusConnection::ExportAllContents;
455
456 (void)new SignonDaemonAdaptor(this);
457 registerOptions = QDBusConnection::ExportAdaptors;
458
459 // p2p connection
460 #ifdef ENABLE_P2P
461 m_dbusServer = new QDBusServer(m_configuration->busAddress(), this);
462 QObject::connect(m_dbusServer,
463 SIGNAL(newConnection(const QDBusConnection &)),
464 this, SLOT(onNewConnection(const QDBusConnection &)));
465 #endif
466
467 // session bus
468 if (!connection.registerObject(SIGNOND_DAEMON_OBJECTPATH,
469 this, registerOptions)) {
470 TRACE() << "Object cannot be registered";
471
472 qFatal("SignonDaemon requires to register daemon's object");
473 }
474
475 if (!connection.registerService(SIGNOND_SERVICE)) {
476 QDBusError err = connection.lastError();
477 TRACE() << "Service cannot be registered: " <<
478 err.errorString(err.type());
479
480 qFatal("SignonDaemon requires to register daemon's service");
481 }
482
483 // handle D-Bus disconnection
484 connection.connect(QString(),
485 QLatin1String("/org/freedesktop/DBus/Local"),
486 QLatin1String("org.freedesktop.DBus.Local"),
487 QLatin1String("Disconnected"),
488 this, SLOT(onDisconnected()));
489
490 initExtensions();
491
492 if (!initStorage())
493 BLAME() << "Signond: Cannot initialize credentials storage.";
494
495 if (m_configuration->daemonTimeout() > 0) {
496 SignonDisposable::invokeOnIdle(m_configuration->daemonTimeout(),
497 this, SLOT(deleteLater()));
498 }
499
500 TRACE() << "Signond SUCCESSFULLY initialized.";
501 }
502
503 void SignonDaemon::onNewConnection(const QDBusConnection &connection)
504 {
505 TRACE() << "New p2p connection" << connection.name();
506 QDBusConnection conn(connection);
507 if (!conn.registerObject(SIGNOND_DAEMON_OBJECTPATH,
508 this, QDBusConnection::ExportAdaptors)) {
509 qFatal("Failed to register SignonDaemon object");
510 }
511 }
512
513 void SignonDaemon::initExtensions()
514 {
515 /* Scan the directory containing signond extensions and attempt loading
516 * all of them.
517 */
518 QDir dir(m_configuration->extensionsDir());
519 QStringList filters(QLatin1String("lib*.so"));
520 QStringList extensionList = dir.entryList(filters, QDir::Files);
521 foreach(const QString &filename, extensionList)
522 initExtension(dir.filePath(filename));
523 }
524
525 void SignonDaemon::initExtension(const QString &filePath)
526 {
527 TRACE() << "Loading plugin " << filePath;
528
529 QPluginLoader pluginLoader(filePath);
530 QObject *plugin = pluginLoader.instance();
531 if (!plugin) {
532 qWarning() << "Couldn't load plugin:" << pluginLoader.errorString();
533 return;
534 }
535
536 /* Check whether the extension implements some useful objects; if not,
537 * unload it. */
538 if (!m_pCAMManager->initExtension(plugin))
539 pluginLoader.unload();
540 }
541
542 bool SignonDaemon::initStorage()
543 {
544 if (!m_pCAMManager->credentialsSystemOpened()) {
545 m_pCAMManager->finalize();
546
547 if (!m_pCAMManager->init()) {
548 BLAME() << "CAM initialization failed";
549 return false;
550 }
551
552 // If encryption is in use this will just open the metadata DB
553 if (!m_pCAMManager->openCredentialsSystem()) {
554 qCritical("Signond: Cannot open CAM credentials system...");
555 return false;
556 }
557 } else {
558 TRACE() << "Secure storage already initialized...";
559 return false;
560 }
561
562 return true;
563 }
564
565 void SignonDaemon::onIdentityStored(SignonIdentity *identity)
566 {
567 m_storedIdentities.insert(identity->id(), identity);
568 }
569
570 void SignonDaemon::onIdentityDestroyed()
571 {
572 SignonIdentity *identity = qobject_cast<SignonIdentity*>(sender());
573 m_storedIdentities.remove(identity->id());
574 }
575
576 void SignonDaemon::watchIdentity(SignonIdentity *identity)
577 {
578 QObject::connect(identity, SIGNAL(stored(SignonIdentity*)),
579 this, SLOT(onIdentityStored(SignonIdentity*)));
580 QObject::connect(identity, SIGNAL(unregistered()),
581 this, SLOT(onIdentityDestroyed()));
582
583 if (identity->id() != SIGNOND_NEW_IDENTITY) {
584 m_storedIdentities.insert(identity->id(), identity);
585 }
586 }
587
588 QObject *SignonDaemon::registerNewIdentity()
589 {
590 clearLastError();
591
592 TRACE() << "Registering new identity:";
593
594 SignonIdentity *identity =
595 SignonIdentity::createIdentity(SIGNOND_NEW_IDENTITY, this);
596
597 Q_ASSERT(identity != NULL);
598 watchIdentity(identity);
599
600 return identity;
601 }
602
603 int SignonDaemon::identityTimeout() const
604 {
605 return (m_configuration == NULL ?
606 300 :
607 m_configuration->identityTimeout());
608 }
609
610 int SignonDaemon::authSessionTimeout() const
611 {
612 return (m_configuration == NULL ?
613 300 :
614 m_configuration->authSessionTimeout());
615 }
616
617 QObject *SignonDaemon::getIdentity(const quint32 id,
618 QVariantMap &identityData)
619 {
620 clearLastError();
621
622 SIGNON_RETURN_IF_CAM_UNAVAILABLE(0);
623
624 TRACE() << "Registering identity:" << id;
625
626 //1st check if the existing identity is in cache
627 SignonIdentity *identity = m_storedIdentities.value(id, NULL);
628
629 //if not create it
630 if (identity == NULL)
631 identity = SignonIdentity::createIdentity(id, this);
632 Q_ASSERT(identity != NULL);
633
634 bool ok;
635 SignonIdentityInfo info = identity->queryInfo(ok, false);
636
637 if (info.isNew())
638 {
639 setLastError(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME,
640 SIGNOND_IDENTITY_NOT_FOUND_ERR_STR);
641 identity->destroy();
642 return 0;
643 }
644
645 watchIdentity(identity);
646 identity->keepInUse();
647
648 identityData = info.toMap();
649
650 TRACE() << "DONE REGISTERING IDENTITY";
651 return identity;
652 }
653
654 QStringList SignonDaemon::queryMethods()
655 {
656 QDir pluginsDir(m_configuration->pluginsDir());
657 //TODO: in the future remove the sym links comment
658 QStringList fileNames = pluginsDir.entryList(
659 QStringList() << QLatin1String("*.so*"),
660 QDir::Files | QDir::NoDotAndDotDot);
661
662 QStringList ret;
663 QString fileName;
664 foreach (fileName, fileNames) {
665 if (fileName.startsWith(QLatin1String("lib"))) {
666 fileName =
667 fileName.mid(3, fileName.indexOf(QLatin1String("plugin")) -3);
668 if ((fileName.length() > 0) && !ret.contains(fileName))
669 ret << fileName;
670 }
671 }
672
673 return ret;
674 }
675
676 QStringList SignonDaemon::queryMechanisms(const QString &method)
677 {
678 clearLastError();
679
680 TRACE() << method;
681
682 QStringList mechs = SignonSessionCore::loadedPluginMethods(method);
683
684 if (!mechs.isEmpty())
685 return mechs;
686
687 PluginProxy *plugin = PluginProxy::createNewPluginProxy(method);
688
689 if (!plugin) {
690 TRACE() << "Could not load plugin of type: " << method;
691 setLastError(SIGNOND_METHOD_NOT_KNOWN_ERR_NAME,
692 SIGNOND_METHOD_NOT_KNOWN_ERR_STR +
693 QString::fromLatin1("Method %1 is not known or could "
694 "not load specific configuration.").
695 arg(method));
696 return QStringList();
697 }
698
699 mechs = plugin->mechanisms();
700 delete plugin;
701
702 return mechs;
703 }
704
705 QList<QVariantMap> SignonDaemon::queryIdentities(const QVariantMap &filter)
706 {
707 clearLastError();
708
709 SIGNON_RETURN_IF_CAM_UNAVAILABLE(QList<QVariantMap>());
710
711 TRACE() << "Querying identities";
712
713 CredentialsDB *db = m_pCAMManager->credentialsDB();
714 if (!db) {
715 qCritical() << Q_FUNC_INFO << m_pCAMManager->lastError();
716 return QList<QVariantMap>();
717 }
718
719 QMap<QString, QString> filterLocal;
720 QMapIterator<QString, QVariant> it(filter);
721 while (it.hasNext()) {
722 it.next();
723 filterLocal.insert(it.key(), it.value().toString());
724 }
725
726 QList<SignonIdentityInfo> credentials = db->credentials(filterLocal);
727
728 if (db->errorOccurred()) {
729 setLastError(internalServerErrName,
730 internalServerErrStr +
731 QLatin1String("Querying database error occurred."));
732 return QList<QVariantMap>();
733 }
734
735 QList<QVariantMap> mapList;
736 foreach (const SignonIdentityInfo &info, credentials) {
737 mapList.append(info.toMap());
738 }
739 return mapList;
740 }
741
742 bool SignonDaemon::clear()
743 {
744 clearLastError();
745
746 SIGNON_RETURN_IF_CAM_UNAVAILABLE(false);
747
748 TRACE() << "\n\n\n Clearing DB\n\n";
749 CredentialsDB *db = m_pCAMManager->credentialsDB();
750 if (!db) {
751 qCritical() << Q_FUNC_INFO << m_pCAMManager->lastError();
752 return false;
753 }
754
755 if (!db->clear()) {
756 setLastError(SIGNOND_INTERNAL_SERVER_ERR_NAME,
757 SIGNOND_INTERNAL_SERVER_ERR_STR +
758 QLatin1String("Database error occurred."));
759 return false;
760 }
761 return true;
762 }
763
764 QObject *SignonDaemon::getAuthSession(const quint32 id,
765 const QString type,
766 pid_t ownerPid)
767 {
768 clearLastError();
769
770 SignonAuthSession *authSession =
771 SignonAuthSession::createAuthSession(id, type, this, ownerPid);
772 if (authSession == NULL) {
773 setLastError(SIGNOND_METHOD_NOT_KNOWN_ERR_NAME,
774 SIGNOND_METHOD_NOT_KNOWN_ERR_STR);
775 return 0;
776 }
777
778 return authSession;
779 }
780
781 void SignonDaemon::eraseBackupDir() const
782 {
783 const CAMConfiguration config = m_configuration->camConfiguration();
784 QString backupRoot = config.m_storagePath + BACKUP_DIR_NAME();
785
786 QDir target(backupRoot);
787 if (!target.exists()) return;
788
789 QStringList targetEntries = target.entryList(QDir::Files);
790 foreach (QString entry, targetEntries) {
791 target.remove(entry);
792 }
793
794 target.rmdir(backupRoot);
795 }
796
797 bool SignonDaemon::copyToBackupDir(const QStringList &fileNames) const
798 {
799 const CAMConfiguration config = m_configuration->camConfiguration();
800 QString backupRoot = config.m_storagePath + BACKUP_DIR_NAME();
801
802 QDir target(backupRoot);
803 if (!target.exists() && !target.mkpath(backupRoot)) {
804 qCritical() << "Cannot create target directory";
805 return false;
806 }
807
808 setUserOwnership(backupRoot);
809
810 /* Now copy the files to be backed up */
811 bool ok = true;
812 foreach (const QString &fileName, fileNames) {
813 /* Remove the target file, if it exists */
814 if (target.exists(fileName))
815 target.remove(fileName);
816
817 /* Copy the source into the target directory */
818 QString source = config.m_storagePath + QDir::separator() + fileName;
819 if (!QFile::exists(source)) continue;
820
821 QString destination = backupRoot + QDir::separator() + fileName;
822 ok = QFile::copy(source, destination);
823 if (!ok) {
824 BLAME() << "Copying" << source << "to" << destination << "failed";
825 break;
826 }
827
828 setUserOwnership(destination);
829 }
830
831 return ok;
832 }
833
834 bool SignonDaemon::copyFromBackupDir(const QStringList &fileNames) const
835 {
836 const CAMConfiguration config = m_configuration->camConfiguration();
837 QString backupRoot = config.m_storagePath + BACKUP_DIR_NAME();
838
839 QDir sourceDir(backupRoot);
840 if (!sourceDir.exists()) {
841 TRACE() << "Backup directory does not exist!";
842 }
843
844 if (!sourceDir.exists(config.m_dbName)) {
845 TRACE() << "Backup does not contain DB:" << config.m_dbName;
846 }
847
848 /* Now restore the files from the backup */
849 bool ok = true;
850 QDir target(config.m_storagePath);
851 QStringList movedFiles, copiedFiles;
852 foreach (const QString &fileName, fileNames) {
853 /* Remove the target file, if it exists */
854 if (target.exists(fileName)) {
855 if (target.rename(fileName, fileName + QLatin1String(".bak")))
856 movedFiles += fileName;
857 }
858
859 /* Copy the source into the target directory */
860 QString source = backupRoot + QDir::separator() + fileName;
861 if (!QFile::exists(source)) {
862 TRACE() << "Ignoring file not present in backup:" << source;
863 continue;
864 }
865
866 QString destination =
867 config.m_storagePath + QDir::separator() + fileName;
868
869 ok = QFile::copy(source, destination);
870 if (ok) {
871 copiedFiles << fileName;
872 } else {
873 qWarning() << "Copy failed for:" << source;
874 break;
875 }
876 }
877
878 if (!ok) {
879 qWarning() << "Restore failed, recovering previous DB";
880
881 foreach (const QString &fileName, copiedFiles) {
882 target.remove(fileName);
883 }
884
885 foreach (const QString &fileName, movedFiles) {
886 if (!target.rename(fileName + QLatin1String(".bak"), fileName)) {
887 qCritical() << "Could not recover:" << fileName;
888 }
889 }
890 } else {
891 /* delete ".bak" files */
892 foreach (const QString &fileName, movedFiles) {
893 target.remove(fileName + QLatin1String(".bak"));
894 }
895
896 }
897 return ok;
898 }
899
900 bool SignonDaemon::createStorageFileTree(const QStringList &backupFiles) const
901 {
902 QString storageDirPath = m_configuration->camConfiguration().m_storagePath;
903 QDir storageDir(storageDirPath);
904
905 if (!storageDir.exists()) {
906 if (!storageDir.mkpath(storageDirPath)) {
907 qCritical() << "Could not create storage dir for backup.";
908 return false;
909 }
910 }
911
912 foreach (const QString &fileName, backupFiles) {
913 if (storageDir.exists(fileName)) continue;
914
915 QString filePath = storageDir.path() + QDir::separator() + fileName;
916 QFile file(filePath);
917 if (!file.open(QIODevice::WriteOnly)) {
918 qCritical() << "Failed to create empty file for backup:" << filePath;
919 return false;
920 } else {
921 file.close();
922 }
923 }
924
925 return true;
926 }
927
928 uchar SignonDaemon::backupStarts()
929 {
930 TRACE() << "backup";
931 if (!m_backup && m_pCAMManager->credentialsSystemOpened())
932 {
933 m_pCAMManager->closeCredentialsSystem();
934 if (m_pCAMManager->credentialsSystemOpened())
935 {
936 qCritical() << "Cannot close credentials database";
937 return 2;
938 }
939 }
940
941 const CAMConfiguration config = m_configuration->camConfiguration();
942
943 /* do backup copy: prepare the list of files to be backed up */
944 QStringList backupFiles;
945 backupFiles << config.m_dbName;
946 backupFiles << m_pCAMManager->backupFiles();
947
948 /* make sure that all the backup files and storage directory exist:
949 create storage dir and empty files if not so, as backup/restore
950 operations must be consistent */
951 if (!createStorageFileTree(backupFiles)) {
952 qCritical() << "Cannot create backup file tree.";
953 return 2;
954 }
955
956 /* perform the copy */
957 eraseBackupDir();
958 if (!copyToBackupDir(backupFiles)) {
959 qCritical() << "Cannot copy database";
960 if (!m_backup)
961 m_pCAMManager->openCredentialsSystem();
962 return 2;
963 }
964
965 if (!m_backup)
966 {
967 //mount file system back
968 if (!m_pCAMManager->openCredentialsSystem()) {
969 qCritical() << "Cannot reopen database";
970 }
971 }
972 return 0;
973 }
974
975 uchar SignonDaemon::backupFinished()
976 {
977 TRACE() << "close";
978
979 eraseBackupDir();
980
981 if (m_backup)
982 {
983 //close daemon
984 TRACE() << "close daemon";
985 this->deleteLater();
986 }
987
988 return 0;
989 }
990
991 /*
992 * Does nothing but start-on-demand
993 * */
994 uchar SignonDaemon::restoreStarts()
995 {
996 TRACE();
997 return 0;
998 }
999
1000 uchar SignonDaemon::restoreFinished()
1001 {
1002 TRACE() << "restore";
1003 //restore requested
1004 if (m_pCAMManager->credentialsSystemOpened())
1005 {
1006 //umount file system
1007 if (!m_pCAMManager->closeCredentialsSystem())
1008 {
1009 qCritical() << "database cannot be closed";
1010 return 2;
1011 }
1012 }
1013
1014 const CAMConfiguration config = m_configuration->camConfiguration();
1015
1016 QStringList backupFiles;
1017 backupFiles << config.m_dbName;
1018 backupFiles << m_pCAMManager->backupFiles();
1019
1020 /* perform the copy */
1021 if (!copyFromBackupDir(backupFiles)) {
1022 qCritical() << "Cannot copy database";
1023 m_pCAMManager->openCredentialsSystem();
1024 return 2;
1025 }
1026
1027 eraseBackupDir();
1028
1029 //TODO check database integrity
1030 if (!m_backup)
1031 {
1032 //mount file system back
1033 if (!m_pCAMManager->openCredentialsSystem())
1034 return 2;
1035 }
1036
1037 return 0;
1038 }
1039
1040 void SignonDaemon::onDisconnected()
1041 {
1042 TRACE() << "Disconnected from session bus: exiting";
1043 this->deleteLater();
1044 QMetaObject::invokeMethod(QCoreApplication::instance(),
1045 "quit",
1046 Qt::QueuedConnection);
1047 }
1048
1049 void SignonDaemon::setLastError(const QString &name, const QString &msg)
1050 {
1051 m_lastErrorName = name;
1052 m_lastErrorMessage = msg;
1053 }
1054
1055 void SignonDaemon::clearLastError()
1056 {
1057 m_lastErrorName = QString();
1058 m_lastErrorMessage = QString();
1059 }
1060
1061 } //namespace SignonDaemonNS
backupifadaptor.h
SignonDaemonNS::internalServerErrName
const QString internalServerErrName
Definition: signondaemon.cpp:244
SignonDaemonNS::CAMConfiguration::addSetting
void addSetting(const QString &key, const QVariant &value)
Definition: credentialsaccessmanager.h:142
SignonDaemonNS::SignonDaemonConfiguration::load
void load()
Definition: signondaemon.cpp:107
SignonDaemonNS::SignonAuthSession
Daemon side representation of authentication session.
Definition: signonauthsession.h:45
SignonDaemonNS::SignonDaemonAdaptor
Definition: signondaemonadaptor.h:39
SignonDaemonNS::CAMConfiguration::m_dbName
QString m_dbName
The database file name.
Definition: credentialsaccessmanager.h:147
BLAME
#define BLAME()
Definition: debug.h:32
signontrace.h
SignonDaemonNS::PluginProxy
Plugin proxy.
Definition: pluginproxy.h:56
SignonDaemonNS::SignonIdentity::destroy
void destroy()
Performs any predestruction operations and the destruction itself.
Definition: signonidentity.cpp:121
BackupIfAdaptor
Definition: backupifadaptor.h:27
SignonDaemonNS::CredentialsDB::lastError
SignOn::CredentialsDBError lastError() const
Definition: credentialsdb.cpp:1335
signond-common.h
SignonDaemonNS::SignonDaemon
Daemon core.
Definition: signondaemon.h:105
SIGNON_RETURN_IF_CAM_UNAVAILABLE
#define SIGNON_RETURN_IF_CAM_UNAVAILABLE(_ret_arg_)
Definition: signondaemon.cpp:56
SignonDaemonNS::CAMConfiguration::setStoragePath
void setStoragePath(const QString &storagePath)
Definition: credentialsaccessmanager.cpp:115
SignonDaemonNS::CAMConfiguration::m_storagePath
QString m_storagePath
The base directory for storage.
Definition: credentialsaccessmanager.h:146
SignonDaemonNS::SignonDaemonConfiguration::~SignonDaemonConfiguration
~SignonDaemonConfiguration()
Definition: signondaemon.cpp:84
SignonDaemonNS::CredentialsDB::credentials
SignonIdentityInfo credentials(const quint32 id, bool queryPassword=true)
Definition: credentialsdb.cpp:1362
SignonDaemonNS::PluginProxy::mechanisms
QStringList mechanisms() const
Definition: pluginproxy.h:72
SignonDaemonNS::CredentialsAccessManager
Main singleton and manager object of the credentials database system.
Definition: credentialsaccessmanager.h:193
BACKUP_DIR_NAME
#define BACKUP_DIR_NAME()
Definition: signondaemon.cpp:66
signondaemonadaptor.h
setUserOwnership
bool setUserOwnership(const QString &filePath)
Definition: misc.cpp:33
signondaemon.h
SignonDaemonNS::internalServerErrStr
const QString internalServerErrStr
Definition: signondaemon.cpp:245
TRACE
#define TRACE()
Definition: debug.h:28
SignonDaemonNS::CredentialsDB::errorOccurred
bool errorOccurred() const
Definition: credentialsdb.h:103
SignonDaemonNS::SignonIdentity
Daemon side representation of identity.
Definition: signonidentity.h:50
signonidentity.h
SignonDaemonNS::SignonIdentityInfo::isNew
bool isNew() const
Definition: signonidentityinfo.h:66
SignonDaemonNS::SignonIdentityInfo
Daemon side representation of identity information.
Definition: signonidentityinfo.h:43
signonauthsession.h
SignonDaemonNS::CredentialsDB
Manages the credentials I/O.
Definition: credentialsdb.h:66
SignonDaemonNS::CAMConfiguration
Configuration object for the CredentialsAccessManager - CAM.
Definition: credentialsaccessmanager.h:104
accesscontrolmanagerhelper.h
Helper class for access control-related functionality.
SignonDaemonNS::CredentialsDB::clear
bool clear()
Definition: credentialsdb.cpp:1439
SignonDaemonNS::SignonDaemonConfiguration
The daemon&#39;s configuration object; loads date from the daemon configuration file. ...
Definition: signondaemon.h:62
SignonDaemonNS::SignonIdentity::queryInfo
SignonIdentityInfo queryInfo(bool &ok, bool queryPassword=true)
Definition: signonidentity.cpp:126
SignonDaemonNS::SignonIdentityInfo::toMap
const QVariantMap toMap() const
Definition: signonidentityinfo.cpp:107
SignonDaemonNS::SignonDisposable::keepInUse
void keepInUse() const
Mark the object as used.
Definition: signondisposable.cpp:57
QMap
Definition: backupifadaptor.h:19
SIGNOND_PLUGINS_DIR
#define SIGNOND_PLUGINS_DIR
Definition: remotepluginprocess.h:50
QList
Definition: backupifadaptor.h:18