28 #include <QVariantMap> 33 #include "SignOn/uisessiondata.h" 34 #include "SignOn/uisessiondata_priv.h" 35 #include "signoncommon.h" 40 #define SIGNON_RETURN_IF_CAM_UNAVAILABLE(_ret_arg_) do { \ 41 if (!(CredentialsAccessManager::instance()->credentialsSystemOpened())) { \ 42 sendErrorReply(internalServerErrName, \ 43 internalServerErrStr + \ 44 QLatin1String("Could not access Signon Database."));\ 54 class PendingCallWatcherWithContext:
public QDBusPendingCallWatcher
59 PendingCallWatcherWithContext(
const QDBusPendingCall &call,
60 SignonIdentity *parent):
61 QDBusPendingCallWatcher(call, parent),
62 m_connection(parent->connection()),
63 m_message(parent->message())
67 PendingCallWatcherWithContext(
const QDBusPendingCall &call,
68 const QDBusConnection &connection,
69 const QDBusMessage &message,
70 SignonIdentity *parent):
71 QDBusPendingCallWatcher(call, parent),
72 m_connection(connection),
77 const QDBusConnection &connection()
const {
return m_connection; }
78 const QDBusMessage &message()
const {
return m_message; }
81 QDBusConnection m_connection;
82 QDBusMessage m_message;
85 SignonIdentity::SignonIdentity(quint32
id,
int timeout,
86 SignonDaemon *parent):
87 SignonDisposable(timeout, parent),
92 (void)
new SignonIdentityAdaptor(
this);
97 static quint32 incr = 0;
98 QString objectName = SIGNOND_DAEMON_OBJECTPATH + QLatin1String(
"/Identity_")
99 + QString::number(incr++, 16);
100 setObjectName(objectName);
104 QDBusConnection::sessionBus(),
110 QObject::connect(db, SIGNAL(credentialsUpdated(quint32)),
111 this, SLOT(onCredentialsUpdated(quint32)));
114 SignonIdentity::~SignonIdentity()
139 bool needLoadFromDB =
true;
141 needLoadFromDB =
false;
142 if (queryPassword && m_pInfo->password().isEmpty()) {
143 needLoadFromDB =
true;
147 if (needLoadFromDB) {
166 if (!queryPassword) {
174 TRACE() <<
"addReference: " << reference;
180 BLAME() <<
"NULL database handler object.";
183 const QDBusContext &context =
static_cast<QDBusContext
>(*this);
186 context.connection(),
194 TRACE() <<
"removeReference: " << reference;
200 BLAME() <<
"NULL database handler object.";
203 const QDBusContext &context =
static_cast<QDBusContext
>(*this);
206 context.connection(),
220 BLAME() <<
"Identity not found.";
221 sendErrorReply(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME,
222 SIGNOND_IDENTITY_NOT_FOUND_ERR_STR);
223 return SIGNOND_NEW_IDENTITY;
226 BLAME() <<
"Password cannot be stored.";
227 sendErrorReply(SIGNOND_STORE_FAILED_ERR_NAME,
228 SIGNOND_STORE_FAILED_ERR_STR);
229 return SIGNOND_NEW_IDENTITY;
233 setDelayedReply(
true);
236 QVariantMap uiRequest;
237 uiRequest.insert(SSOUI_KEY_QUERYPASSWORD,
true);
238 uiRequest.insert(SSOUI_KEY_USERNAME, info.
userName());
239 uiRequest.insert(SSOUI_KEY_MESSAGE, displayMessage);
240 uiRequest.insert(SSOUI_KEY_CAPTION, info.
caption());
242 TRACE() <<
"Waiting for reply from signon-ui";
243 PendingCallWatcherWithContext *watcher =
244 new PendingCallWatcherWithContext(m_signonui->queryDialog(uiRequest),
246 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
247 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*)));
249 setAutoDestruct(
false);
255 TRACE() <<
"QUERYING INFO";
264 sendErrorReply(SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME,
265 SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR +
266 QLatin1String(
"Database querying error occurred."));
267 return QVariantMap();
272 sendErrorReply(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME,
273 SIGNOND_IDENTITY_NOT_FOUND_ERR_STR);
274 return QVariantMap();
282 void SignonIdentity::queryUserPassword(
const QVariantMap ¶ms,
283 const QDBusConnection &connection,
284 const QDBusMessage &message)
286 TRACE() <<
"Waiting for reply from signon-ui";
287 PendingCallWatcherWithContext *watcher =
288 new PendingCallWatcherWithContext(m_signonui->queryDialog(params),
289 connection, message,
this);
290 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
this,
291 SLOT(verifyUiSlot(QDBusPendingCallWatcher*)));
293 setAutoDestruct(
false);
304 BLAME() <<
"Identity not found.";
305 sendErrorReply(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME,
306 SIGNOND_IDENTITY_NOT_FOUND_ERR_STR);
310 BLAME() <<
"Password is not stored.";
311 sendErrorReply(SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME,
312 SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR);
317 setDelayedReply(
true);
320 QVariantMap uiRequest;
321 uiRequest.unite(params);
322 uiRequest.insert(SSOUI_KEY_QUERYPASSWORD,
true);
323 uiRequest.insert(SSOUI_KEY_USERNAME, info.
userName());
324 uiRequest.insert(SSOUI_KEY_CAPTION, info.
caption());
326 queryUserPassword(uiRequest, connection(), message());
338 sendErrorReply(SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME,
339 SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR +
340 QLatin1String(
"Database querying error occurred."));
345 bool ret = db->
checkPassword(m_pInfo->id(), m_pInfo->userName(), secret);
357 TRACE() <<
"Error occurred while inserting/updating credentials.";
358 sendErrorReply(SIGNOND_REMOVE_FAILED_ERR_NAME,
359 SIGNOND_REMOVE_FAILED_ERR_STR +
360 QLatin1String(
"Database error occurred."));
363 setDelayedReply(
true);
364 setAutoDestruct(
false);
365 PendingCallWatcherWithContext *watcher =
366 new PendingCallWatcherWithContext(m_signonui->removeIdentityData(m_id),
368 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
369 this, SLOT(removeCompleted(QDBusPendingCallWatcher*)));
373 void SignonIdentity::removeCompleted(QDBusPendingCallWatcher *call)
375 Q_ASSERT(call != NULL);
377 setAutoDestruct(
true);
380 PendingCallWatcherWithContext *context =
381 qobject_cast<PendingCallWatcherWithContext*>(call);
382 QDBusPendingReply<> signOnUiReply = *call;
383 bool ok = !signOnUiReply.isError();
384 TRACE() << (ok ?
"removeIdentityData succeeded" :
"removeIdentityData failed");
386 emit infoUpdated((
int)SignOn::IdentityRemoved);
388 QDBusMessage reply = context->message().createReply();
389 context->connection().send(reply);
394 TRACE() <<
"Signout request. Identity ID: " << id();
403 if (
id() != SIGNOND_NEW_IDENTITY) {
408 TRACE() <<
"clear data failed";
411 setDelayedReply(
true);
412 setAutoDestruct(
false);
413 PendingCallWatcherWithContext *watcher =
414 new PendingCallWatcherWithContext(m_signonui->removeIdentityData(m_id),
416 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
417 this, SLOT(signOutCompleted(QDBusPendingCallWatcher*)));
423 void SignonIdentity::signOutCompleted(QDBusPendingCallWatcher *call)
425 Q_ASSERT(call != NULL);
427 setAutoDestruct(
true);
430 PendingCallWatcherWithContext *context =
431 qobject_cast<PendingCallWatcherWithContext*>(call);
432 QDBusPendingReply<> signOnUiReply = *call;
433 bool ok = !signOnUiReply.isError();
434 TRACE() << (ok ?
"removeIdentityData succeeded" :
"removeIdentityData failed");
436 emit infoUpdated((
int)SignOn::IdentitySignedOut);
438 QDBusMessage reply = context->message().createReply();
440 context->connection().send(reply);
443 void SignonIdentity::onCredentialsUpdated(quint32
id)
445 if (
id != m_id)
return;
456 emit infoUpdated((
int)SignOn::IdentityDataUpdated);
464 const QDBusContext &context =
static_cast<QDBusContext
>(*this);
467 context.connection(),
470 const QVariant container = info.value(SIGNOND_IDENTITY_INFO_AUTHMETHODS);
471 MethodMap methods = container.isValid() ?
475 QStringList ownerList =
476 info.value(SIGNOND_IDENTITY_INFO_OWNER).toStringList();
478 ownerList.append(appId);
482 m_pInfo->setMethods(methods);
483 m_pInfo->setOwnerList(ownerList);
485 if (info.contains(SIGNOND_IDENTITY_INFO_SECRET)) {
486 QString secret = info.value(SIGNOND_IDENTITY_INFO_SECRET).toString();
487 m_pInfo->setPassword(secret);
490 info.value(SIGNOND_IDENTITY_INFO_STORESECRET).toBool();
492 info.value(SIGNOND_IDENTITY_INFO_USERNAME).toString();
494 info.value(SIGNOND_IDENTITY_INFO_CAPTION).toString();
496 info.value(SIGNOND_IDENTITY_INFO_REALMS).toStringList();
497 QStringList accessControlList =
498 info.value(SIGNOND_IDENTITY_INFO_ACL).toStringList();
499 int type = info.value(SIGNOND_IDENTITY_INFO_TYPE).toInt();
501 m_pInfo->setStorePassword(storeSecret);
502 m_pInfo->setUserName(userName);
503 m_pInfo->setCaption(caption);
504 m_pInfo->setMethods(methods);
505 m_pInfo->setRealms(realms);
506 m_pInfo->setAccessControlList(accessControlList);
507 m_pInfo->setOwnerList(ownerList);
508 m_pInfo->setType(type);
511 m_id = storeCredentials(*m_pInfo);
513 if (m_id == SIGNOND_NEW_IDENTITY) {
514 sendErrorReply(SIGNOND_STORE_FAILED_ERR_NAME,
515 SIGNOND_STORE_FAILED_ERR_STR);
525 BLAME() <<
"NULL database handler object.";
526 return SIGNOND_NEW_IDENTITY;
529 bool newIdentity = info.
isNew();
538 m_id = SIGNOND_NEW_IDENTITY;
540 TRACE() <<
"Error occurred while inserting/updating credentials.";
548 TRACE() <<
"FRESH, JUST STORED CREDENTIALS ID:" << m_id;
549 emit infoUpdated((
int)SignOn::IdentityDataUpdated);
557 Q_ASSERT(call != NULL);
559 setAutoDestruct(
true);
561 PendingCallWatcherWithContext *context =
562 qobject_cast<PendingCallWatcherWithContext*>(call);
563 const QDBusMessage &message = context->message();
564 const QDBusConnection &connection = context->connection();
566 QDBusMessage errReply;
567 QDBusPendingReply<QVariantMap> reply = *call;
570 QVariantMap resultParameters;
571 if (!reply.isError() && reply.count()) {
572 resultParameters = reply.argumentAt<0>();
574 errReply = message.createErrorReply(
575 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME,
576 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR);
577 connection.send(errReply);
581 if (!resultParameters.contains(SSOUI_KEY_ERROR)) {
583 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME,
584 SIGNOND_INTERNAL_SERVER_ERR_STR);
585 connection.send(errReply);
589 int errorCode = resultParameters.value(SSOUI_KEY_ERROR).toInt();
590 TRACE() <<
"error: " << errorCode;
591 if (errorCode != QUERY_ERROR_NONE) {
592 if (errorCode == QUERY_ERROR_CANCELED)
594 message.createErrorReply(
595 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME,
596 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR);
599 message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME,
600 QString(QLatin1String(
"signon-ui call returned error %1")).
603 connection.send(errReply);
607 if (resultParameters.contains(SSOUI_KEY_PASSWORD)) {
611 BLAME() <<
"NULL database handler object.";
612 errReply = message.createErrorReply(SIGNOND_STORE_FAILED_ERR_NAME,
613 SIGNOND_STORE_FAILED_ERR_STR);
614 connection.send(errReply);
620 m_pInfo->setPassword(resultParameters[SSOUI_KEY_PASSWORD].toString());
625 if (ret != SIGNOND_NEW_IDENTITY) {
626 QDBusMessage dbusreply = message.createReply();
627 dbusreply << quint32(m_id);
628 connection.send(dbusreply);
631 BLAME() <<
"Error during update";
637 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME,
638 SIGNOND_INTERNAL_SERVER_ERR_STR);
639 connection.send(errReply);
646 Q_ASSERT(call != NULL);
648 setAutoDestruct(
true);
650 PendingCallWatcherWithContext *context =
651 qobject_cast<PendingCallWatcherWithContext*>(call);
652 const QDBusMessage &message = context->message();
653 const QDBusConnection &connection = context->connection();
655 QDBusMessage errReply;
656 QDBusPendingReply<QVariantMap> reply = *call;
658 QVariantMap resultParameters;
659 if (!reply.isError() && reply.count()) {
660 resultParameters = reply.argumentAt<0>();
663 message.createErrorReply(
664 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME,
665 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR);
666 connection.send(errReply);
670 if (!resultParameters.contains(SSOUI_KEY_ERROR)) {
672 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME,
673 SIGNOND_INTERNAL_SERVER_ERR_STR);
674 connection.send(errReply);
678 int errorCode = resultParameters.value(SSOUI_KEY_ERROR).toInt();
679 TRACE() <<
"error: " << errorCode;
680 if (errorCode != QUERY_ERROR_NONE) {
681 if (errorCode == QUERY_ERROR_CANCELED)
682 errReply = message.createErrorReply(
683 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME,
684 SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR);
685 else if (errorCode == QUERY_ERROR_FORGOT_PASSWORD)
686 errReply = message.createErrorReply(
687 SIGNOND_FORGOT_PASSWORD_ERR_NAME,
688 SIGNOND_FORGOT_PASSWORD_ERR_STR);
690 errReply = message.createErrorReply(
691 SIGNOND_INTERNAL_SERVER_ERR_NAME,
692 QString(QLatin1String(
"signon-ui call " 693 "returned error %1")).
696 connection.send(errReply);
700 if (resultParameters.contains(SSOUI_KEY_PASSWORD)) {
704 BLAME() <<
"NULL database handler object.";
705 errReply = message.createErrorReply(SIGNOND_STORE_FAILED_ERR_NAME,
706 SIGNOND_STORE_FAILED_ERR_STR);
707 connection.send(errReply);
714 m_pInfo->password() == resultParameters[SSOUI_KEY_PASSWORD].
717 if (!ret && resultParameters.contains(SSOUI_KEY_CONFIRMCOUNT)) {
718 int count = resultParameters[SSOUI_KEY_CONFIRMCOUNT].toInt();
719 TRACE() <<
"retry count:" << count;
721 resultParameters[SSOUI_KEY_CONFIRMCOUNT] = (count-1);
722 resultParameters[SSOUI_KEY_MESSAGEID] =
723 QUERY_MESSAGE_NOT_AUTHORIZED;
724 queryUserPassword(resultParameters, connection, message);
732 QDBusMessage dbusreply = message.createReply();
734 connection.send(dbusreply);
739 errReply = message.createErrorReply(SIGNOND_INTERNAL_SERVER_ERR_NAME,
740 SIGNOND_INTERNAL_SERVER_ERR_STR);
741 connection.send(errReply);
747 #include "signonidentity.moc" bool removeData(const quint32 id, const QString &method=QString())
const QString internalServerErrName
#define SIGNON_RETURN_IF_CAM_UNAVAILABLE(_ret_arg_)
QString appIdOfPeer(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage)
Looks up for the application identifier of a specific client process.
quint32 requestCredentialsUpdate(const QString &message)
bool storePassword() const
static AccessControlManagerHelper * instance()
bool addReference(const QString &reference)
void destroy()
Performs any predestruction operations and the destruction itself.
void verifyUiSlot(QDBusPendingCallWatcher *call)
quint32 insertCredentials(const SignonIdentityInfo &info)
quint32 updateCredentials(const SignonIdentityInfo &info)
SignOn::CredentialsDBError lastError() const
bool verifySecret(const QString &secret)
bool addReference(const quint32 id, const QString &token, const QString &reference)
bool verifyUser(const QVariantMap ¶ms)
bool removeCredentials(const quint32 id)
static SignonIdentity * createIdentity(quint32 id, SignonDaemon *parent)
static CredentialsAccessManager * instance()
Returns CAM instance.
#define SIGNON_UI_SERVICE
void setPassword(const QString &password)
void queryUiSlot(QDBusPendingCallWatcher *call)
SignonIdentityInfo credentials(const quint32 id, bool queryPassword=true)
bool removeReference(const quint32 id, const QString &token, const QString &reference=QString())
const QString internalServerErrStr
QMap< MethodName, MechanismsList > MethodMap
quint32 store(const QVariantMap &info)
bool errorOccurred() const
bool removeReference(const QString &reference)
Daemon side representation of identity.
Daemon side representation of identity information.
bool checkPassword(const quint32 id, const QString &username, const QString &password)
CredentialsDB * credentialsDB() const
Manages the credentials I/O.
Helper class for access control-related functionality.
#define SIGNON_UI_DAEMON_OBJECTPATH
quint32 storeCredentials(const SignonIdentityInfo &info)
SignonIdentityInfo queryInfo(bool &ok, bool queryPassword=true)
const QVariantMap toMap() const
int identityTimeout() const
Returns the number of seconds of inactivity after which identity objects might be automatically delet...