signon  8.40
signonsessioncore.cpp
Go to the documentation of this file.
00001 /*
00002  * This file is part of signon
00003  *
00004  * Copyright (C) 2009-2010 Nokia Corporation.
00005  * Copyright (C) 2011 Intel Corporation.
00006  *
00007  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
00008  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public License
00012  * version 2.1 as published by the Free Software Foundation.
00013  *
00014  * This library is distributed in the hope that it will be useful, but
00015  * WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00022  * 02110-1301 USA
00023  */
00024 
00025 #include "signond-common.h"
00026 #include "signonauthsession.h"
00027 #include "signonidentityinfo.h"
00028 #include "signonidentity.h"
00029 #include "signonauthsessionadaptor.h"
00030 #include "signonui_interface.h"
00031 #include "accesscontrolmanagerhelper.h"
00032 
00033 #include "SignOn/uisessiondata_priv.h"
00034 #include "SignOn/authpluginif.h"
00035 #include "SignOn/signonerror.h"
00036 
00037 #define MAX_IDLE_TIME SIGNOND_MAX_IDLE_TIME
00038 /*
00039  * the watchdog searches for idle sessions with period of half of idle timeout
00040  * */
00041 #define IDLE_WATCHDOG_TIMEOUT SIGNOND_MAX_IDLE_TIME * 500
00042 
00043 #define SSO_KEY_USERNAME QLatin1String("UserName")
00044 #define SSO_KEY_PASSWORD QLatin1String("Secret")
00045 #define SSO_KEY_CAPTION QLatin1String("Caption")
00046 
00047 using namespace SignonDaemonNS;
00048 
00049 /*
00050  * cache of session queues, as was mentined they cannot be static
00051  * */
00052 QMap<QString, SignonSessionCore *> sessionsOfStoredCredentials;
00053 /*
00054  * List of "zero" authsessions, needed for global signout
00055  * */
00056 QList<SignonSessionCore *> sessionsOfNonStoredCredentials;
00057 
00058 static QVariantMap filterVariantMap(const QVariantMap &other)
00059 {
00060     QVariantMap result;
00061 
00062     foreach(QString key, other.keys()) {
00063         if (!other.value(key).isNull() && other.value(key).isValid())
00064             result.insert(key, other.value(key));
00065     }
00066 
00067     return result;
00068 }
00069 
00070 static QString sessionName(const quint32 id, const QString &method)
00071 {
00072    return QString::number(id) + QLatin1String("+") + method;
00073 }
00074 
00075 SignonSessionCore::SignonSessionCore(quint32 id,
00076                                      const QString &method,
00077                                      int timeout,
00078                                      SignonDaemon *parent):
00079     SignonDisposable(timeout, parent),
00080     m_id(id),
00081     m_method(method),
00082     m_queryCredsUiDisplayed(false)
00083 {
00084     m_signonui = NULL;
00085     m_watcher = NULL;
00086 
00087     m_signonui = new SignonUiAdaptor(SIGNON_UI_SERVICE,
00088                                      SIGNON_UI_DAEMON_OBJECTPATH,
00089                                      QDBusConnection::sessionBus());
00090 
00091 
00092     connect(CredentialsAccessManager::instance(),
00093             SIGNAL(credentialsSystemReady()),
00094             SLOT(credentialsSystemReady()));
00095 }
00096 
00097 SignonSessionCore::~SignonSessionCore()
00098 {
00099     AuthCoreCache::instance()->authSessionDestroyed(
00100         AuthCoreCache::CacheId(m_id, m_method));
00101 
00102     delete m_plugin;
00103     delete m_watcher;
00104     delete m_signonui;
00105 
00106     m_plugin = NULL;
00107     m_signonui = NULL;
00108     m_watcher = NULL;
00109 }
00110 
00111 SignonSessionCore *SignonSessionCore::sessionCore(const quint32 id,
00112                                                   const QString &method,
00113                                                   SignonDaemon *parent)
00114 {
00115     QString objectName;
00116     QString key = sessionName(id, method);
00117 
00118     if (id) {
00119         if (sessionsOfStoredCredentials.contains(key)) {
00120             return sessionsOfStoredCredentials.value(key);
00121         }
00122     }
00123 
00124     SignonSessionCore *ssc = new SignonSessionCore(id, method,
00125                                                    parent->authSessionTimeout(),
00126                                                    parent);
00127 
00128     if (ssc->setupPlugin() == false) {
00129         TRACE() << "The resulted object is corrupted and has to be deleted";
00130         delete ssc;
00131         return NULL;
00132     }
00133 
00134     if (id)
00135         sessionsOfStoredCredentials.insert(key, ssc);
00136     else
00137         sessionsOfNonStoredCredentials.append(ssc);
00138 
00139     TRACE() << "The new session is created :" << key;
00140     return ssc;
00141 }
00142 
00143 quint32 SignonSessionCore::id() const
00144 {
00145     TRACE();
00146     keepInUse();
00147     return m_id;
00148 }
00149 
00150 QString SignonSessionCore::method() const
00151 {
00152     TRACE();
00153     keepInUse();
00154     return m_method;
00155 }
00156 
00157 bool SignonSessionCore::setupPlugin()
00158 {
00159     m_plugin = PluginProxy::createNewPluginProxy(m_method);
00160 
00161     if (!m_plugin) {
00162         TRACE() << "Plugin of type " << m_method << " cannot be found";
00163         return false;
00164     }
00165 
00166     connect(m_plugin,
00167             SIGNAL(processResultReply(const QString&, const QVariantMap&)),
00168             this,
00169             SLOT(processResultReply(const QString&, const QVariantMap&)),
00170             Qt::DirectConnection);
00171 
00172     connect(m_plugin,
00173             SIGNAL(processStore(const QString&, const QVariantMap&)),
00174             this,
00175             SLOT(processStore(const QString&, const QVariantMap&)),
00176             Qt::DirectConnection);
00177 
00178     connect(m_plugin,
00179             SIGNAL(processUiRequest(const QString&, const QVariantMap&)),
00180             this,
00181             SLOT(processUiRequest(const QString&, const QVariantMap&)),
00182             Qt::DirectConnection);
00183 
00184     connect(m_plugin,
00185             SIGNAL(processRefreshRequest(const QString&, const QVariantMap&)),
00186             this,
00187             SLOT(processRefreshRequest(const QString&, const QVariantMap&)),
00188             Qt::DirectConnection);
00189 
00190     connect(m_plugin,
00191             SIGNAL(processError(const QString&, int, const QString&)),
00192             this,
00193             SLOT(processError(const QString&, int, const QString&)),
00194             Qt::DirectConnection);
00195 
00196     connect(m_plugin,
00197             SIGNAL(stateChanged(const QString&, int, const QString&)),
00198             this,
00199             SLOT(stateChangedSlot(const QString&, int, const QString&)),
00200             Qt::DirectConnection);
00201 
00202     return true;
00203 }
00204 
00205 void SignonSessionCore::stopAllAuthSessions()
00206 {
00207     qDeleteAll(sessionsOfStoredCredentials);
00208     sessionsOfStoredCredentials.clear();
00209 
00210     qDeleteAll(sessionsOfNonStoredCredentials);
00211     sessionsOfNonStoredCredentials.clear();
00212 }
00213 
00214 QStringList SignonSessionCore::loadedPluginMethods(const QString &method)
00215 {
00216     foreach (SignonSessionCore *corePtr, sessionsOfStoredCredentials) {
00217         if (corePtr->method() == method)
00218             return corePtr->queryAvailableMechanisms(QStringList());
00219     }
00220 
00221     foreach (SignonSessionCore *corePtr, sessionsOfNonStoredCredentials) {
00222         if (corePtr->method() == method)
00223             return corePtr->queryAvailableMechanisms(QStringList());
00224     }
00225 
00226     return QStringList();
00227 }
00228 
00229 QStringList
00230 SignonSessionCore::queryAvailableMechanisms(const QStringList &wantedMechanisms)
00231 {
00232     keepInUse();
00233 
00234     if (!wantedMechanisms.size())
00235         return m_plugin->mechanisms();
00236 
00237     return m_plugin->mechanisms().toSet().
00238         intersect(wantedMechanisms.toSet()).toList();
00239 }
00240 
00241 void SignonSessionCore::process(const QDBusConnection &connection,
00242                                 const QDBusMessage &message,
00243                                 const QVariantMap &sessionDataVa,
00244                                 const QString &mechanism,
00245                                 const QString &cancelKey)
00246 {
00247     keepInUse();
00248     m_listOfRequests.enqueue(RequestData(connection,
00249                                          message,
00250                                          sessionDataVa,
00251                                          mechanism,
00252                                          cancelKey));
00253 
00254     if (CredentialsAccessManager::instance()->isCredentialsSystemReady())
00255         QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection);
00256 }
00257 
00258 void SignonSessionCore::cancel(const QString &cancelKey)
00259 {
00260     TRACE();
00261 
00262     int requestIndex;
00263     for (requestIndex = 0;
00264          requestIndex < m_listOfRequests.size();
00265          requestIndex++) {
00266         if (m_listOfRequests.at(requestIndex).m_cancelKey == cancelKey)
00267             break;
00268     }
00269 
00270     TRACE() << "The request is found with index " << requestIndex;
00271 
00272     if (requestIndex < m_listOfRequests.size()) {
00273         if (requestIndex == 0) {
00274             m_canceled = cancelKey;
00275             m_plugin->cancel();
00276 
00277             if (m_watcher && !m_watcher->isFinished()) {
00278                 m_signonui->cancelUiRequest(cancelKey);
00279                 delete m_watcher;
00280                 m_watcher = 0;
00281             }
00282         }
00283 
00284         /*
00285          * We must let to the m_listOfRequests to have the canceled request data
00286          * in order to delay the next request execution until the actual cancelation
00287          * will happen. We will know about that precisely: plugin must reply via
00288          * resultSlot or via errorSlot.
00289          * */
00290         RequestData rd((requestIndex == 0 ?
00291                         m_listOfRequests.head() :
00292                         m_listOfRequests.takeAt(requestIndex)));
00293 
00294         QDBusMessage errReply =
00295             rd.m_msg.createErrorReply(SIGNOND_SESSION_CANCELED_ERR_NAME,
00296                                       SIGNOND_SESSION_CANCELED_ERR_STR);
00297         rd.m_conn.send(errReply);
00298         TRACE() << "Size of the queue is " << m_listOfRequests.size();
00299     }
00300 }
00301 
00302 void SignonSessionCore::setId(quint32 id)
00303 {
00304     keepInUse();
00305 
00306     if (m_id == id)
00307         return;
00308 
00309     QString key;
00310 
00311     if (id == 0) {
00312         key = sessionName(m_id, m_method);
00313         sessionsOfNonStoredCredentials.append(
00314                                         sessionsOfStoredCredentials.take(key));
00315     } else {
00316         key = sessionName(id, m_method);
00317         if (sessionsOfStoredCredentials.contains(key)) {
00318             qCritical() << "attempt to assign existing id";
00319             return;
00320         }
00321 
00322         sessionsOfNonStoredCredentials.removeOne(this);
00323         sessionsOfStoredCredentials[key] = this;
00324     }
00325     m_id = id;
00326 }
00327 
00328 void SignonSessionCore::startProcess()
00329 {
00330 
00331     TRACE() << "the number of requests is : " << m_listOfRequests.length();
00332 
00333     keepInUse();
00334 
00335     RequestData data = m_listOfRequests.head();
00336     QVariantMap parameters = data.m_params;
00337 
00338     /* save the client data; this should not be modified during the processing
00339      * of this request */
00340     m_clientData = parameters;
00341 
00342     if (m_id) {
00343         CredentialsDB *db =
00344             CredentialsAccessManager::instance()->credentialsDB();
00345         Q_ASSERT(db != 0);
00346 
00347         SignonIdentityInfo info = db->credentials(m_id);
00348         if (info.id() != SIGNOND_NEW_IDENTITY) {
00349             if (!parameters.contains(SSO_KEY_PASSWORD)) {
00350                 //If secrets db not available attempt loading data from cache
00351                 if (db->isSecretsDBOpen()) {
00352                     parameters[SSO_KEY_PASSWORD] = info.password();
00353                 }
00354 
00355                 /* Temporary fix - keep it until session core refactoring is
00356                  * complete and auth cache will be dumped in the secrets db. */
00357                 if (parameters[SSO_KEY_PASSWORD].toString().isEmpty()) {
00358                     AuthCache *cache =
00359                         AuthCoreCache::instance()->data(info.id());
00360                     if (cache != 0) {
00361                         TRACE() << "Using cached secret.";
00362                         parameters[SSO_KEY_PASSWORD] = cache->password();
00363                     } else {
00364                         TRACE() << "Secrets storage not available and "
00365                             "authentication cache is empty - if SSO requires "
00366                             "a password, auth. will fail.";
00367                     }
00368                 }
00369             }
00370             //database overrules over sessiondata for validated username,
00371             //so that identity cannot be misused
00372             if (info.validated() || !parameters.contains(SSO_KEY_USERNAME)) {
00373                 parameters[SSO_KEY_USERNAME] = info.userName();
00374             }
00375 
00376             QStringList paramsTokenList;
00377             QStringList identityAclList = info.accessControlList();
00378 
00379             foreach(QString acl, identityAclList)
00380                 if (AccessControlManagerHelper::instance()->isPeerAllowedToAccess(data.m_msg, acl))
00381                     paramsTokenList.append(acl);
00382 
00383             if (!paramsTokenList.isEmpty()) {
00384                 parameters[SSO_ACCESS_CONTROL_TOKENS] = paramsTokenList;
00385             }
00386         } else {
00387             BLAME() << "Error occurred while getting data from credentials "
00388                 "database.";
00389         }
00390 
00391         QVariantMap storedParams;
00392         if (db->isSecretsDBOpen()) {
00393             storedParams = db->loadData(m_id, m_method);
00394         }
00395         /* Temporary fix - keep it until session core refactoring is complete and auth cache
00396          * will be dumped in the secrets db. */
00397         if (storedParams.isEmpty()) {
00398             AuthCache *cache = AuthCoreCache::instance()->data(info.id());
00399             if (cache != 0) {
00400                 TRACE() << "Using cached BLOB data.";
00401                 storedParams = cache->blobData();
00402             }
00403         }
00404 
00405         //parameters will overwrite any common keys on stored params
00406         parameters = mergeVariantMaps(storedParams, parameters);
00407     }
00408 
00409     if (parameters.contains(SSOUI_KEY_UIPOLICY)
00410         && parameters[SSOUI_KEY_UIPOLICY] == RequestPasswordPolicy) {
00411         parameters.remove(SSO_KEY_PASSWORD);
00412     }
00413 
00414     /* Temporary caching, if credentials are valid
00415      * this data will be effectively cached */
00416     m_tmpUsername = parameters[SSO_KEY_USERNAME].toString();
00417     m_tmpPassword = parameters[SSO_KEY_PASSWORD].toString();
00418 
00419     if (!m_plugin->process(data.m_cancelKey, parameters, data.m_mechanism)) {
00420         QDBusMessage errReply =
00421             data.m_msg.createErrorReply(SIGNOND_RUNTIME_ERR_NAME,
00422                                         SIGNOND_RUNTIME_ERR_STR);
00423         data.m_conn.send(errReply);
00424         m_listOfRequests.removeFirst();
00425         QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection);
00426     } else
00427         stateChangedSlot(data.m_cancelKey, SignOn::SessionStarted,
00428                          QLatin1String("The request is started successfully"));
00429 }
00430 
00431 void SignonSessionCore::replyError(const QDBusConnection &conn,
00432                                    const QDBusMessage &msg,
00433                                    int err, const QString &message)
00434 {
00435     keepInUse();
00436 
00437     QString errName;
00438     QString errMessage;
00439 
00440     //TODO this is needed for old error codes
00441     if( err < Error::AuthSessionErr) {
00442         BLAME() << "Deprecated error code: " << err;
00443             if (message.isEmpty())
00444                 errMessage = SIGNOND_UNKNOWN_ERR_STR;
00445             else
00446                 errMessage = message;
00447             errName = SIGNOND_UNKNOWN_ERR_NAME;
00448     }
00449 
00450     if (Error::AuthSessionErr < err && err < Error::UserErr) {
00451         switch(err) {
00452         case Error::MechanismNotAvailable:
00453             errName = SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_NAME;
00454             errMessage = SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_STR;
00455             break;
00456         case Error::MissingData:
00457             errName = SIGNOND_MISSING_DATA_ERR_NAME;
00458             errMessage = SIGNOND_MISSING_DATA_ERR_STR;
00459             break;
00460         case Error::InvalidCredentials:
00461             errName = SIGNOND_INVALID_CREDENTIALS_ERR_NAME;
00462             errMessage = SIGNOND_INVALID_CREDENTIALS_ERR_STR;
00463             break;
00464         case Error::NotAuthorized:
00465             errName = SIGNOND_NOT_AUTHORIZED_ERR_NAME;
00466             errMessage = SIGNOND_NOT_AUTHORIZED_ERR_STR;
00467             break;
00468         case Error::WrongState:
00469             errName = SIGNOND_WRONG_STATE_ERR_NAME;
00470             errMessage = SIGNOND_WRONG_STATE_ERR_STR;
00471             break;
00472         case Error::OperationNotSupported:
00473             errName = SIGNOND_OPERATION_NOT_SUPPORTED_ERR_NAME;
00474             errMessage = SIGNOND_OPERATION_NOT_SUPPORTED_ERR_STR;
00475             break;
00476         case Error::NoConnection:
00477             errName = SIGNOND_NO_CONNECTION_ERR_NAME;
00478             errMessage = SIGNOND_NO_CONNECTION_ERR_STR;
00479             break;
00480         case Error::Network:
00481             errName = SIGNOND_NETWORK_ERR_NAME;
00482             errMessage = SIGNOND_NETWORK_ERR_STR;
00483             break;
00484         case Error::Ssl:
00485             errName = SIGNOND_SSL_ERR_NAME;
00486             errMessage = SIGNOND_SSL_ERR_STR;
00487             break;
00488         case Error::Runtime:
00489             errName = SIGNOND_RUNTIME_ERR_NAME;
00490             errMessage = SIGNOND_RUNTIME_ERR_STR;
00491             break;
00492         case Error::SessionCanceled:
00493             errName = SIGNOND_SESSION_CANCELED_ERR_NAME;
00494             errMessage = SIGNOND_SESSION_CANCELED_ERR_STR;
00495             break;
00496         case Error::TimedOut:
00497             errName = SIGNOND_TIMED_OUT_ERR_NAME;
00498             errMessage = SIGNOND_TIMED_OUT_ERR_STR;
00499             break;
00500         case Error::UserInteraction:
00501             errName = SIGNOND_USER_INTERACTION_ERR_NAME;
00502             errMessage = SIGNOND_USER_INTERACTION_ERR_STR;
00503             break;
00504         case Error::OperationFailed:
00505             errName = SIGNOND_OPERATION_FAILED_ERR_NAME;
00506             errMessage = SIGNOND_OPERATION_FAILED_ERR_STR;
00507             break;
00508         case Error::EncryptionFailure:
00509             errName = SIGNOND_ENCRYPTION_FAILED_ERR_NAME;
00510             errMessage = SIGNOND_ENCRYPTION_FAILED_ERR_STR;
00511             break;
00512         case Error::TOSNotAccepted:
00513             errName = SIGNOND_TOS_NOT_ACCEPTED_ERR_NAME;
00514             errMessage = SIGNOND_TOS_NOT_ACCEPTED_ERR_STR;
00515             break;
00516         case Error::ForgotPassword:
00517             errName = SIGNOND_FORGOT_PASSWORD_ERR_NAME;
00518             errMessage = SIGNOND_FORGOT_PASSWORD_ERR_STR;
00519             break;
00520         case Error::IncorrectDate:
00521             errName = SIGNOND_INCORRECT_DATE_ERR_NAME;
00522             errMessage = SIGNOND_INCORRECT_DATE_ERR_STR;
00523             break;
00524         default:
00525             if (message.isEmpty())
00526                 errMessage = SIGNOND_UNKNOWN_ERR_STR;
00527             else
00528                 errMessage = message;
00529             errName = SIGNOND_UNKNOWN_ERR_NAME;
00530             break;
00531         };
00532     }
00533 
00534     if (err > Error::UserErr) {
00535         errName = SIGNOND_USER_ERROR_ERR_NAME;
00536         errMessage = (QString::fromLatin1("%1:%2")).arg(err).arg(message);
00537     }
00538 
00539     QDBusMessage errReply;
00540     errReply = msg.createErrorReply(errName,
00541                                     (message.isEmpty() ? errMessage : message));
00542     conn.send(errReply);
00543 }
00544 
00545 void SignonSessionCore::processStoreOperation(const StoreOperation &operation)
00546 {
00547     TRACE() << "Processing store operation.";
00548     CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB();
00549     Q_ASSERT(db != 0);
00550 
00551     if (operation.m_storeType != StoreOperation::Blob) {
00552         if (!(db->updateCredentials(operation.m_info))) {
00553             BLAME() << "Error occured while updating credentials.";
00554         }
00555     } else {
00556         TRACE() << "Processing --- StoreOperation::Blob";
00557 
00558         if(!db->storeData(m_id,
00559                           operation.m_authMethod,
00560                           operation.m_blobData)) {
00561             BLAME() << "Error occured while storing data.";
00562         }
00563     }
00564 }
00565 
00566 void SignonSessionCore::processResultReply(const QString &cancelKey,
00567                                            const QVariantMap &data)
00568 {
00569     TRACE();
00570 
00571     keepInUse();
00572 
00573     if (!m_listOfRequests.size())
00574         return;
00575 
00576     RequestData rd = m_listOfRequests.dequeue();
00577 
00578     if (cancelKey != m_canceled) {
00579         QVariantList arguments;
00580         QVariantMap filteredData = filterVariantMap(data);
00581 
00582         CredentialsAccessManager *camManager =
00583             CredentialsAccessManager::instance();
00584         CredentialsDB *db = camManager->credentialsDB();
00585         Q_ASSERT(db != 0);
00586 
00587         //update database entry
00588         bool credentialsUpdated = false;
00589         if (m_id != SIGNOND_NEW_IDENTITY) {
00590             SignonIdentityInfo info = db->credentials(m_id);
00591             bool identityWasValidated = info.validated();
00592 
00593             /* update username and password from ui interaction; do not allow
00594              * updating the username if the identity is validated */
00595             if (!info.validated() && !m_tmpUsername.isEmpty()) {
00596                 info.setUserName(m_tmpUsername);
00597             }
00598             if (!m_tmpPassword.isEmpty()) {
00599                 info.setPassword(m_tmpPassword);
00600             }
00601             info.setValidated(true);
00602 
00603             StoreOperation storeOp(StoreOperation::Credentials);
00604             storeOp.m_info = info;
00605 
00606             /* If the credentials are validated, the secrets db is not
00607              * available and not authorized keys are available inform the CAM
00608              * about the situation. */
00609             if (identityWasValidated && !db->isSecretsDBOpen()) {
00610                 /* Send the storage not available event only if the curent
00611                  * result processing is following a previous signon UI query.
00612                  * This is to avoid unexpected UI pop-ups. */
00613                 if (m_queryCredsUiDisplayed) {
00614                     m_storeQueue.enqueue(storeOp);
00615 
00616                     SecureStorageEvent *event =
00617                         new SecureStorageEvent(
00618                             (QEvent::Type)SIGNON_SECURE_STORAGE_NOT_AVAILABLE);
00619 
00620                     event->m_sender = static_cast<QObject *>(this);
00621 
00622                     QCoreApplication::postEvent(
00623                         CredentialsAccessManager::instance(),
00624                         event,
00625                         Qt::HighEventPriority);
00626                 }
00627             } else {
00628                 processStoreOperation(storeOp);
00629                 credentialsUpdated = true;
00630             }
00631         }
00632 
00633         /* If secrets db not available cache credentials for this session core.
00634          * Avoid creating an invalid caching record - cache only if the password
00635          * is not empty. */
00636         if (!credentialsUpdated && !m_tmpPassword.isEmpty()) {
00637             AuthCache *cache = new AuthCache;
00638             cache->setUsername(m_tmpUsername);
00639             cache->setPassword(m_tmpPassword);
00640             AuthCoreCache::instance()->insert(
00641                 AuthCoreCache::CacheId(m_id, m_method), cache);
00642         }
00643 
00644         m_tmpUsername.clear();
00645         m_tmpPassword.clear();
00646 
00647         //remove secret field from output
00648         if (m_method != QLatin1String("password")
00649             && filteredData.contains(SSO_KEY_PASSWORD))
00650             filteredData.remove(SSO_KEY_PASSWORD);
00651 
00652         arguments << filteredData;
00653         rd.m_conn.send(rd.m_msg.createReply(arguments));
00654 
00655         m_canceled = QString();
00656 
00657         if (m_watcher && !m_watcher->isFinished()) {
00658             m_signonui->cancelUiRequest(rd.m_cancelKey);
00659             delete m_watcher;
00660             m_watcher = 0;
00661         }
00662         m_queryCredsUiDisplayed = false;
00663     }
00664     m_canceled = QString();
00665     QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection);
00666 }
00667 
00668 void SignonSessionCore::processStore(const QString &cancelKey,
00669                                      const QVariantMap &data)
00670 {
00671     Q_UNUSED(cancelKey);
00672     TRACE();
00673 
00674     keepInUse();
00675     if (m_id == SIGNOND_NEW_IDENTITY) {
00676         BLAME() << "Cannot store without identity";
00677         return;
00678     }
00679     QVariantMap filteredData = data;
00680     //do not store username or password
00681     filteredData.remove(SSO_KEY_PASSWORD);
00682     filteredData.remove(SSO_KEY_USERNAME);
00683     filteredData.remove(SSO_ACCESS_CONTROL_TOKENS);
00684 
00685     //store data into db
00686     CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB();
00687     Q_ASSERT(db != NULL);
00688 
00689     StoreOperation storeOp(StoreOperation::Blob);
00690     storeOp.m_blobData = filteredData;
00691     storeOp.m_authMethod = m_method;
00692 
00693     /* If the credentials are validated, the secrets db is not available and
00694      * not authorized keys are available inform the CAM about the situation. */
00695     SignonIdentityInfo info = db->credentials(m_id);
00696     if (info.validated() && !db->isSecretsDBOpen()) {
00697         /* Send the storage not available event only if the curent store
00698          * processing is following a previous signon UI query. This is to avoid
00699          * unexpected UI pop-ups.
00700          */
00701         if (m_queryCredsUiDisplayed) {
00702             TRACE() << "Secure storage not available. "
00703                 "Queueing store operations.";
00704             m_storeQueue.enqueue(storeOp);
00705 
00706             SecureStorageEvent *event =
00707                 new SecureStorageEvent(
00708                     (QEvent::Type)SIGNON_SECURE_STORAGE_NOT_AVAILABLE);
00709             event->m_sender = static_cast<QObject *>(this);
00710 
00711             QCoreApplication::postEvent(
00712                 CredentialsAccessManager::instance(),
00713                 event,
00714                 Qt::HighEventPriority);
00715         }
00716     } else {
00717         processStoreOperation(storeOp);
00718     }
00719 
00720     /* If secrets db not available cache credentials for this session core.
00721      * Avoid creating an invalid caching record - cache only if the BLOB data
00722      * is not empty. */
00723     if (!db->isSecretsDBOpen() && !data.isEmpty()) {
00724         TRACE() << "Caching BLOB authentication data.";
00725         AuthCache *cache = new AuthCache;
00726         cache->setBlobData(data);
00727         AuthCoreCache::instance()->insert(
00728             AuthCoreCache::CacheId(m_id, m_method), cache);
00729     }
00730     m_queryCredsUiDisplayed = false;
00731 
00732     return;
00733 }
00734 
00735 void SignonSessionCore::processUiRequest(const QString &cancelKey,
00736                                          const QVariantMap &data)
00737 {
00738     TRACE();
00739 
00740     keepInUse();
00741 
00742     if (cancelKey != m_canceled && m_listOfRequests.size()) {
00743         QString uiRequestId = m_listOfRequests.head().m_cancelKey;
00744 
00745         if (m_watcher) {
00746             if (!m_watcher->isFinished())
00747                 m_signonui->cancelUiRequest(uiRequestId);
00748 
00749             delete m_watcher;
00750             m_watcher = 0;
00751         }
00752 
00753         m_listOfRequests.head().m_params = filterVariantMap(data);
00754         m_listOfRequests.head().m_params[SSOUI_KEY_REQUESTID] = uiRequestId;
00755 
00756         if (m_id == SIGNOND_NEW_IDENTITY)
00757             m_listOfRequests.head().m_params[SSOUI_KEY_STORED_IDENTITY] = false;
00758         else
00759             m_listOfRequests.head().m_params[SSOUI_KEY_STORED_IDENTITY] = true;
00760         m_listOfRequests.head().m_params[SSOUI_KEY_IDENTITY] = m_id;
00761         m_listOfRequests.head().m_params[SSOUI_KEY_CLIENT_DATA] = m_clientData;
00762 
00763         CredentialsAccessManager *camManager =
00764             CredentialsAccessManager::instance();
00765         CredentialsDB *db = camManager->credentialsDB();
00766         Q_ASSERT(db != 0);
00767 
00768         //check that we have caption
00769         if (!data.contains(SSO_KEY_CAPTION)) {
00770             TRACE() << "Caption missing";
00771             if (m_id != SIGNOND_NEW_IDENTITY) {
00772                 SignonIdentityInfo info = db->credentials(m_id);
00773                 m_listOfRequests.head().m_params.insert(SSO_KEY_CAPTION,
00774                                                         info.caption());
00775                 TRACE() << "Got caption: " << info.caption();
00776             }
00777         }
00778 
00779         /*
00780          * Check the secure storage status, if any issues are encountered signal
00781          * this to the signon ui. */
00782         if (!db->isSecretsDBOpen()) {
00783             TRACE();
00784 
00785             //If there are no keys available
00786             if (!camManager->keysAvailable()) {
00787                 TRACE() << "Secrets DB not available."
00788                         << "CAM has no keys available. Informing signon-ui.";
00789                 m_listOfRequests.head().m_params[
00790                     SSOUI_KEY_STORAGE_KEYS_UNAVAILABLE] = true;
00791             }
00792         }
00793 
00794         m_watcher = new QDBusPendingCallWatcher(
00795                      m_signonui->queryDialog(m_listOfRequests.head().m_params),
00796                      this);
00797         connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
00798                 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*)));
00799     }
00800 }
00801 
00802 void SignonSessionCore::processRefreshRequest(const QString &cancelKey,
00803                                               const QVariantMap &data)
00804 {
00805     TRACE();
00806 
00807     keepInUse();
00808 
00809     if (cancelKey != m_canceled && m_listOfRequests.size()) {
00810         QString uiRequestId = m_listOfRequests.head().m_cancelKey;
00811 
00812         if (m_watcher) {
00813             if (!m_watcher->isFinished())
00814                 m_signonui->cancelUiRequest(uiRequestId);
00815 
00816             delete m_watcher;
00817             m_watcher = 0;
00818         }
00819 
00820         m_listOfRequests.head().m_params = filterVariantMap(data);
00821         m_watcher = new QDBusPendingCallWatcher(
00822                      m_signonui->refreshDialog(m_listOfRequests.head().m_params),
00823                      this);
00824         connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
00825                 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*)));
00826     }
00827 }
00828 
00829 void SignonSessionCore::processError(const QString &cancelKey,
00830                                      int err, const QString &message)
00831 {
00832     TRACE();
00833     keepInUse();
00834     m_tmpUsername.clear();
00835     m_tmpPassword.clear();
00836 
00837     if (!m_listOfRequests.size())
00838         return;
00839 
00840     RequestData rd = m_listOfRequests.dequeue();
00841 
00842     if (cancelKey != m_canceled) {
00843         replyError(rd.m_conn, rd.m_msg, err, message);
00844 
00845         if (m_watcher && !m_watcher->isFinished()) {
00846             m_signonui->cancelUiRequest(rd.m_cancelKey);
00847             delete m_watcher;
00848             m_watcher = 0;
00849         }
00850     }
00851 
00852     m_canceled = QString();
00853     QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection);
00854 }
00855 
00856 void SignonSessionCore::stateChangedSlot(const QString &cancelKey,
00857                                          int state, const QString &message)
00858 {
00859     if (cancelKey != m_canceled && m_listOfRequests.size()) {
00860         RequestData rd = m_listOfRequests.head();
00861         emit stateChanged(rd.m_cancelKey, (int)state, message);
00862     }
00863 
00864     keepInUse();
00865 }
00866 
00867 void SignonSessionCore::childEvent(QChildEvent *ce)
00868 {
00869     if (ce->added())
00870         keepInUse();
00871     else if (ce->removed())
00872         SignonDisposable::destroyUnused();
00873 }
00874 
00875 void SignonSessionCore::customEvent(QEvent *event)
00876 {
00877     TRACE() << "Custom event received.";
00878     if (event->type() == SIGNON_SECURE_STORAGE_AVAILABLE) {
00879         TRACE() << "Secure storage is available.";
00880         AuthCoreCache::instance()->clear();
00881 
00882         TRACE() << "Processing queued stored operations.";
00883         while (!m_storeQueue.empty()) {
00884             processStoreOperation(m_storeQueue.dequeue());
00885         }
00886     } else if (event->type() == SIGNON_SECURE_STORAGE_NOT_AVAILABLE) {
00887         TRACE() << "Secure storage still not available. "
00888                    "Clearing storage operation queue.";
00889         m_storeQueue.clear();
00890     }
00891 
00892     QObject::customEvent(event);
00893 }
00894 
00895 void SignonSessionCore::queryUiSlot(QDBusPendingCallWatcher *call)
00896 {
00897     keepInUse();
00898 
00899     QDBusPendingReply<QVariantMap> reply = *call;
00900     bool isRequestToRefresh = false;
00901     Q_ASSERT_X(m_listOfRequests.size() != 0, __func__,
00902                "queue of requests is empty");
00903 
00904     if (!reply.isError() && reply.count()) {
00905         QVariantMap resultParameters = reply.argumentAt<0>();
00906         if (resultParameters.contains(SSOUI_KEY_REFRESH)) {
00907             isRequestToRefresh = true;
00908             resultParameters.remove(SSOUI_KEY_REFRESH);
00909         }
00910 
00911         m_listOfRequests.head().m_params = resultParameters;
00912 
00913         /* If the query ui was canceled or any other error occurred
00914          * do not set this flag to true. */
00915         if (resultParameters.contains(SSOUI_KEY_ERROR)
00916             && (resultParameters[SSOUI_KEY_ERROR] == QUERY_ERROR_CANCELED)) {
00917 
00918             m_queryCredsUiDisplayed = false;
00919         } else {
00920             m_queryCredsUiDisplayed = true;
00921         }
00922     } else {
00923         m_listOfRequests.head().m_params.insert(SSOUI_KEY_ERROR,
00924                                         (int)SignOn::QUERY_ERROR_NO_SIGNONUI);
00925     }
00926 
00927     if (m_listOfRequests.head().m_cancelKey != m_canceled) {
00928         /* Temporary caching, if credentials are valid
00929          * this data will be effectively cached */
00930         m_tmpUsername = m_listOfRequests.head().m_params.value(
00931             SSO_KEY_USERNAME, QVariant()).toString();
00932         m_tmpPassword = m_listOfRequests.head().m_params.value(
00933             SSO_KEY_PASSWORD, QVariant()).toString();
00934 
00935         if (isRequestToRefresh) {
00936             TRACE() << "REFRESH IS REQUIRED";
00937 
00938             m_listOfRequests.head().m_params.remove(SSOUI_KEY_REFRESH);
00939             m_plugin->processRefresh(m_listOfRequests.head().m_cancelKey,
00940                                      m_listOfRequests.head().m_params);
00941         } else {
00942             m_plugin->processUi(m_listOfRequests.head().m_cancelKey,
00943                                 m_listOfRequests.head().m_params);
00944         }
00945     }
00946 
00947     delete m_watcher;
00948     m_watcher = NULL;
00949 }
00950 
00951 void SignonSessionCore::startNewRequest()
00952 {
00953     keepInUse();
00954 
00955     // there is no request
00956     if (!m_listOfRequests.length()) {
00957         TRACE() << "the data queue is EMPTY!!!";
00958         return;
00959     }
00960 
00961     //plugin is busy
00962     if (m_plugin && m_plugin->isProcessing()) {
00963         TRACE() << " the plugin is in challenge processing";
00964         return;
00965     }
00966 
00967     //there is some UI operation with plugin
00968     if (m_watcher && !m_watcher->isFinished()) {
00969         TRACE() << "watcher is in running mode";
00970         return;
00971     }
00972 
00973     TRACE() << "Start the authentication process";
00974     startProcess();
00975 }
00976 
00977 void SignonSessionCore::destroy()
00978 {
00979     if (m_plugin->isProcessing() ||
00980         m_watcher != NULL) {
00981         keepInUse();
00982         return;
00983     }
00984 
00985     if (m_id)
00986         sessionsOfStoredCredentials.remove(sessionName(m_id, m_method));
00987     else
00988         sessionsOfNonStoredCredentials.removeOne(this);
00989 
00990     emit destroyed();
00991     deleteLater();
00992 }
00993 
00994 void SignonSessionCore::credentialsSystemReady()
00995 {
00996     QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection);
00997 }