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