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 * Copyright (C) 2013 Canonical Ltd. 00007 * 00008 * Contact: Aurel Popirtac <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 #include <iostream> 00028 #include <QVariantMap> 00029 00030 #include "signond-common.h" 00031 #include "signonidentity.h" 00032 #include "signonui_interface.h" 00033 #include "SignOn/uisessiondata.h" 00034 #include "SignOn/uisessiondata_priv.h" 00035 #include "signoncommon.h" 00036 00037 #include "accesscontrolmanagerhelper.h" 00038 #include "signonidentityadaptor.h" 00039 00040 #define SIGNON_RETURN_IF_CAM_UNAVAILABLE(_ret_arg_) do { \ 00041 if (!(CredentialsAccessManager::instance()->credentialsSystemOpened())) { \ 00042 sendErrorReply(internalServerErrName, \ 00043 internalServerErrStr + \ 00044 QLatin1String("Could not access Signon Database."));\ 00045 return _ret_arg_; \ 00046 } \ 00047 } while(0) 00048 00049 namespace SignonDaemonNS { 00050 00051 const QString internalServerErrName = SIGNOND_INTERNAL_SERVER_ERR_NAME; 00052 const QString internalServerErrStr = SIGNOND_INTERNAL_SERVER_ERR_STR; 00053 00054 class PendingCallWatcherWithContext: public QDBusPendingCallWatcher 00055 { 00056 Q_OBJECT 00057 00058 public: 00059 PendingCallWatcherWithContext(const QDBusPendingCall &call, 00060 SignonIdentity *parent): 00061 QDBusPendingCallWatcher(call, parent), 00062 m_connection(parent->connection()), 00063 m_message(parent->message()) 00064 { 00065 } 00066 00067 PendingCallWatcherWithContext(const QDBusPendingCall &call, 00068 const QDBusConnection &connection, 00069 const QDBusMessage &message, 00070 SignonIdentity *parent): 00071 QDBusPendingCallWatcher(call, parent), 00072 m_connection(connection), 00073 m_message(message) 00074 { 00075 } 00076 00077 const QDBusConnection &connection() const { return m_connection; } 00078 const QDBusMessage &message() const { return m_message; } 00079 00080 private: 00081 QDBusConnection m_connection; 00082 QDBusMessage m_message; 00083 }; 00084 00085 SignonIdentity::SignonIdentity(quint32 id, int timeout, 00086 SignonDaemon *parent): 00087 SignonDisposable(timeout, parent), 00088 m_pInfo(NULL) 00089 { 00090 m_id = id; 00091 00092 (void)new SignonIdentityAdaptor(this); 00093 00094 /* 00095 * creation of unique name for the given identity 00096 * */ 00097 static quint32 incr = 0; 00098 QString objectName = SIGNOND_DAEMON_OBJECTPATH + QLatin1String("/Identity_") 00099 + QString::number(incr++, 16); 00100 setObjectName(objectName); 00101 00102 m_signonui = new SignonUiAdaptor(SIGNON_UI_SERVICE, 00103 SIGNON_UI_DAEMON_OBJECTPATH, 00104 QDBusConnection::sessionBus(), 00105 this); 00106 00107 /* Watch for credential updates happening outside of this object (this can 00108 * happen on request of authentication plugins) */ 00109 CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); 00110 QObject::connect(db, SIGNAL(credentialsUpdated(quint32)), 00111 this, SLOT(onCredentialsUpdated(quint32))); 00112 } 00113 00114 SignonIdentity::~SignonIdentity() 00115 { 00116 emit unregistered(); 00117 00118 delete m_signonui; 00119 delete m_pInfo; 00120 } 00121 00122 SignonIdentity *SignonIdentity::createIdentity(quint32 id, SignonDaemon *parent) 00123 { 00124 return new SignonIdentity(id, parent->identityTimeout(), parent); 00125 } 00126 00127 void SignonIdentity::destroy() 00128 { 00129 /* Emitting the destroyed signal makes QDBusConnection unregister the 00130 * object */ 00131 Q_EMIT destroyed(); 00132 deleteLater(); 00133 } 00134 00135 SignonIdentityInfo SignonIdentity::queryInfo(bool &ok, bool queryPassword) 00136 { 00137 ok = true; 00138 00139 bool needLoadFromDB = true; 00140 if (m_pInfo) { 00141 needLoadFromDB = false; 00142 if (queryPassword && m_pInfo->password().isEmpty()) { 00143 needLoadFromDB = true; 00144 } 00145 } 00146 00147 if (needLoadFromDB) { 00148 if (m_pInfo != 0) { 00149 delete m_pInfo; 00150 } 00151 00152 CredentialsDB *db = 00153 CredentialsAccessManager::instance()->credentialsDB(); 00154 m_pInfo = new SignonIdentityInfo(db->credentials(m_id, queryPassword)); 00155 00156 if (db->lastError().isValid()) { 00157 ok = false; 00158 delete m_pInfo; 00159 m_pInfo = NULL; 00160 return SignonIdentityInfo(); 00161 } 00162 } 00163 00164 /* Make sure that we clear the password, if the caller doesn't need it */ 00165 SignonIdentityInfo info = *m_pInfo; 00166 if (!queryPassword) { 00167 info.setPassword(QString()); 00168 } 00169 return info; 00170 } 00171 00172 bool SignonIdentity::addReference(const QString &reference) 00173 { 00174 TRACE() << "addReference: " << reference; 00175 00176 SIGNON_RETURN_IF_CAM_UNAVAILABLE(false); 00177 00178 CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); 00179 if (db == NULL) { 00180 BLAME() << "NULL database handler object."; 00181 return false; 00182 } 00183 const QDBusContext &context = static_cast<QDBusContext>(*this); 00184 QString appId = 00185 AccessControlManagerHelper::instance()->appIdOfPeer( 00186 context.connection(), 00187 context.message()); 00188 keepInUse(); 00189 return db->addReference(m_id, appId, reference); 00190 } 00191 00192 bool SignonIdentity::removeReference(const QString &reference) 00193 { 00194 TRACE() << "removeReference: " << reference; 00195 00196 SIGNON_RETURN_IF_CAM_UNAVAILABLE(false); 00197 00198 CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); 00199 if (db == NULL) { 00200 BLAME() << "NULL database handler object."; 00201 return false; 00202 } 00203 const QDBusContext &context = static_cast<QDBusContext>(*this); 00204 QString appId = 00205 AccessControlManagerHelper::instance()->appIdOfPeer( 00206 context.connection(), 00207 context.message()); 00208 keepInUse(); 00209 return db->removeReference(m_id, appId, reference); 00210 } 00211 00212 quint32 SignonIdentity::requestCredentialsUpdate(const QString &displayMessage) 00213 { 00214 SIGNON_RETURN_IF_CAM_UNAVAILABLE(SIGNOND_NEW_IDENTITY); 00215 00216 bool ok; 00217 SignonIdentityInfo info = queryInfo(ok, false); 00218 00219 if (!ok) { 00220 BLAME() << "Identity not found."; 00221 sendErrorReply(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME, 00222 SIGNOND_IDENTITY_NOT_FOUND_ERR_STR); 00223 return SIGNOND_NEW_IDENTITY; 00224 } 00225 if (!info.storePassword()) { 00226 BLAME() << "Password cannot be stored."; 00227 sendErrorReply(SIGNOND_STORE_FAILED_ERR_NAME, 00228 SIGNOND_STORE_FAILED_ERR_STR); 00229 return SIGNOND_NEW_IDENTITY; 00230 } 00231 00232 //delay dbus reply, ui interaction might take long time to complete 00233 setDelayedReply(true); 00234 00235 //create ui request to ask password 00236 QVariantMap uiRequest; 00237 uiRequest.insert(SSOUI_KEY_QUERYPASSWORD, true); 00238 uiRequest.insert(SSOUI_KEY_USERNAME, info.userName()); 00239 uiRequest.insert(SSOUI_KEY_MESSAGE, displayMessage); 00240 uiRequest.insert(SSOUI_KEY_CAPTION, info.caption()); 00241 00242 TRACE() << "Waiting for reply from signon-ui"; 00243 PendingCallWatcherWithContext *watcher = 00244 new PendingCallWatcherWithContext(m_signonui->queryDialog(uiRequest), 00245 this); 00246 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), 00247 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*))); 00248 00249 setAutoDestruct(false); 00250 return 0; 00251 } 00252 00253 QVariantMap SignonIdentity::getInfo() 00254 { 00255 TRACE() << "QUERYING INFO"; 00256 00257 SIGNON_RETURN_IF_CAM_UNAVAILABLE(QVariantMap()); 00258 00259 bool ok; 00260 SignonIdentityInfo info = queryInfo(ok, false); 00261 00262 if (!ok) { 00263 TRACE(); 00264 sendErrorReply(SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME, 00265 SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR + 00266 QLatin1String("Database querying error occurred.")); 00267 return QVariantMap(); 00268 } 00269 00270 if (info.isNew()) { 00271 TRACE(); 00272 sendErrorReply(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME, 00273 SIGNOND_IDENTITY_NOT_FOUND_ERR_STR); 00274 return QVariantMap(); 00275 } 00276 00277 keepInUse(); 00278 info.removeSecrets(); 00279 return info.toMap(); 00280 } 00281 00282 void SignonIdentity::queryUserPassword(const QVariantMap ¶ms, 00283 const QDBusConnection &connection, 00284 const QDBusMessage &message) 00285 { 00286 TRACE() << "Waiting for reply from signon-ui"; 00287 PendingCallWatcherWithContext *watcher = 00288 new PendingCallWatcherWithContext(m_signonui->queryDialog(params), 00289 connection, message, this); 00290 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, 00291 SLOT(verifyUiSlot(QDBusPendingCallWatcher*))); 00292 00293 setAutoDestruct(false); 00294 } 00295 00296 bool SignonIdentity::verifyUser(const QVariantMap ¶ms) 00297 { 00298 SIGNON_RETURN_IF_CAM_UNAVAILABLE(false); 00299 00300 bool ok; 00301 SignonIdentityInfo info = queryInfo(ok, true); 00302 00303 if (!ok) { 00304 BLAME() << "Identity not found."; 00305 sendErrorReply(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME, 00306 SIGNOND_IDENTITY_NOT_FOUND_ERR_STR); 00307 return false; 00308 } 00309 if (!info.storePassword() || info.password().isEmpty()) { 00310 BLAME() << "Password is not stored."; 00311 sendErrorReply(SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME, 00312 SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR); 00313 return false; 00314 } 00315 00316 //delay dbus reply, ui interaction might take long time to complete 00317 setDelayedReply(true); 00318 00319 //create ui request to ask password 00320 QVariantMap uiRequest; 00321 uiRequest.unite(params); 00322 uiRequest.insert(SSOUI_KEY_QUERYPASSWORD, true); 00323 uiRequest.insert(SSOUI_KEY_USERNAME, info.userName()); 00324 uiRequest.insert(SSOUI_KEY_CAPTION, info.caption()); 00325 00326 queryUserPassword(uiRequest, connection(), message()); 00327 return false; 00328 } 00329 00330 bool SignonIdentity::verifySecret(const QString &secret) 00331 { 00332 SIGNON_RETURN_IF_CAM_UNAVAILABLE(false); 00333 00334 bool ok; 00335 queryInfo(ok); 00336 if (!ok) { 00337 TRACE(); 00338 sendErrorReply(SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME, 00339 SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR + 00340 QLatin1String("Database querying error occurred.")); 00341 return false; 00342 } 00343 00344 CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); 00345 bool ret = db->checkPassword(m_pInfo->id(), m_pInfo->userName(), secret); 00346 00347 keepInUse(); 00348 return ret; 00349 } 00350 00351 void SignonIdentity::remove() 00352 { 00353 SIGNON_RETURN_IF_CAM_UNAVAILABLE(); 00354 00355 CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); 00356 if ((db == 0) || !db->removeCredentials(m_id)) { 00357 TRACE() << "Error occurred while inserting/updating credentials."; 00358 sendErrorReply(SIGNOND_REMOVE_FAILED_ERR_NAME, 00359 SIGNOND_REMOVE_FAILED_ERR_STR + 00360 QLatin1String("Database error occurred.")); 00361 return; 00362 } 00363 setDelayedReply(true); 00364 setAutoDestruct(false); 00365 PendingCallWatcherWithContext *watcher = 00366 new PendingCallWatcherWithContext(m_signonui->removeIdentityData(m_id), 00367 this); 00368 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), 00369 this, SLOT(removeCompleted(QDBusPendingCallWatcher*))); 00370 keepInUse(); 00371 } 00372 00373 void SignonIdentity::removeCompleted(QDBusPendingCallWatcher *call) 00374 { 00375 Q_ASSERT(call != NULL); 00376 00377 setAutoDestruct(true); 00378 call->deleteLater(); 00379 00380 PendingCallWatcherWithContext *context = 00381 qobject_cast<PendingCallWatcherWithContext*>(call); 00382 QDBusPendingReply<> signOnUiReply = *call; 00383 bool ok = !signOnUiReply.isError(); 00384 TRACE() << (ok ? "removeIdentityData succeeded" : "removeIdentityData failed"); 00385 00386 emit infoUpdated((int)SignOn::IdentityRemoved); 00387 00388 QDBusMessage reply = context->message().createReply(); 00389 context->connection().send(reply); 00390 } 00391 00392 bool SignonIdentity::signOut() 00393 { 00394 TRACE() << "Signout request. Identity ID: " << id(); 00395 /* 00396 * - If the identity is stored (thus registered here) 00397 * signal 'sign out' to all identities subsribed to this object, 00398 * otherwise the only identity subscribed to this is the newly 00399 * created client side identity, which called this method. 00400 * - This is just a safety check, as the client identity - if it is a new 00401 * one - should not inform server side to sign out. 00402 */ 00403 if (id() != SIGNOND_NEW_IDENTITY) { 00404 //clear stored sessiondata 00405 CredentialsDB *db = 00406 CredentialsAccessManager::instance()->credentialsDB(); 00407 if ((db == 0) || !db->removeData(m_id)) { 00408 TRACE() << "clear data failed"; 00409 } 00410 00411 setDelayedReply(true); 00412 setAutoDestruct(false); 00413 PendingCallWatcherWithContext *watcher = 00414 new PendingCallWatcherWithContext(m_signonui->removeIdentityData(m_id), 00415 this); 00416 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), 00417 this, SLOT(signOutCompleted(QDBusPendingCallWatcher*))); 00418 } 00419 keepInUse(); 00420 return true; 00421 } 00422 00423 void SignonIdentity::signOutCompleted(QDBusPendingCallWatcher *call) 00424 { 00425 Q_ASSERT(call != NULL); 00426 00427 setAutoDestruct(true); 00428 call->deleteLater(); 00429 00430 PendingCallWatcherWithContext *context = 00431 qobject_cast<PendingCallWatcherWithContext*>(call); 00432 QDBusPendingReply<> signOnUiReply = *call; 00433 bool ok = !signOnUiReply.isError(); 00434 TRACE() << (ok ? "removeIdentityData succeeded" : "removeIdentityData failed"); 00435 00436 emit infoUpdated((int)SignOn::IdentitySignedOut); 00437 00438 QDBusMessage reply = context->message().createReply(); 00439 reply << ok; 00440 context->connection().send(reply); 00441 } 00442 00443 void SignonIdentity::onCredentialsUpdated(quint32 id) 00444 { 00445 if (id != m_id) return; 00446 00447 TRACE() << m_id; 00448 00449 /* Clear the cached information about the identity; some of it might not be 00450 * valid anymore */ 00451 if (m_pInfo) { 00452 delete m_pInfo; 00453 m_pInfo = NULL; 00454 } 00455 00456 emit infoUpdated((int)SignOn::IdentityDataUpdated); 00457 } 00458 00459 quint32 SignonIdentity::store(const QVariantMap &info) 00460 { 00461 keepInUse(); 00462 SIGNON_RETURN_IF_CAM_UNAVAILABLE(SIGNOND_NEW_IDENTITY); 00463 00464 const QDBusContext &context = static_cast<QDBusContext>(*this); 00465 QString appId = 00466 AccessControlManagerHelper::instance()->appIdOfPeer( 00467 context.connection(), 00468 context.message()); 00469 00470 const QVariant container = info.value(SIGNOND_IDENTITY_INFO_AUTHMETHODS); 00471 MethodMap methods = container.isValid() ? 00472 qdbus_cast<MethodMap>(container.value<QDBusArgument>()) : MethodMap(); 00473 00474 if (m_pInfo == 0) { 00475 m_pInfo = new SignonIdentityInfo(info); 00476 m_pInfo->setMethods(methods); 00477 //Add creator to owner list if it has AID 00478 QStringList ownerList = 00479 info.value(SIGNOND_IDENTITY_INFO_OWNER).toStringList(); 00480 if (!appId.isNull()) { 00481 ownerList.append(appId); 00482 } 00483 m_pInfo->setOwnerList(ownerList); 00484 } else { 00485 SignonIdentityInfo newInfo(info); 00486 m_pInfo->update(newInfo); 00487 } 00488 00489 m_id = storeCredentials(*m_pInfo); 00490 00491 if (m_id == SIGNOND_NEW_IDENTITY) { 00492 sendErrorReply(SIGNOND_STORE_FAILED_ERR_NAME, 00493 SIGNOND_STORE_FAILED_ERR_STR); 00494 } 00495 00496 return m_id; 00497 } 00498 00499 quint32 SignonIdentity::storeCredentials(const SignonIdentityInfo &info) 00500 { 00501 CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); 00502 if (db == NULL) { 00503 BLAME() << "NULL database handler object."; 00504 return SIGNOND_NEW_IDENTITY; 00505 } 00506 00507 bool newIdentity = info.isNew(); 00508 00509 if (newIdentity) 00510 m_id = db->insertCredentials(info); 00511 else 00512 db->updateCredentials(info); 00513 00514 if (db->errorOccurred()) { 00515 if (newIdentity) 00516 m_id = SIGNOND_NEW_IDENTITY; 00517 00518 TRACE() << "Error occurred while inserting/updating credentials."; 00519 } else { 00520 if (m_pInfo) { 00521 delete m_pInfo; 00522 m_pInfo = NULL; 00523 } 00524 Q_EMIT stored(this); 00525 00526 TRACE() << "FRESH, JUST STORED CREDENTIALS ID:" << m_id; 00527 emit infoUpdated((int)SignOn::IdentityDataUpdated); 00528 } 00529 return m_id; 00530 } 00531 00532 void SignonIdentity::queryUiSlot(QDBusPendingCallWatcher *call) 00533 { 00534 TRACE(); 00535 Q_ASSERT(call != NULL); 00536 00537 setAutoDestruct(true); 00538 00539 PendingCallWatcherWithContext *context = 00540 qobject_cast<PendingCallWatcherWithContext*>(call); 00541 const QDBusMessage &message = context->message(); 00542 const QDBusConnection &connection = context->connection(); 00543 00544 QDBusMessage errReply; 00545 QDBusPendingReply<QVariantMap> reply = *call; 00546 call->deleteLater(); 00547 00548 QVariantMap resultParameters; 00549 if (!reply.isError() && reply.count()) { 00550 resultParameters = reply.argumentAt<0>(); 00551 } else { 00552 errReply = message.createErrorReply( 00553 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME, 00554 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR); 00555 connection.send(errReply); 00556 return; 00557 } 00558 00559 if (!resultParameters.contains(SSOUI_KEY_ERROR)) { 00560 //no reply code 00561 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME, 00562 SIGNOND_INTERNAL_SERVER_ERR_STR); 00563 connection.send(errReply); 00564 return; 00565 } 00566 00567 int errorCode = resultParameters.value(SSOUI_KEY_ERROR).toInt(); 00568 TRACE() << "error: " << errorCode; 00569 if (errorCode != QUERY_ERROR_NONE) { 00570 if (errorCode == QUERY_ERROR_CANCELED) 00571 errReply = 00572 message.createErrorReply( 00573 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME, 00574 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR); 00575 else 00576 errReply = 00577 message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME, 00578 QString(QLatin1String("signon-ui call returned error %1")). 00579 arg(errorCode)); 00580 00581 connection.send(errReply); 00582 return; 00583 } 00584 00585 if (resultParameters.contains(SSOUI_KEY_PASSWORD)) { 00586 CredentialsDB *db = 00587 CredentialsAccessManager::instance()->credentialsDB(); 00588 if (db == NULL) { 00589 BLAME() << "NULL database handler object."; 00590 errReply = message.createErrorReply(SIGNOND_STORE_FAILED_ERR_NAME, 00591 SIGNOND_STORE_FAILED_ERR_STR); 00592 connection.send(errReply); 00593 return; 00594 } 00595 00596 //store new password 00597 if (m_pInfo) { 00598 m_pInfo->setPassword(resultParameters[SSOUI_KEY_PASSWORD].toString()); 00599 00600 quint32 ret = db->updateCredentials(*m_pInfo); 00601 delete m_pInfo; 00602 m_pInfo = NULL; 00603 if (ret != SIGNOND_NEW_IDENTITY) { 00604 QDBusMessage dbusreply = message.createReply(); 00605 dbusreply << quint32(m_id); 00606 connection.send(dbusreply); 00607 return; 00608 } else{ 00609 BLAME() << "Error during update"; 00610 } 00611 } 00612 } 00613 00614 //this should not happen, return error 00615 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME, 00616 SIGNOND_INTERNAL_SERVER_ERR_STR); 00617 connection.send(errReply); 00618 return; 00619 } 00620 00621 void SignonIdentity::verifyUiSlot(QDBusPendingCallWatcher *call) 00622 { 00623 TRACE(); 00624 Q_ASSERT(call != NULL); 00625 00626 setAutoDestruct(true); 00627 00628 PendingCallWatcherWithContext *context = 00629 qobject_cast<PendingCallWatcherWithContext*>(call); 00630 const QDBusMessage &message = context->message(); 00631 const QDBusConnection &connection = context->connection(); 00632 00633 QDBusMessage errReply; 00634 QDBusPendingReply<QVariantMap> reply = *call; 00635 call->deleteLater(); 00636 QVariantMap resultParameters; 00637 if (!reply.isError() && reply.count()) { 00638 resultParameters = reply.argumentAt<0>(); 00639 } else { 00640 errReply = 00641 message.createErrorReply( 00642 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME, 00643 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR); 00644 connection.send(errReply); 00645 return; 00646 } 00647 00648 if (!resultParameters.contains(SSOUI_KEY_ERROR)) { 00649 //no reply code 00650 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME, 00651 SIGNOND_INTERNAL_SERVER_ERR_STR); 00652 connection.send(errReply); 00653 return; 00654 } 00655 00656 int errorCode = resultParameters.value(SSOUI_KEY_ERROR).toInt(); 00657 TRACE() << "error: " << errorCode; 00658 if (errorCode != QUERY_ERROR_NONE) { 00659 if (errorCode == QUERY_ERROR_CANCELED) 00660 errReply = message.createErrorReply( 00661 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME, 00662 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR); 00663 else if (errorCode == QUERY_ERROR_FORGOT_PASSWORD) 00664 errReply = message.createErrorReply( 00665 SIGNOND_FORGOT_PASSWORD_ERR_NAME, 00666 SIGNOND_FORGOT_PASSWORD_ERR_STR); 00667 else 00668 errReply = message.createErrorReply( 00669 SIGNOND_INTERNAL_SERVER_ERR_NAME, 00670 QString(QLatin1String("signon-ui call " 00671 "returned error %1")). 00672 arg(errorCode)); 00673 00674 connection.send(errReply); 00675 return; 00676 } 00677 00678 if (resultParameters.contains(SSOUI_KEY_PASSWORD)) { 00679 CredentialsDB *db = 00680 CredentialsAccessManager::instance()->credentialsDB(); 00681 if (db == NULL) { 00682 BLAME() << "NULL database handler object."; 00683 errReply = message.createErrorReply(SIGNOND_STORE_FAILED_ERR_NAME, 00684 SIGNOND_STORE_FAILED_ERR_STR); 00685 connection.send(errReply); 00686 return; 00687 } 00688 00689 //compare passwords 00690 if (m_pInfo) { 00691 bool ret = 00692 m_pInfo->password() == resultParameters[SSOUI_KEY_PASSWORD]. 00693 toString(); 00694 00695 if (!ret && resultParameters.contains(SSOUI_KEY_CONFIRMCOUNT)) { 00696 int count = resultParameters[SSOUI_KEY_CONFIRMCOUNT].toInt(); 00697 TRACE() << "retry count:" << count; 00698 if (count > 0) { //retry 00699 resultParameters[SSOUI_KEY_CONFIRMCOUNT] = (count-1); 00700 resultParameters[SSOUI_KEY_MESSAGEID] = 00701 QUERY_MESSAGE_NOT_AUTHORIZED; 00702 queryUserPassword(resultParameters, connection, message); 00703 return; 00704 } else { 00705 //TODO show error note here if needed 00706 } 00707 } 00708 delete m_pInfo; 00709 m_pInfo = NULL; 00710 QDBusMessage dbusreply = message.createReply(); 00711 dbusreply << ret; 00712 connection.send(dbusreply); 00713 return; 00714 } 00715 } 00716 //this should not happen, return error 00717 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME, 00718 SIGNOND_INTERNAL_SERVER_ERR_STR); 00719 connection.send(errReply); 00720 return; 00721 } 00722 00723 } //namespace SignonDaemonNS 00724 00725 #include "signonidentity.moc"