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