signon  8.58
credentialsaccessmanager.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /*
00003  * This file is part of signon
00004  *
00005  * Copyright (C) 2009-2010 Nokia Corporation.
00006  * Copyright (C) 2011 Intel Corporation.
00007  *
00008  * Contact: Aurel Popirtac <mailto:ext-Aurel.Popirtac@nokia.com>
00009  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
00010  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
00011  *
00012  * This library is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public License
00014  * version 2.1 as published by the Free Software Foundation.
00015  *
00016  * This library is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA
00025  */
00026 
00027 #define SIGNON_ENABLE_UNSTABLE_APIS
00028 #include "credentialsaccessmanager.h"
00029 
00030 #include "default-crypto-manager.h"
00031 #include "default-key-authorizer.h"
00032 #include "default-secrets-storage.h"
00033 #include "signond-common.h"
00034 
00035 #include "SignOn/ExtensionInterface"
00036 #include "SignOn/misc.h"
00037 
00038 #include <QFile>
00039 #include <QBuffer>
00040 
00041 
00042 #define RETURN_IF_NOT_INITIALIZED(return_value)                  \
00043     do {                                                         \
00044         if (!m_isInitialized) {                                  \
00045             m_error = NotInitialized;                            \
00046             TRACE() << "CredentialsAccessManager not initialized."; \
00047             return return_value;                                \
00048         }                                                       \
00049     } while (0)
00050 
00051 using namespace SignonDaemonNS;
00052 using namespace SignOn;
00053 
00054 /* ---------------------- CAMConfiguration ---------------------- */
00055 
00056 CAMConfiguration::CAMConfiguration():
00057     m_dbName(QLatin1String(signonDefaultDbName)),
00058     m_secretsDbName(QLatin1String(signonDefaultSecretsDbName)),
00059     m_encryptionPassphrase(QByteArray())
00060 {
00061     setStoragePath(QLatin1String(signonDefaultStoragePath));
00062 }
00063 
00064 void CAMConfiguration::serialize(QIODevice *device)
00065 {
00066     if (device == NULL)
00067         return;
00068 
00069     if (!device->open(QIODevice::ReadWrite)) {
00070         return;
00071     }
00072 
00073     QString buffer;
00074     QTextStream stream(&buffer);
00075     stream << "\n\n====== Credentials Access Manager Configuration ======\n\n";
00076     const char *usingEncryption = useEncryption() ? "true" : "false";
00077     stream << "Using encryption: " << usingEncryption << '\n';
00078     stream << "Metadata DB path: " << metadataDBPath() << '\n';
00079     stream << "Cryptomanager name: " << cryptoManagerName() << '\n';
00080     stream << "ACL manager name: " << accessControlManagerName() << '\n';
00081     stream << "Secrets storage name: " << secretsStorageName() << '\n';
00082     stream << "======================================================\n\n";
00083     device->write(buffer.toUtf8());
00084     device->close();
00085 }
00086 
00087 QString CAMConfiguration::metadataDBPath() const
00088 {
00089     return m_storagePath + QDir::separator() + m_dbName;
00090 }
00091 
00092 QString CAMConfiguration::cryptoManagerName() const
00093 {
00094     return m_settings.value(QLatin1String("CryptoManager")).toString();
00095 }
00096 
00097 QString CAMConfiguration::accessControlManagerName() const
00098 {
00099     return m_settings.value(QLatin1String("AccessControlManager")).toString();
00100 }
00101 
00102 bool CAMConfiguration::useEncryption() const
00103 {
00104     return cryptoManagerName() != QLatin1String("default");
00105 }
00106 
00107 QString CAMConfiguration::secretsStorageName() const
00108 {
00109     return m_settings.value(QLatin1String("SecretsStorage")).toString();
00110 }
00111 
00112 void CAMConfiguration::setStoragePath(const QString &storagePath) {
00113     m_storagePath = storagePath;
00114     if (m_storagePath.startsWith(QLatin1Char('~')))
00115         m_storagePath.replace(0, 1, QDir::homePath());
00116     // CryptoSetup extensions are given the m_settings dictionary only
00117     addSetting(QLatin1String("StoragePath"), m_storagePath);
00118 }
00119 
00120 /* ---------------------- CredentialsAccessManager ---------------------- */
00121 
00122 CredentialsAccessManager *CredentialsAccessManager::m_pInstance = NULL;
00123 
00124 CredentialsAccessManager::CredentialsAccessManager(
00125                                           const CAMConfiguration &configuration,
00126                                           QObject *parent):
00127     QObject(parent),
00128     m_isInitialized(false),
00129     m_systemOpened(false),
00130     m_error(NoError),
00131     keyManagers(),
00132     m_pCredentialsDB(NULL),
00133     m_cryptoManager(NULL),
00134     m_keyHandler(NULL),
00135     m_keyAuthorizer(NULL),
00136     m_secretsStorage(NULL),
00137     m_CAMConfiguration(configuration),
00138     m_acManager(NULL),
00139     m_acManagerHelper(NULL)
00140 {
00141     if (!m_pInstance) {
00142         m_pInstance = this;
00143     } else {
00144         BLAME() << "Creating a second instance of the CAM";
00145     }
00146 
00147     m_keyHandler = new SignOn::KeyHandler(this);
00148 }
00149 
00150 CredentialsAccessManager::~CredentialsAccessManager()
00151 {
00152     closeCredentialsSystem();
00153 
00154     m_pInstance = NULL;
00155 }
00156 
00157 CredentialsAccessManager *CredentialsAccessManager::instance()
00158 {
00159     return m_pInstance;
00160 }
00161 
00162 void CredentialsAccessManager::finalize()
00163 {
00164     TRACE() << "Enter";
00165 
00166     if (m_systemOpened)
00167         closeCredentialsSystem();
00168 
00169     // Disconnect all key managers
00170     foreach (SignOn::AbstractKeyManager *keyManager, keyManagers)
00171         keyManager->disconnect();
00172 
00173     m_isInitialized = false;
00174     m_error = NoError;
00175 }
00176 
00177 bool CredentialsAccessManager::init()
00178 {
00179     if (m_isInitialized) {
00180         TRACE() << "CAM already initialized.";
00181         m_error = AlreadyInitialized;
00182         return false;
00183     }
00184 
00185     QBuffer config;
00186     m_CAMConfiguration.serialize(&config);
00187     TRACE() << "Initializing CredentialsAccessManager with configuration: " <<
00188         config.data();
00189 
00190     if (!createStorageDir()) {
00191         BLAME() << "Failed to create storage directory.";
00192         return false;
00193     }
00194 
00195     if (m_secretsStorage == 0) {
00196         QString name = m_CAMConfiguration.secretsStorageName();
00197         if (!name.isEmpty() && name != QLatin1String("default")) {
00198             BLAME() << "Couldn't load SecretsStorage:" << name;
00199         }
00200         TRACE() << "No SecretsStorage set, using default (dummy)";
00201         m_secretsStorage = new DefaultSecretsStorage(this);
00202     }
00203 
00204     //Initialize AccessControlManager
00205     if (m_acManager == 0) {
00206         QString name = m_CAMConfiguration.accessControlManagerName();
00207         if (!name.isEmpty() && name != QLatin1String("default")) {
00208             BLAME() << "Couldn't load AccessControlManager:" << name;
00209         }
00210         TRACE() << "No AccessControlManager set, using default (dummy)";
00211         m_acManager = new SignOn::AbstractAccessControlManager(this);
00212     }
00213 
00214     //Initialize AccessControlManagerHelper
00215     if (m_acManagerHelper == 0) {
00216         m_acManagerHelper = new AccessControlManagerHelper(m_acManager);
00217     }
00218 
00219     //Initialize CryptoManager
00220     if (m_cryptoManager == 0) {
00221         QString name = m_CAMConfiguration.cryptoManagerName();
00222         if (!name.isEmpty() && name != QLatin1String("default")) {
00223             BLAME() << "Couldn't load CryptoManager:" << name;
00224         }
00225         TRACE() << "No CryptoManager set, using default (dummy)";
00226         m_cryptoManager = new DefaultCryptoManager(this);
00227     }
00228     QObject::connect(m_cryptoManager, SIGNAL(fileSystemMounted()),
00229                      this, SLOT(onEncryptedFSMounted()));
00230     QObject::connect(m_cryptoManager, SIGNAL(fileSystemUnmounting()),
00231                      this, SLOT(onEncryptedFSUnmounting()));
00232     m_cryptoManager->initialize(m_CAMConfiguration.m_settings);
00233 
00234     /* This check is an optimization: instantiating the KeyAuthorizer is
00235      * probably not harmful if useEncryption() is false, but it's certainly
00236      * useless. */
00237     if (m_CAMConfiguration.useEncryption()) {
00238         if (m_keyAuthorizer == 0) {
00239             TRACE() << "No key authorizer set, using default";
00240             m_keyAuthorizer = new DefaultKeyAuthorizer(m_keyHandler, this);
00241         }
00242         QObject::connect(m_keyAuthorizer,
00243                          SIGNAL(keyAuthorizationQueried(const SignOn::Key,int)),
00244                          this,
00245                          SLOT(onKeyAuthorizationQueried(const SignOn::Key,int)));
00246 
00247         /* These signal connections should be done after instantiating the
00248          * KeyAuthorizer, so that the KeyAuthorizer's slot will be called
00249          * first (or we could connect to them in queued mode)
00250          */
00251         QObject::connect(m_keyHandler, SIGNAL(ready()),
00252                          this, SIGNAL(credentialsSystemReady()));
00253         QObject::connect(m_keyHandler, SIGNAL(keyInserted(SignOn::Key)),
00254                          this, SLOT(onKeyInserted(SignOn::Key)));
00255         QObject::connect(m_keyHandler,
00256                          SIGNAL(lastAuthorizedKeyRemoved(SignOn::Key)),
00257                          this,
00258                          SLOT(onLastAuthorizedKeyRemoved(SignOn::Key)));
00259         QObject::connect(m_keyHandler, SIGNAL(keyRemoved(SignOn::Key)),
00260                          this, SLOT(onKeyRemoved(SignOn::Key)));
00261         m_keyHandler->initialize(m_cryptoManager, keyManagers);
00262     }
00263 
00264     m_isInitialized = true;
00265     m_error = NoError;
00266 
00267     TRACE() << "CredentialsAccessManager successfully initialized...";
00268     return true;
00269 }
00270 
00271 void CredentialsAccessManager::addKeyManager(
00272     SignOn::AbstractKeyManager *keyManager)
00273 {
00274     keyManagers.append(keyManager);
00275 }
00276 
00277 bool CredentialsAccessManager::initExtension(QObject *plugin)
00278 {
00279     bool extensionInUse = false;
00280 
00281     SignOn::ExtensionInterface *extension;
00282     SignOn::ExtensionInterface2 *extension2;
00283     SignOn::ExtensionInterface3 *extension3;
00284 
00285     extension3 = qobject_cast<SignOn::ExtensionInterface3 *>(plugin);
00286 
00287     if (extension3 != 0)
00288         extension2 = extension3;
00289     else
00290         extension2 = qobject_cast<SignOn::ExtensionInterface2 *>(plugin);
00291 
00292     if (extension2 != 0)
00293         extension = extension2;
00294     else
00295         extension = qobject_cast<SignOn::ExtensionInterface *>(plugin);
00296 
00297     if (extension == 0) {
00298         qWarning() << "Plugin instance is not an ExtensionInterface";
00299         return false;
00300     }
00301 
00302     SignOn::AbstractKeyManager *keyManager = extension->keyManager(this);
00303     if (keyManager) {
00304         addKeyManager(keyManager);
00305         extensionInUse = true;
00306     }
00307 
00308     /* Check if the extension implements the new interface and provides a key
00309      * authorizer. */
00310     if (extension2 != 0) {
00311         SignOn::AbstractKeyAuthorizer *keyAuthorizer =
00312             extension2->keyAuthorizer(m_keyHandler, this);
00313         if (keyAuthorizer != 0) {
00314             if (m_keyAuthorizer == 0) {
00315                 m_keyAuthorizer = keyAuthorizer;
00316                 extensionInUse = true;
00317             } else {
00318                 TRACE() << "Key authorizer already set";
00319                 delete keyAuthorizer;
00320             }
00321         }
00322     }
00323 
00324     if (extension3 != 0) {
00325         /* Instantiate this plugin's CryptoManager only if it's the plugin
00326          * requested in the config file. */
00327         if (m_CAMConfiguration.cryptoManagerName().isEmpty() ||
00328             plugin->objectName() == m_CAMConfiguration.cryptoManagerName()) {
00329             SignOn::AbstractCryptoManager *cryptoManager =
00330                 extension3->cryptoManager(this);
00331             if (cryptoManager != 0) {
00332                 if (m_cryptoManager == 0) {
00333                     m_cryptoManager = cryptoManager;
00334                     extensionInUse = true;
00335                 } else {
00336                     TRACE() << "Crypto manager already set";
00337                     delete cryptoManager;
00338                 }
00339             }
00340         }
00341 
00342         if (m_CAMConfiguration.secretsStorageName().isEmpty() ||
00343             plugin->objectName() == m_CAMConfiguration.secretsStorageName()) {
00344             SignOn::AbstractSecretsStorage *secretsStorage =
00345                 extension3->secretsStorage(this);
00346             if (secretsStorage != 0) {
00347                 if (m_secretsStorage == 0) {
00348                     m_secretsStorage = secretsStorage;
00349                     extensionInUse = true;
00350                 } else {
00351                     TRACE() << "SecretsStorage already set";
00352                     delete secretsStorage;
00353                 }
00354             }
00355         }
00356 
00357         /* Instantiate this plugin's AccessControlManager only if it's the
00358          * plugin requested in the config file. */
00359         if (m_CAMConfiguration.accessControlManagerName().isEmpty() ||
00360             plugin->objectName() ==
00361             m_CAMConfiguration.accessControlManagerName()) {
00362             SignOn::AbstractAccessControlManager *acManager =
00363                 extension3->accessControlManager(this);
00364             if (acManager != 0) {
00365                 if (m_acManager == 0) {
00366                     m_acManager = acManager;
00367                     extensionInUse = true;
00368                 } else {
00369                     TRACE() << "Access control manager already set";
00370                     delete acManager;
00371                 }
00372             }
00373         }
00374     }
00375     return extensionInUse;
00376 }
00377 
00378 QStringList CredentialsAccessManager::backupFiles() const
00379 {
00380     QStringList files;
00381 
00382     files << m_cryptoManager->backupFiles();
00383     return files;
00384 }
00385 
00386 bool CredentialsAccessManager::openSecretsDB()
00387 {
00388     if (!m_cryptoManager->fileSystemIsMounted()) {
00389         /* Do not attempt to mount the FS; we know that it will be mounted
00390          * automatically, as soon as some encryption keys are provided */
00391         m_error = CredentialsDbNotMounted;
00392         return false;
00393     }
00394 
00395     QString dbPath = m_cryptoManager->fileSystemMountPath()
00396         + QDir::separator()
00397         + m_CAMConfiguration.m_secretsDbName;
00398 
00399     TRACE() << "Database name: [" << dbPath << "]";
00400 
00401     if (!m_pCredentialsDB->openSecretsDB(dbPath))
00402         return false;
00403 
00404     m_error = NoError;
00405     return true;
00406 }
00407 
00408 bool CredentialsAccessManager::isSecretsDBOpen()
00409 {
00410     return m_pCredentialsDB->isSecretsDBOpen();
00411 }
00412 
00413 bool CredentialsAccessManager::closeSecretsDB()
00414 {
00415     m_pCredentialsDB->closeSecretsDB();
00416 
00417     if (!m_cryptoManager->unmountFileSystem()) {
00418         m_error = CredentialsDbUnmountFailed;
00419         return false;
00420     }
00421 
00422     return true;
00423 }
00424 
00425 bool CredentialsAccessManager::createStorageDir()
00426 {
00427     QString dbPath = m_CAMConfiguration.metadataDBPath();
00428 
00429     QFileInfo fileInfo(dbPath);
00430     if (!fileInfo.exists()) {
00431         QDir storageDir(fileInfo.dir());
00432         if (!storageDir.mkpath(storageDir.path())) {
00433             BLAME() << "Could not create storage directory:" <<
00434                 storageDir.path();
00435             m_error = CredentialsDbSetupFailed;
00436             return false;
00437         }
00438         setUserOwnership(storageDir.path());
00439     }
00440     return true;
00441 
00442 }
00443 bool CredentialsAccessManager::openMetaDataDB()
00444 {
00445     QString dbPath = m_CAMConfiguration.metadataDBPath();
00446 
00447     m_pCredentialsDB = new CredentialsDB(dbPath, m_secretsStorage);
00448 
00449     if (!m_pCredentialsDB->init()) {
00450         m_error = CredentialsDbConnectionError;
00451         return false;
00452     }
00453 
00454     return true;
00455 }
00456 
00457 void CredentialsAccessManager::closeMetaDataDB()
00458 {
00459     if (m_pCredentialsDB) {
00460         delete m_pCredentialsDB;
00461         m_pCredentialsDB = NULL;
00462     }
00463 }
00464 
00465 bool CredentialsAccessManager::openCredentialsSystem()
00466 {
00467     RETURN_IF_NOT_INITIALIZED(false);
00468 
00469     if (!openMetaDataDB()) {
00470         BLAME() << "Couldn't open metadata DB!";
00471         return false;
00472     }
00473 
00474     m_systemOpened = true;
00475 
00476     if (m_cryptoManager->fileSystemIsMounted()) {
00477         if (!openSecretsDB()) {
00478             BLAME() << "Failed to open secrets DB.";
00479             /* Even if the secrets DB couldn't be opened, signond is still
00480              * usable: that's why we return "true" anyways. */
00481         }
00482     } else {
00483         /* The secrets DB will be opened as soon as the encrypted FS is
00484          * mounted.
00485          */
00486         m_cryptoManager->mountFileSystem();
00487     }
00488 
00489     return true;
00490 }
00491 
00492 bool CredentialsAccessManager::closeCredentialsSystem()
00493 {
00494     RETURN_IF_NOT_INITIALIZED(false);
00495 
00496     if (!credentialsSystemOpened())
00497         return true;
00498 
00499     bool allClosed = true;
00500     if (isSecretsDBOpen() && !closeSecretsDB())
00501         allClosed = false;
00502 
00503     closeMetaDataDB();
00504 
00505     m_error = NoError;
00506     m_systemOpened = false;
00507     return allClosed;
00508 }
00509 
00510 bool CredentialsAccessManager::deleteCredentialsSystem()
00511 {
00512     RETURN_IF_NOT_INITIALIZED(false);
00513 
00514     if (m_systemOpened && !closeCredentialsSystem()) {
00515         /* The close operation failed: we cannot proceed */
00516         return false;
00517     }
00518 
00519     BLAME() << "Not implemented";
00520     return false;
00521 }
00522 
00523 CredentialsDB *CredentialsAccessManager::credentialsDB() const
00524 {
00525     RETURN_IF_NOT_INITIALIZED(NULL);
00526 
00527     return m_pCredentialsDB;
00528 }
00529 
00530 bool CredentialsAccessManager::isCredentialsSystemReady() const
00531 {
00532     return (m_keyHandler != 0) ? m_keyHandler->isReady() : true;
00533 }
00534 
00535 void CredentialsAccessManager::onKeyInserted(const SignOn::Key key)
00536 {
00537     TRACE() << "Key inserted.";
00538 
00539     if (!m_keyHandler->keyIsAuthorized(key))
00540         m_keyAuthorizer->queryKeyAuthorization(
00541             key, AbstractKeyAuthorizer::KeyInserted);
00542 }
00543 
00544 void CredentialsAccessManager::onLastAuthorizedKeyRemoved(const SignOn::Key key)
00545 {
00546     Q_UNUSED(key);
00547     TRACE() << "All keys disabled. Closing secure storage.";
00548     if (isSecretsDBOpen() || m_cryptoManager->fileSystemIsMounted())
00549         if (!closeSecretsDB())
00550             BLAME() << "Error occurred while closing secure storage.";
00551 }
00552 
00553 void CredentialsAccessManager::onKeyRemoved(const SignOn::Key key)
00554 {
00555     TRACE() << "Key removed.";
00556 
00557     if (m_keyHandler->keyIsAuthorized(key)) {
00558         if (!m_keyHandler->revokeKeyAuthorization(key)) {
00559             BLAME() << "Revoking key authorization failed";
00560         }
00561     }
00562 }
00563 
00564 void CredentialsAccessManager::onKeyAuthorizationQueried(const SignOn::Key key,
00565                                                          int result)
00566 {
00567     TRACE() << "result:" << result;
00568 
00569     if (result != AbstractKeyAuthorizer::Denied) {
00570         KeyHandler::AuthorizeFlags flags = KeyHandler::None;
00571         if (result == AbstractKeyAuthorizer::Exclusive) {
00572             TRACE() << "Reformatting secure storage.";
00573             flags |= KeyHandler::FormatStorage;
00574         }
00575 
00576         if (!m_keyHandler->authorizeKey(key, flags)) {
00577             BLAME() << "Authorization failed";
00578         }
00579     }
00580 
00581     replyToSecureStorageEventNotifiers();
00582 }
00583 
00584 bool CredentialsAccessManager::keysAvailable() const
00585 {
00586     if (m_keyHandler == 0) return false;
00587     return !m_keyHandler->insertedKeys().isEmpty();
00588 }
00589 
00590 void CredentialsAccessManager::replyToSecureStorageEventNotifiers()
00591 {
00592     TRACE();
00593     //Notify secure storage notifiers if any.
00594     int eventType = SIGNON_SECURE_STORAGE_NOT_AVAILABLE;
00595     if ((m_pCredentialsDB != 0) && m_pCredentialsDB->isSecretsDBOpen())
00596         eventType = SIGNON_SECURE_STORAGE_AVAILABLE;
00597 
00598     // Signal objects that posted secure storage not available events
00599     foreach (EventSender object, m_secureStorageEventNotifiers) {
00600         if (object.isNull())
00601             continue;
00602 
00603         SecureStorageEvent *secureStorageEvent =
00604             new SecureStorageEvent((QEvent::Type)eventType);
00605 
00606         QCoreApplication::postEvent(
00607             object.data(),
00608             secureStorageEvent,
00609             Qt::HighEventPriority);
00610     }
00611 
00612     m_secureStorageEventNotifiers.clear();
00613 }
00614 
00615 void CredentialsAccessManager::customEvent(QEvent *event)
00616 {
00617     TRACE() << "Custom event received.";
00618     if (event->type() != SIGNON_SECURE_STORAGE_NOT_AVAILABLE) {
00619         QObject::customEvent(event);
00620         return;
00621     }
00622 
00623     SecureStorageEvent *localEvent =
00624         static_cast<SecureStorageEvent *>(event);
00625 
00626     /* All senders of this event will receive a reply when
00627      * the secure storage becomes available or an error occurs. */
00628     m_secureStorageEventNotifiers.append(localEvent->m_sender);
00629 
00630     TRACE() << "Processing secure storage not available event.";
00631     if ((localEvent == 0) || (m_pCredentialsDB == 0)) {
00632         replyToSecureStorageEventNotifiers();
00633         QObject::customEvent(event);
00634         return;
00635     }
00636 
00637     //Double check if the secrets DB is indeed unavailable
00638     if (m_pCredentialsDB->isSecretsDBOpen()) {
00639         replyToSecureStorageEventNotifiers();
00640         QObject::customEvent(event);
00641         return;
00642     }
00643 
00644     SignOn::Key key; /* we don't specity any key */
00645     m_keyAuthorizer->queryKeyAuthorization(key,
00646                                            AbstractKeyAuthorizer::StorageNeeded);
00647 
00648     QObject::customEvent(event);
00649 }
00650 
00651 void CredentialsAccessManager::onEncryptedFSMounted()
00652 {
00653     TRACE();
00654     if (!credentialsSystemOpened()) return;
00655 
00656     if (!isSecretsDBOpen()) {
00657         if (openSecretsDB()) {
00658             TRACE() << "Secrets DB opened.";
00659         } else {
00660             BLAME() << "Failed to open secrets DB.";
00661         }
00662     } else {
00663         BLAME() << "Secrets DB already opened?";
00664     }
00665 }
00666 
00667 void CredentialsAccessManager::onEncryptedFSUnmounting()
00668 {
00669     TRACE();
00670     if (!credentialsSystemOpened()) return;
00671 
00672     if (isSecretsDBOpen()) {
00673         m_pCredentialsDB->closeSecretsDB();
00674     }
00675 }