Commit 5ddd5160 authored by Tomi Leppänen's avatar Tomi Leppänen

Merge branch 'jb45370_fix_unlock_async' into 'master'

Fix asynchronous unlocking and implement asynchronous code checking. JB#45370

See merge request !39
parents b65e6989 16ef742b
......@@ -146,7 +146,7 @@ public:
virtual void confirmAuthentication(Authenticator::Method method) = 0;
virtual void abortAuthentication(AuthenticationInput::Error error);
\
// Signals
void feedback(
AuthenticationInput::Feedback feedback,
......
......@@ -129,6 +129,7 @@ public:
Authenticator::Methods methods, uint authenticatingPid, AuthenticationInput::Feedback feedback) override;
void authenticationEnded(bool confirmed) override;
void checkCodeFinished(int result);
void setCodeFinished(int result);
// Signals
......@@ -145,33 +146,70 @@ public:
void availabilityChanged();
private:
enum StateFlag {
ErrorFlag = 0x1000,
EvaluatingFlag = 0x2000,
CanceledFlag = 0x4000,
CompletedFlag = 0x8000
};
enum State {
Idle,
Authenticating,
AuthenticationError,
AuthenticatingForChange,
RequestingPermission,
EnteringNewSecurityCode,
RepeatingNewSecurityCode,
ExpectingGeneratedSecurityCode,
Changing,
ChangeError,
ChangeCanceled,
AuthenticatingForClear,
ClearError,
AuthenticationError = Authenticating | ErrorFlag,
AuthenticationEvaluating = Authenticating | EvaluatingFlag,
AuthenticationCanceled = Authenticating | CanceledFlag,
AuthenticationCompleted = Authenticating | CompletedFlag,
PermissionEvaluating = RequestingPermission | EvaluatingFlag, // The error and cancel states are shared with authenticating.
ChangeError = AuthenticatingForChange | ErrorFlag,
AuthenticationForChangeEvaluating = AuthenticatingForChange | EvaluatingFlag,
AuthenticationForChangeCanceled = AuthenticatingForChange | CanceledFlag,
ClearError = AuthenticatingForClear | ErrorFlag,
AuthenticationForClearEvaluating = AuthenticatingForClear | EvaluatingFlag,
AuthenticationForClearCanceled = AuthenticatingForClear | CanceledFlag,
};
enum Request {
NoRequest,
AuthenticateRequest,
PermissionRequest,
ChangeRequest,
ClearRequest
};
inline bool isSecurityCodeSet() const;
inline void authenticate(
const QString &authenticator, const QVariant &challengeCode, Authenticator::Methods methods);
inline void beginAuthenticate(uint pid, const QVariant &challengeCode, Authenticator::Methods methods);
inline void requestPermission(
const QString &client,
const QString &message,
const QVariantMap &properties,
Authenticator::Methods methods);
inline void beginRequestPermission(
uint pid,
const QString &message,
const QVariantMap &properties,
Authenticator::Methods methods);
inline void handleChangeSecurityCode(const QString &client, const QVariant &challengeCode);
inline void beginChangeSecurityCode(uint pid, const QVariant &challengeCode);
inline void handleClearSecurityCode(const QString &client);
inline void beginClearSecurityCode(uint pid);
inline void handleCancel(const QString &client);
inline void cancelPending();
inline void beginPending();
inline QVariantMap generatedCodeData();
inline void enterCodeChangeState(
FeedbackFunction feedback, Authenticator::Methods methods = Authenticator::Methods());
......@@ -181,6 +219,19 @@ private:
HostAuthenticatorAdaptor m_adaptor;
HostSecurityCodeSettingsAdaptor m_securityCodeAdaptor;
struct Pending {
QVariant challengeCode;
QVariantMap properties;
QString connection;
QString client;
QString message;
uint pid = 0;
Authenticator::Methods methods;
Request request = NoRequest;
void clear();
} m_pending;
QVariant m_challengeCode;
QString m_currentCode;
QString m_newCode;
......
......@@ -149,10 +149,6 @@ void HostDeviceLock::enterSecurityCode(const QString &code)
break;
case Authenticating: {
switch (const int result = unlockWithCode(code)) {
case Evaluating:
case Success:
unlockFinished(result, Authenticator::SecurityCode);
break;
case SecurityCodeExpired:
m_state = EnteringNewSecurityCode;
m_currentCode = code;
......@@ -164,21 +160,10 @@ void HostDeviceLock::enterSecurityCode(const QString &code)
case LockedOut:
lockedOut();
break;
default: {
const int maximum = maximumAttempts();
if (maximum > 0) {
feedback(AuthenticationInput::IncorrectSecurityCode, qMax(0, maximum - result));
if (result >= maximum) {
lockedOut();
}
} else {
feedback(AuthenticationInput::IncorrectSecurityCode, -1);
}
default:
unlockFinished(result, Authenticator::SecurityCode);
break;
}
}
break;
}
case EnteringNewSecurityCode:
......@@ -255,7 +240,9 @@ void HostDeviceLock::unlockFinished(int result, Authenticator::Method method)
abortAuthentication(AuthenticationInput::SoftwareError);
}
break;
default:
case SecurityCodeExpired:
case SecurityCodeInHistory:
case LockedOut:
if (m_state == Canceled) {
m_state = Idle;
......@@ -266,6 +253,28 @@ void HostDeviceLock::unlockFinished(int result, Authenticator::Method method)
abortAuthentication(AuthenticationInput::SoftwareError);
}
break;
default: {
int attemptsRemaining = -1;
const int maximum = maximumAttempts();
if (maximum > 0) {
if (result >= maximum) {
feedback(AuthenticationInput::IncorrectSecurityCode, 0);
lockedOut();
break;
} else {
attemptsRemaining = maximum - result;
}
}
if (m_state == Unlocking) {
m_state = Authenticating;
authenticationResumed(AuthenticationInput::IncorrectSecurityCode, {{ QStringLiteral("attemptsRemaining"), attemptsRemaining }});
} else {
feedback(AuthenticationInput::IncorrectSecurityCode, attemptsRemaining);
}
break;
}
}
}
......
......@@ -146,17 +146,27 @@ bool HostObject::authorizeConnection(const QDBusConnection &connection)
return true;
}
bool HostObject::isActiveClient(const QString &connection, const QString &client) const
{
return m_activeConnection == connection && m_activeClient == client;
}
bool HostObject::isActiveClient(const QString &client) const
{
return m_activeConnection == QDBusContext::connection().name() && m_activeClient == client;
return isActiveClient(QDBusContext::connection().name(), client);
}
void HostObject::setActiveClient(const QString &client)
void HostObject::setActiveClient(const QString &connection, const QString &client)
{
m_activeConnection = QDBusContext::connection().name();
m_activeConnection = connection;
m_activeClient = client;
}
void HostObject::setActiveClient(const QString &client)
{
setActiveClient(QDBusContext::connection().name(), client);
}
void HostObject::clearActiveClient()
{
m_activeConnection.clear();
......
......@@ -64,8 +64,10 @@ public:
virtual bool authorizeConnection(const QDBusConnection &connection);
bool isActiveClient(const QString &connection, const QString &client) const;
bool isActiveClient(const QString &client) const;
void setActiveClient(const QString &client);
void setActiveClient(const QString &connection, const QString &client);
void clearActiveClient();
protected:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment