33 #include "SignOn/uisessiondata_priv.h"
34 #include "SignOn/authpluginif.h"
35 #include "SignOn/signonerror.h"
37 #define MAX_IDLE_TIME SIGNOND_MAX_IDLE_TIME
41 #define IDLE_WATCHDOG_TIMEOUT SIGNOND_MAX_IDLE_TIME * 500
43 #define SSO_KEY_USERNAME QLatin1String("UserName")
44 #define SSO_KEY_PASSWORD QLatin1String("Secret")
45 #define SSO_KEY_CAPTION QLatin1String("Caption")
47 using namespace SignonDaemonNS;
58 static QVariantMap filterVariantMap(
const QVariantMap &other)
62 foreach(QString key, other.keys()) {
63 if (!other.value(key).isNull() && other.value(key).isValid())
64 result.insert(key, other.value(key));
70 static QString sessionName(
const quint32
id,
const QString &method)
72 return QString::number(
id) + QLatin1String(
"+") + method;
76 const QString &method,
82 m_queryCredsUiDisplayed(false)
89 QDBusConnection::sessionBus());
112 const QString &method,
116 QString key = sessionName(
id, method);
129 TRACE() <<
"The resulted object is corrupted and has to be deleted";
139 TRACE() <<
"The new session is created :" << key;
162 TRACE() <<
"Plugin of type " << m_method <<
" cannot be found";
167 SIGNAL(processResultReply(
const QString&,
const QVariantMap&)),
169 SLOT(processResultReply(
const QString&,
const QVariantMap&)),
170 Qt::DirectConnection);
173 SIGNAL(processStore(
const QString&,
const QVariantMap&)),
175 SLOT(processStore(
const QString&,
const QVariantMap&)),
176 Qt::DirectConnection);
179 SIGNAL(processUiRequest(
const QString&,
const QVariantMap&)),
181 SLOT(processUiRequest(
const QString&,
const QVariantMap&)),
182 Qt::DirectConnection);
185 SIGNAL(processRefreshRequest(
const QString&,
const QVariantMap&)),
187 SLOT(processRefreshRequest(
const QString&,
const QVariantMap&)),
188 Qt::DirectConnection);
191 SIGNAL(processError(
const QString&,
int,
const QString&)),
193 SLOT(processError(
const QString&,
int,
const QString&)),
194 Qt::DirectConnection);
197 SIGNAL(
stateChanged(
const QString&,
int,
const QString&)),
199 SLOT(stateChangedSlot(
const QString&,
int,
const QString&)),
200 Qt::DirectConnection);
226 return QStringList();
234 if (!wantedMechanisms.size())
238 intersect(wantedMechanisms.toSet()).toList();
242 const QDBusMessage &message,
243 const QVariantMap &sessionDataVa,
244 const QString &mechanism,
245 const QString &cancelKey)
255 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);
263 for (requestIndex = 0;
264 requestIndex < m_listOfRequests.size();
266 if (m_listOfRequests.at(requestIndex).m_cancelKey == cancelKey)
270 TRACE() <<
"The request is found with index " << requestIndex;
272 if (requestIndex < m_listOfRequests.size()) {
273 if (requestIndex == 0) {
274 m_canceled = cancelKey;
277 if (m_watcher && !m_watcher->isFinished()) {
291 m_listOfRequests.head() :
292 m_listOfRequests.takeAt(requestIndex)));
294 QDBusMessage errReply =
295 rd.
m_msg.createErrorReply(SIGNOND_SESSION_CANCELED_ERR_NAME,
296 SIGNOND_SESSION_CANCELED_ERR_STR);
298 TRACE() <<
"Size of the queue is " << m_listOfRequests.size();
312 key = sessionName(m_id, m_method);
316 key = sessionName(
id, m_method);
318 qCritical() <<
"attempt to assign existing id";
328 void SignonSessionCore::startProcess()
331 TRACE() <<
"the number of requests is : " << m_listOfRequests.length();
336 QVariantMap parameters = data.
m_params;
340 m_clientData = parameters;
348 if (info.
id() != SIGNOND_NEW_IDENTITY) {
361 TRACE() <<
"Using cached secret.";
364 TRACE() <<
"Secrets storage not available and "
365 "authentication cache is empty - if SSO requires "
366 "a password, auth. will fail.";
376 QStringList paramsTokenList;
379 foreach(QString acl, identityAclList)
381 paramsTokenList.append(acl);
383 if (!paramsTokenList.isEmpty()) {
384 parameters[SSO_ACCESS_CONTROL_TOKENS] = paramsTokenList;
387 BLAME() <<
"Error occurred while getting data from credentials "
391 QVariantMap storedParams;
393 storedParams = db->
loadData(m_id, m_method);
397 if (storedParams.isEmpty()) {
400 TRACE() <<
"Using cached BLOB data.";
409 if (parameters.contains(SSOUI_KEY_UIPOLICY)
410 && parameters[SSOUI_KEY_UIPOLICY] == RequestPasswordPolicy) {
420 QDBusMessage errReply =
421 data.
m_msg.createErrorReply(SIGNOND_RUNTIME_ERR_NAME,
422 SIGNOND_RUNTIME_ERR_STR);
423 data.
m_conn.send(errReply);
424 m_listOfRequests.removeFirst();
425 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);
427 stateChangedSlot(data.
m_cancelKey, SignOn::SessionStarted,
428 QLatin1String(
"The request is started successfully"));
431 void SignonSessionCore::replyError(
const QDBusConnection &conn,
432 const QDBusMessage &msg,
433 int err,
const QString &message)
441 if( err < Error::AuthSessionErr) {
442 BLAME() <<
"Deprecated error code: " << err;
443 if (message.isEmpty())
444 errMessage = SIGNOND_UNKNOWN_ERR_STR;
446 errMessage = message;
447 errName = SIGNOND_UNKNOWN_ERR_NAME;
450 if (Error::AuthSessionErr < err && err < Error::UserErr) {
452 case Error::MechanismNotAvailable:
453 errName = SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_NAME;
454 errMessage = SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_STR;
456 case Error::MissingData:
457 errName = SIGNOND_MISSING_DATA_ERR_NAME;
458 errMessage = SIGNOND_MISSING_DATA_ERR_STR;
460 case Error::InvalidCredentials:
461 errName = SIGNOND_INVALID_CREDENTIALS_ERR_NAME;
462 errMessage = SIGNOND_INVALID_CREDENTIALS_ERR_STR;
464 case Error::NotAuthorized:
465 errName = SIGNOND_NOT_AUTHORIZED_ERR_NAME;
466 errMessage = SIGNOND_NOT_AUTHORIZED_ERR_STR;
468 case Error::WrongState:
469 errName = SIGNOND_WRONG_STATE_ERR_NAME;
470 errMessage = SIGNOND_WRONG_STATE_ERR_STR;
472 case Error::OperationNotSupported:
473 errName = SIGNOND_OPERATION_NOT_SUPPORTED_ERR_NAME;
474 errMessage = SIGNOND_OPERATION_NOT_SUPPORTED_ERR_STR;
476 case Error::NoConnection:
477 errName = SIGNOND_NO_CONNECTION_ERR_NAME;
478 errMessage = SIGNOND_NO_CONNECTION_ERR_STR;
481 errName = SIGNOND_NETWORK_ERR_NAME;
482 errMessage = SIGNOND_NETWORK_ERR_STR;
485 errName = SIGNOND_SSL_ERR_NAME;
486 errMessage = SIGNOND_SSL_ERR_STR;
489 errName = SIGNOND_RUNTIME_ERR_NAME;
490 errMessage = SIGNOND_RUNTIME_ERR_STR;
492 case Error::SessionCanceled:
493 errName = SIGNOND_SESSION_CANCELED_ERR_NAME;
494 errMessage = SIGNOND_SESSION_CANCELED_ERR_STR;
496 case Error::TimedOut:
497 errName = SIGNOND_TIMED_OUT_ERR_NAME;
498 errMessage = SIGNOND_TIMED_OUT_ERR_STR;
500 case Error::UserInteraction:
501 errName = SIGNOND_USER_INTERACTION_ERR_NAME;
502 errMessage = SIGNOND_USER_INTERACTION_ERR_STR;
504 case Error::OperationFailed:
505 errName = SIGNOND_OPERATION_FAILED_ERR_NAME;
506 errMessage = SIGNOND_OPERATION_FAILED_ERR_STR;
508 case Error::EncryptionFailure:
509 errName = SIGNOND_ENCRYPTION_FAILED_ERR_NAME;
510 errMessage = SIGNOND_ENCRYPTION_FAILED_ERR_STR;
512 case Error::TOSNotAccepted:
513 errName = SIGNOND_TOS_NOT_ACCEPTED_ERR_NAME;
514 errMessage = SIGNOND_TOS_NOT_ACCEPTED_ERR_STR;
516 case Error::ForgotPassword:
517 errName = SIGNOND_FORGOT_PASSWORD_ERR_NAME;
518 errMessage = SIGNOND_FORGOT_PASSWORD_ERR_STR;
520 case Error::IncorrectDate:
521 errName = SIGNOND_INCORRECT_DATE_ERR_NAME;
522 errMessage = SIGNOND_INCORRECT_DATE_ERR_STR;
525 if (message.isEmpty())
526 errMessage = SIGNOND_UNKNOWN_ERR_STR;
528 errMessage = message;
529 errName = SIGNOND_UNKNOWN_ERR_NAME;
534 if (err > Error::UserErr) {
535 errName = SIGNOND_USER_ERROR_ERR_NAME;
536 errMessage = (QString::fromLatin1(
"%1:%2")).arg(err).arg(message);
539 QDBusMessage errReply;
540 errReply = msg.createErrorReply(errName,
541 (message.isEmpty() ? errMessage : message));
545 void SignonSessionCore::processStoreOperation(
const StoreOperation &operation)
547 TRACE() <<
"Processing store operation.";
553 BLAME() <<
"Error occured while updating credentials.";
556 TRACE() <<
"Processing --- StoreOperation::Blob";
561 BLAME() <<
"Error occured while storing data.";
566 void SignonSessionCore::processResultReply(
const QString &cancelKey,
567 const QVariantMap &data)
573 if (!m_listOfRequests.size())
578 if (cancelKey != m_canceled) {
579 QVariantList arguments;
580 QVariantMap filteredData = filterVariantMap(data);
588 bool credentialsUpdated =
false;
589 if (m_id != SIGNOND_NEW_IDENTITY) {
591 bool identityWasValidated = info.
validated();
595 if (!info.
validated() && !m_tmpUsername.isEmpty()) {
598 if (!m_tmpPassword.isEmpty()) {
604 storeOp.m_info = info;
613 if (m_queryCredsUiDisplayed) {
614 m_storeQueue.enqueue(storeOp);
620 event->m_sender =
static_cast<QObject *
>(
this);
622 QCoreApplication::postEvent(
625 Qt::HighEventPriority);
628 processStoreOperation(storeOp);
629 credentialsUpdated =
true;
636 if (!credentialsUpdated && !m_tmpPassword.isEmpty()) {
644 m_tmpUsername.clear();
645 m_tmpPassword.clear();
648 if (m_method != QLatin1String(
"password")
652 arguments << filteredData;
655 m_canceled = QString();
657 if (m_watcher && !m_watcher->isFinished()) {
662 m_queryCredsUiDisplayed =
false;
664 m_canceled = QString();
665 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);
668 void SignonSessionCore::processStore(
const QString &cancelKey,
669 const QVariantMap &data)
675 if (m_id == SIGNOND_NEW_IDENTITY) {
676 BLAME() <<
"Cannot store without identity";
679 QVariantMap filteredData = data;
683 filteredData.remove(SSO_ACCESS_CONTROL_TOKENS);
687 Q_ASSERT(db != NULL);
690 storeOp.m_blobData = filteredData;
691 storeOp.m_authMethod = m_method;
701 if (m_queryCredsUiDisplayed) {
702 TRACE() <<
"Secure storage not available. "
703 "Queueing store operations.";
704 m_storeQueue.enqueue(storeOp);
709 event->m_sender =
static_cast<QObject *
>(
this);
711 QCoreApplication::postEvent(
714 Qt::HighEventPriority);
717 processStoreOperation(storeOp);
724 TRACE() <<
"Caching BLOB authentication data.";
730 m_queryCredsUiDisplayed =
false;
735 void SignonSessionCore::processUiRequest(
const QString &cancelKey,
736 const QVariantMap &data)
742 if (cancelKey != m_canceled && m_listOfRequests.size()) {
743 QString uiRequestId = m_listOfRequests.head().m_cancelKey;
746 if (!m_watcher->isFinished())
753 m_listOfRequests.head().m_params = filterVariantMap(data);
754 m_listOfRequests.head().m_params[SSOUI_KEY_REQUESTID] = uiRequestId;
756 if (m_id == SIGNOND_NEW_IDENTITY)
757 m_listOfRequests.head().m_params[SSOUI_KEY_STORED_IDENTITY] =
false;
759 m_listOfRequests.head().m_params[SSOUI_KEY_STORED_IDENTITY] =
true;
760 m_listOfRequests.head().m_params[SSOUI_KEY_IDENTITY] = m_id;
761 m_listOfRequests.head().m_params[SSOUI_KEY_CLIENT_DATA] = m_clientData;
770 TRACE() <<
"Caption missing";
771 if (m_id != SIGNOND_NEW_IDENTITY) {
787 TRACE() <<
"Secrets DB not available."
788 <<
"CAM has no keys available. Informing signon-ui.";
789 m_listOfRequests.head().m_params[
790 SSOUI_KEY_STORAGE_KEYS_UNAVAILABLE] =
true;
794 m_watcher =
new QDBusPendingCallWatcher(
795 m_signonui->
queryDialog(m_listOfRequests.head().m_params),
797 connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
798 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*)));
802 void SignonSessionCore::processRefreshRequest(
const QString &cancelKey,
803 const QVariantMap &data)
809 if (cancelKey != m_canceled && m_listOfRequests.size()) {
810 QString uiRequestId = m_listOfRequests.head().m_cancelKey;
813 if (!m_watcher->isFinished())
820 m_listOfRequests.head().m_params = filterVariantMap(data);
821 m_watcher =
new QDBusPendingCallWatcher(
824 connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
825 this, SLOT(queryUiSlot(QDBusPendingCallWatcher*)));
829 void SignonSessionCore::processError(
const QString &cancelKey,
830 int err,
const QString &message)
834 m_tmpUsername.clear();
835 m_tmpPassword.clear();
837 if (!m_listOfRequests.size())
842 if (cancelKey != m_canceled) {
845 if (m_watcher && !m_watcher->isFinished()) {
852 m_canceled = QString();
853 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);
856 void SignonSessionCore::stateChangedSlot(
const QString &cancelKey,
857 int state,
const QString &message)
859 if (cancelKey != m_canceled && m_listOfRequests.size()) {
871 else if (ce->removed())
877 TRACE() <<
"Custom event received.";
879 TRACE() <<
"Secure storage is available.";
882 TRACE() <<
"Processing queued stored operations.";
883 while (!m_storeQueue.empty()) {
884 processStoreOperation(m_storeQueue.dequeue());
887 TRACE() <<
"Secure storage still not available. "
888 "Clearing storage operation queue.";
889 m_storeQueue.clear();
895 void SignonSessionCore::queryUiSlot(QDBusPendingCallWatcher *call)
899 QDBusPendingReply<QVariantMap> reply = *call;
900 bool isRequestToRefresh =
false;
901 Q_ASSERT_X(m_listOfRequests.size() != 0, __func__,
902 "queue of requests is empty");
904 if (!reply.isError() && reply.count()) {
905 QVariantMap resultParameters = reply.argumentAt<0>();
906 if (resultParameters.contains(SSOUI_KEY_REFRESH)) {
907 isRequestToRefresh =
true;
908 resultParameters.remove(SSOUI_KEY_REFRESH);
911 m_listOfRequests.head().m_params = resultParameters;
915 if (resultParameters.contains(SSOUI_KEY_ERROR)
916 && (resultParameters[SSOUI_KEY_ERROR] == QUERY_ERROR_CANCELED)) {
918 m_queryCredsUiDisplayed =
false;
920 m_queryCredsUiDisplayed =
true;
923 m_listOfRequests.head().m_params.insert(SSOUI_KEY_ERROR,
924 (
int)SignOn::QUERY_ERROR_NO_SIGNONUI);
927 if (m_listOfRequests.head().m_cancelKey != m_canceled) {
930 m_tmpUsername = m_listOfRequests.head().m_params.value(
932 m_tmpPassword = m_listOfRequests.head().m_params.value(
935 if (isRequestToRefresh) {
936 TRACE() <<
"REFRESH IS REQUIRED";
938 m_listOfRequests.head().m_params.remove(SSOUI_KEY_REFRESH);
940 m_listOfRequests.head().m_params);
942 m_plugin->
processUi(m_listOfRequests.head().m_cancelKey,
943 m_listOfRequests.head().m_params);
951 void SignonSessionCore::startNewRequest()
956 if (!m_listOfRequests.length()) {
957 TRACE() <<
"the data queue is EMPTY!!!";
963 TRACE() <<
" the plugin is in challenge processing";
968 if (m_watcher && !m_watcher->isFinished()) {
969 TRACE() <<
"watcher is in running mode";
973 TRACE() <<
"Start the authentication process";
996 QMetaObject::invokeMethod(
this,
"startNewRequest", Qt::QueuedConnection);