32 #include "SignOn/uisessiondata_priv.h"
33 #include "SignOn/authpluginif.h"
34 #include "SignOn/signonerror.h"
36 #define MAX_IDLE_TIME SIGNOND_MAX_IDLE_TIME
40 #define IDLE_WATCHDOG_TIMEOUT SIGNOND_MAX_IDLE_TIME * 500
42 #define SSO_KEY_USERNAME QLatin1String("UserName")
43 #define SSO_KEY_PASSWORD QLatin1String("Secret")
44 #define SSO_KEY_CAPTION QLatin1String("Caption")
46 using namespace SignonDaemonNS;
57 static QVariantMap filterVariantMap(
const QVariantMap &other)
61 foreach(QString key, other.keys()) {
62 if (!other.value(key).isNull() && other.value(key).isValid())
63 result.insert(key, other.value(key));
69 static QString sessionName(
const quint32
id,
const QString &method)
71 return QString::number(
id) + QLatin1String(
"+") + method;
75 const QString &method,
81 m_requestIsActive(false),
85 m_queryCredsUiDisplayed(false)
89 QDBusConnection::sessionBus());
109 const QString &method,
112 QString key = sessionName(
id, method);
125 TRACE() <<
"The resulted object is corrupted and has to be deleted";
135 TRACE() <<
"The new session is created :" << key;
158 TRACE() <<
"Plugin of type " << m_method <<
" cannot be found";
163 SIGNAL(processResultReply(
const QVariantMap&)),
165 SLOT(processResultReply(
const QVariantMap&)),
166 Qt::DirectConnection);
169 SIGNAL(processStore(
const QVariantMap&)),
171 SLOT(processStore(
const QVariantMap&)),
172 Qt::DirectConnection);
175 SIGNAL(processUiRequest(
const QVariantMap&)),
177 SLOT(processUiRequest(
const QVariantMap&)),
178 Qt::DirectConnection);
181 SIGNAL(processRefreshRequest(
const QVariantMap&)),
183 SLOT(processRefreshRequest(
const QVariantMap&)),
184 Qt::DirectConnection);
187 SIGNAL(processError(
int,
const QString&)),
189 SLOT(processError(
int,
const QString&)),
190 Qt::DirectConnection);
195 SLOT(stateChangedSlot(
int,
const QString&)),
196 Qt::DirectConnection);
222 return QStringList();
230 if (!wantedMechanisms.size())
234 intersect(wantedMechanisms.toSet()).toList();
238 const QDBusMessage &message,
239 const QVariantMap &sessionDataVa,
240 const QString &mechanism,
241 const QString &cancelKey)
251 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);
259 for (requestIndex = 0;
260 requestIndex < m_listOfRequests.size();
262 if (m_listOfRequests.at(requestIndex).m_cancelKey == cancelKey)
266 TRACE() <<
"The request is found with index " << requestIndex;
268 if (requestIndex < m_listOfRequests.size()) {
271 bool isActive = (requestIndex == 0) && m_requestIsActive;
276 if (m_watcher && !m_watcher->isFinished()) {
290 m_listOfRequests.head() :
291 m_listOfRequests.takeAt(requestIndex));
293 QDBusMessage errReply =
294 rd.
m_msg.createErrorReply(SIGNOND_SESSION_CANCELED_ERR_NAME,
295 SIGNOND_SESSION_CANCELED_ERR_STR);
296 rd.m_conn.send(errReply);
297 TRACE() <<
"Size of the queue is" << m_listOfRequests.size();
311 key = sessionName(m_id, m_method);
315 key = sessionName(
id, m_method);
317 qCritical() <<
"attempt to assign existing id";
327 void SignonSessionCore::startProcess()
330 TRACE() <<
"the number of requests is" << m_listOfRequests.length();
332 m_requestIsActive =
true;
334 QVariantMap parameters = data.
m_params;
338 m_clientData = parameters;
346 if (info.
id() != SIGNOND_NEW_IDENTITY) {
356 QStringList paramsTokenList;
359 foreach(QString acl, identityAclList)
361 paramsTokenList.append(acl);
363 if (!paramsTokenList.isEmpty()) {
364 parameters[SSO_ACCESS_CONTROL_TOKENS] = paramsTokenList;
367 BLAME() <<
"Error occurred while getting data from credentials "
371 QVariantMap storedParams = db->
loadData(m_id, m_method);
377 if (parameters.contains(SSOUI_KEY_UIPOLICY)
378 && parameters[SSOUI_KEY_UIPOLICY] == RequestPasswordPolicy) {
388 QDBusMessage errReply =
389 data.
m_msg.createErrorReply(SIGNOND_RUNTIME_ERR_NAME,
390 SIGNOND_RUNTIME_ERR_STR);
391 data.
m_conn.send(errReply);
394 stateChangedSlot(SignOn::SessionStarted,
395 QLatin1String(
"The request is started successfully"));
398 void SignonSessionCore::replyError(
const QDBusConnection &conn,
399 const QDBusMessage &msg,
400 int err,
const QString &message)
408 if( err < Error::AuthSessionErr) {
409 BLAME() <<
"Deprecated error code:" << err;
410 if (message.isEmpty())
411 errMessage = SIGNOND_UNKNOWN_ERR_STR;
413 errMessage = message;
414 errName = SIGNOND_UNKNOWN_ERR_NAME;
417 if (Error::AuthSessionErr < err && err < Error::UserErr) {
419 case Error::MechanismNotAvailable:
420 errName = SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_NAME;
421 errMessage = SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_STR;
423 case Error::MissingData:
424 errName = SIGNOND_MISSING_DATA_ERR_NAME;
425 errMessage = SIGNOND_MISSING_DATA_ERR_STR;
427 case Error::InvalidCredentials:
428 errName = SIGNOND_INVALID_CREDENTIALS_ERR_NAME;
429 errMessage = SIGNOND_INVALID_CREDENTIALS_ERR_STR;
431 case Error::NotAuthorized:
432 errName = SIGNOND_NOT_AUTHORIZED_ERR_NAME;
433 errMessage = SIGNOND_NOT_AUTHORIZED_ERR_STR;
435 case Error::WrongState:
436 errName = SIGNOND_WRONG_STATE_ERR_NAME;
437 errMessage = SIGNOND_WRONG_STATE_ERR_STR;
439 case Error::OperationNotSupported:
440 errName = SIGNOND_OPERATION_NOT_SUPPORTED_ERR_NAME;
441 errMessage = SIGNOND_OPERATION_NOT_SUPPORTED_ERR_STR;
443 case Error::NoConnection:
444 errName = SIGNOND_NO_CONNECTION_ERR_NAME;
445 errMessage = SIGNOND_NO_CONNECTION_ERR_STR;
448 errName = SIGNOND_NETWORK_ERR_NAME;
449 errMessage = SIGNOND_NETWORK_ERR_STR;
452 errName = SIGNOND_SSL_ERR_NAME;
453 errMessage = SIGNOND_SSL_ERR_STR;
456 errName = SIGNOND_RUNTIME_ERR_NAME;
457 errMessage = SIGNOND_RUNTIME_ERR_STR;
459 case Error::SessionCanceled:
460 errName = SIGNOND_SESSION_CANCELED_ERR_NAME;
461 errMessage = SIGNOND_SESSION_CANCELED_ERR_STR;
463 case Error::TimedOut:
464 errName = SIGNOND_TIMED_OUT_ERR_NAME;
465 errMessage = SIGNOND_TIMED_OUT_ERR_STR;
467 case Error::UserInteraction:
468 errName = SIGNOND_USER_INTERACTION_ERR_NAME;
469 errMessage = SIGNOND_USER_INTERACTION_ERR_STR;
471 case Error::OperationFailed:
472 errName = SIGNOND_OPERATION_FAILED_ERR_NAME;
473 errMessage = SIGNOND_OPERATION_FAILED_ERR_STR;
475 case Error::EncryptionFailure:
476 errName = SIGNOND_ENCRYPTION_FAILED_ERR_NAME;
477 errMessage = SIGNOND_ENCRYPTION_FAILED_ERR_STR;
479 case Error::TOSNotAccepted:
480 errName = SIGNOND_TOS_NOT_ACCEPTED_ERR_NAME;
481 errMessage = SIGNOND_TOS_NOT_ACCEPTED_ERR_STR;
483 case Error::ForgotPassword:
484 errName = SIGNOND_FORGOT_PASSWORD_ERR_NAME;
485 errMessage = SIGNOND_FORGOT_PASSWORD_ERR_STR;
487 case Error::IncorrectDate:
488 errName = SIGNOND_INCORRECT_DATE_ERR_NAME;
489 errMessage = SIGNOND_INCORRECT_DATE_ERR_STR;
492 if (message.isEmpty())
493 errMessage = SIGNOND_UNKNOWN_ERR_STR;
495 errMessage = message;
496 errName = SIGNOND_UNKNOWN_ERR_NAME;
501 if (err > Error::UserErr) {
502 errName = SIGNOND_USER_ERROR_ERR_NAME;
503 errMessage = (QString::fromLatin1(
"%1:%2")).arg(err).arg(message);
506 QDBusMessage errReply;
507 errReply = msg.createErrorReply(errName,
508 (message.isEmpty() ? errMessage : message));
512 void SignonSessionCore::processStoreOperation(
const StoreOperation &operation)
514 TRACE() <<
"Processing store operation.";
520 BLAME() <<
"Error occured while updating credentials.";
523 TRACE() <<
"Processing --- StoreOperation::Blob";
528 BLAME() <<
"Error occured while storing data.";
533 void SignonSessionCore::requestDone()
535 m_listOfRequests.removeFirst();
536 m_requestIsActive =
false;
537 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);
540 void SignonSessionCore::processResultReply(
const QVariantMap &data)
546 if (m_listOfRequests.isEmpty())
552 QVariantList arguments;
553 QVariantMap filteredData = filterVariantMap(data);
561 if (m_id != SIGNOND_NEW_IDENTITY) {
563 bool identityWasValidated = info.
validated();
567 if (!info.
validated() && !m_tmpUsername.isEmpty()) {
570 if (!m_tmpPassword.isEmpty()) {
576 storeOp.m_info = info;
577 processStoreOperation(storeOp);
588 if (m_queryCredsUiDisplayed) {
593 event->m_sender =
static_cast<QObject *
>(
this);
595 QCoreApplication::postEvent(
598 Qt::HighEventPriority);
603 m_tmpUsername.clear();
604 m_tmpPassword.clear();
607 if (m_method != QLatin1String(
"password")
611 arguments << filteredData;
614 if (m_watcher && !m_watcher->isFinished()) {
619 m_queryCredsUiDisplayed =
false;
625 void SignonSessionCore::processStore(
const QVariantMap &data)
630 if (m_id == SIGNOND_NEW_IDENTITY) {
631 BLAME() <<
"Cannot store without identity";
634 QVariantMap filteredData = data;
638 filteredData.remove(SSO_ACCESS_CONTROL_TOKENS);
642 Q_ASSERT(db != NULL);
645 storeOp.m_blobData = filteredData;
646 storeOp.m_authMethod = m_method;
647 processStoreOperation(storeOp);
657 if (m_queryCredsUiDisplayed) {
658 TRACE() <<
"Secure storage not available.";
663 event->m_sender =
static_cast<QObject *
>(
this);
665 QCoreApplication::postEvent(
668 Qt::HighEventPriority);
672 m_queryCredsUiDisplayed =
false;
677 void SignonSessionCore::processUiRequest(
const QVariantMap &data)
683 if (!m_canceled && !m_listOfRequests.isEmpty()) {
688 if (!m_watcher->isFinished())
695 request.
m_params = filterVariantMap(data);
696 request.
m_params[SSOUI_KEY_REQUESTID] = uiRequestId;
698 if (m_id == SIGNOND_NEW_IDENTITY)
699 request.
m_params[SSOUI_KEY_STORED_IDENTITY] =
false;
701 request.
m_params[SSOUI_KEY_STORED_IDENTITY] =
true;
702 request.
m_params[SSOUI_KEY_IDENTITY] = m_id;
703 request.
m_params[SSOUI_KEY_CLIENT_DATA] = m_clientData;
704 request.
m_params[SSOUI_KEY_METHOD] = m_method;
714 TRACE() <<
"Caption missing";
715 if (m_id != SIGNOND_NEW_IDENTITY) {
730 TRACE() <<
"Secrets DB not available."
731 <<
"CAM has no keys available. Informing signon-ui.";
732 request.
m_params[SSOUI_KEY_STORAGE_KEYS_UNAVAILABLE] =
true;
736 m_watcher =
new QDBusPendingCallWatcher(
739 connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
740 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*)));
744 void SignonSessionCore::processRefreshRequest(
const QVariantMap &data)
750 if (!m_canceled && !m_listOfRequests.isEmpty()) {
751 QString uiRequestId = m_listOfRequests.head().m_cancelKey;
754 if (!m_watcher->isFinished())
761 m_listOfRequests.head().m_params = filterVariantMap(data);
762 m_watcher =
new QDBusPendingCallWatcher(
765 connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
766 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*)));
770 void SignonSessionCore::processError(
int err,
const QString &message)
774 m_tmpUsername.clear();
775 m_tmpPassword.clear();
777 if (m_listOfRequests.isEmpty())
785 if (m_watcher && !m_watcher->isFinished()) {
795 void SignonSessionCore::stateChangedSlot(
int state,
const QString &message)
797 if (!m_canceled && !m_listOfRequests.isEmpty()) {
809 else if (ce->removed())
821 TRACE() <<
"Custom event received.";
823 TRACE() <<
"Secure storage is available.";
825 TRACE() <<
"Secure storage still not available.";
828 QObject::customEvent(event);
831 void SignonSessionCore::queryUiSlot(QDBusPendingCallWatcher *call)
835 QDBusPendingReply<QVariantMap> reply = *call;
836 bool isRequestToRefresh =
false;
837 Q_ASSERT_X(m_listOfRequests.size() != 0, __func__,
838 "queue of requests is empty");
841 if (!reply.isError() && reply.count()) {
842 QVariantMap resultParameters = reply.argumentAt<0>();
843 if (resultParameters.contains(SSOUI_KEY_REFRESH)) {
844 isRequestToRefresh =
true;
845 resultParameters.remove(SSOUI_KEY_REFRESH);
848 rd.m_params = resultParameters;
852 if (resultParameters.contains(SSOUI_KEY_ERROR)
853 && (resultParameters[SSOUI_KEY_ERROR] == QUERY_ERROR_CANCELED)) {
855 m_queryCredsUiDisplayed =
false;
857 m_queryCredsUiDisplayed =
true;
860 rd.m_params.insert(SSOUI_KEY_ERROR,
861 (
int)SignOn::QUERY_ERROR_NO_SIGNONUI);
868 QVariant()).toString();
870 QVariant()).toString();
872 if (isRequestToRefresh) {
873 TRACE() <<
"REFRESH IS REQUIRED";
875 rd.m_params.remove(SSOUI_KEY_REFRESH);
886 void SignonSessionCore::startNewRequest()
892 if (m_listOfRequests.isEmpty()) {
893 TRACE() <<
"No more requests to process";
899 if (m_requestIsActive) {
900 TRACE() <<
"One request is already active";
905 if (m_watcher && !m_watcher->isFinished()) {
906 TRACE() <<
"Some UI operation is still pending";
910 TRACE() <<
"Starting the authentication process";
917 if (m_requestIsActive ||
934 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);