Commit 1fbbe608 authored by Andrew den Exter's avatar Andrew den Exter

Merge branch 'jb38309' into 'master'

Introduce an option for suggesting security codes

See merge request !19
parents 650c9841 107e8244
......@@ -14,6 +14,9 @@
<arg name="client" type="o" direction="in"/>
<arg name="code" type="s" direction="in"/>
</method>
<method name="RequestSecurityCode">
<arg name="client" type="o" direction="in"/>
</method>
<method name="Cancel">
<arg name="client" type="o" direction="in"/>
</method>
......
......@@ -7,5 +7,9 @@
<property name="Unlocking" type="b" access="read"/>
<method name="Unlock"/>
<method name="Cancel"/>
<signal name="Notice">
<arg name="notice" type="u" direction="in"/>
<arg name="data" type="a{sv}" direction="in"/>
</signal>
</interface>
</node>
......@@ -22,7 +22,7 @@
</method>
<method name="Feedback">
<arg name="feedback" type="u" direction="in"/>
<arg name="attempts_remaining" type="u" direction="in"/>
<arg name="data" type="a{sv}" direction="in"/>
<arg name="utilized_methods" type="u" direction="in"/>
</method>
<method name="Error">
......
This diff is collapsed.
......@@ -34,6 +34,7 @@
#define NEMODEVICELOCK_AUTHENTICATIONINPUT_H
#include <nemo-devicelock/authenticator.h>
#include <QDateTime>
namespace NemoDeviceLock {
......@@ -46,13 +47,13 @@ public:
explicit AuthenticationInputAdaptor(AuthenticationInput *authenticationInput);
public slots:
Q_NOREPLY void AuthenticationStarted(uint pid, uint utilizedMethods, uint instruction);
Q_NOREPLY void AuthenticationStarted(uint pid, uint utilizedMethods, uint instruction, const QVariantMap &data);
Q_NOREPLY void AuthenticationUnavailable(uint pid, uint error);
Q_NOREPLY void AuthenticationResumed(uint utilizedMethods, uint instruction);
Q_NOREPLY void AuthenticationResumed(uint utilizedMethods, uint instruction, const QVariantMap &data);
Q_NOREPLY void AuthenticationEvaluating();
Q_NOREPLY void AuthenticationProgress(int current, int maximum);
Q_NOREPLY void AuthenticationEnded(bool confirmed);
Q_NOREPLY void Feedback(uint feedback, uint attemptsRemaining, uint utilizedMethods);
Q_NOREPLY void Feedback(uint feedback, const QVariantMap &data, uint utilizedMethods);
Q_NOREPLY void Error(uint error);
private:
......@@ -72,17 +73,17 @@ class NEMODEVICELOCK_EXPORT AuthenticationInput : public QObject, private Connec
Q_PROPERTY(int maximumCodeLength READ maximumCodeLength CONSTANT)
Q_PROPERTY(int maximumAttempts READ maximumAttempts NOTIFY maximumAttemptsChanged)
Q_PROPERTY(bool codeInputIsKeyboard READ codeInputIsKeyboard NOTIFY codeInputIsKeyboardChanged)
Q_ENUMS(Feedback)
Q_ENUMS(Error)
Q_ENUMS(Status)
Q_PROPERTY(CodeGeneration codeGeneration READ codeGeneration NOTIFY codeGenerationChanged)
public:
enum Feedback {
EnterSecurityCode,
EnterNewSecurityCode,
RepeatNewSecurityCode,
SuggestSecurityCode,
SecurityCodesDoNotMatch,
SecurityCodeInHistory,
SecurityCodeExpired,
SecurityCodeDueToExpire,
PartialPrint,
PrintIsUnclear,
SensorIsDirty,
......@@ -95,6 +96,7 @@ public:
PermanentlyLocked,
UnlockToPerformOperation
};
Q_ENUM(Feedback)
enum Error {
FunctionUnavailable,
......@@ -103,6 +105,7 @@ public:
Canceled,
SoftwareError
};
Q_ENUM(Error)
enum Type {
Authentication,
......@@ -115,6 +118,14 @@ public:
Evaluating,
AuthenticationError
};
Q_ENUM(Status)
enum CodeGeneration {
NoCodeGeneration,
OptionalCodeGeneration,
MandatoryCodeGeneration
};
Q_ENUM(CodeGeneration)
explicit AuthenticationInput(Type type = Authentication, QObject *parent = nullptr);
~AuthenticationInput();
......@@ -131,11 +142,14 @@ public:
int maximumAttempts() const;
CodeGeneration codeGeneration() const;
int minimumCodeLength() const;
int maximumCodeLength() const;
bool codeInputIsKeyboard() const;
Q_INVOKABLE void enterSecurityCode(const QString &code);
Q_INVOKABLE void requestSecurityCode();
Q_INVOKABLE void cancel();
signals:
......@@ -145,15 +159,18 @@ signals:
void authenticatingPidChanged();
void utilizedMethodsChanged();
void maximumAttemptsChanged();
void temporaryLockoutDurationChanged();
void temporaryLockoutExpirationChanged();
void codeGenerationChanged();
void codeInputIsKeyboardChanged();
void authenticationStarted(Feedback feedback);
void authenticationStarted(Feedback feedback, const QVariant &data);
void authenticationUnavailable(Error error);
void authenticationEvaluating();
void authenticationProgress(int current, int maximum);
void authenticationEnded(bool confirmed);
void feedback(Feedback feedback, int attemptsRemaining);
void feedback(Feedback feedback, const QVariantMap &data);
void error(Error error);
private:
......@@ -162,13 +179,17 @@ private:
inline void connected();
inline void handleAuthenticationStarted(
int pid, Authenticator::Methods utilizedMethods, Feedback feedback);
int pid,
Authenticator::Methods utilizedMethods,
Feedback feedback,
const QVariantMap &data);
inline void handleAuthenticationUnavailable(int pid, Error error);
inline void handleAuthenticationResumed(Authenticator::Methods utilizedMethods, Feedback feedback);
inline void handleAuthenticationResumed(
Authenticator::Methods utilizedMethods, Feedback feedback, const QVariantMap &data);
inline void handleAuthenticationEvaluating();
inline void handleAuthenticationEnded(bool confirmed);
inline void handleFeedback(
Feedback feedback, int attemptsRemaining, Authenticator::Methods utilizedMethods);
Feedback feedback, const QVariantMap &data, Authenticator::Methods utilizedMethods);
inline void handleError(Error error);
AuthenticationInputAdaptor m_adaptor;
......
......@@ -47,6 +47,17 @@ namespace NemoDeviceLock
AuthenticationInput provider.
*/
/*!
\enum NemoDeviceLock::DeviceLock::Notice
Broadcast notifications decribing events of importance.
\value SecurityCodeDueToExpire The user's security code is due to due to expire in the near
future. The expiration date is provided as an ISO 8601 formatted string in the
\c expirationDate member of the notice data.
\value SecurityCodeChanged The user's security code has been changed.
*/
/*!
Constructs a device lock interface instance which is a child of \a parent.
*/
......@@ -217,10 +228,25 @@ void DeviceLock::cancel()
Signals that there was an error requesting authentication to unlock the device.
*/
/*!
\signal NemoDeviceLock::DeviceLock::notice(Notice notice, const QVariantMap &map)
Emits a broadcast \a notice from the device lock. Some noteices will also
include \a data that should be incorporated into the message, the members of data
accompanying a notice will be described in the documentation for that notice.
*/
void DeviceLock::handleNotice(uint notice, const QVariantMap &data)
{
emit DeviceLock::notice(DeviceLock::Notice(notice), data);
}
void DeviceLock::connected()
{
registerObject();
connectToSignal(QStringLiteral("Notice"), SLOT(handleNotice(uint,QVariantMap)));
subscribeToProperty<bool>(QStringLiteral("Enabled"), [this](bool enabled) {
if (m_enabled != enabled) {
m_enabled = enabled;
......
......@@ -28,7 +28,6 @@ class SettingsWatcher;
class NEMODEVICELOCK_EXPORT DeviceLock : public QObject, private ConnectionClient
{
Q_OBJECT
Q_ENUMS(LockState)
Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged)
Q_PROPERTY(bool unlocking READ isUnlocking NOTIFY unlockingChanged)
Q_PROPERTY(LockState state READ state NOTIFY stateChanged)
......@@ -43,10 +42,17 @@ public:
Unlocked = 0, /*!< Unlocked - The lock is unlocked */
Locked, /*!< Locked - The lock is being used */
ManagerLockout, /*!< ManagerLockout - Access has been restricted by a device manager. */
TemporaryLockout, /*!< TemporaryLockout - Access has been temporarily restricted because of excessive incorrect unlock attempts. */
PermanentLockout, /*!< PermanentLockout - Access has been permanently restricted because of excessive incorrect unlock attempts. */
CodeEntryLockout, /*!< CodeEntryLockout - Access has been restricted because of excessive incorrect unlock attempts. */
Undefined /*!< Undefined - The state of the lock is unknown */
};
Q_ENUM(LockState)
enum Notice
{
SecurityCodeDueToExpire,
SecurityCodeChanged
};
Q_ENUM(Notice)
bool isEnabled() const;
bool isUnlocking() const;
......@@ -69,6 +75,11 @@ signals:
void unlocked();
void unlockError();
void notice(Notice notice, const QVariantMap &data);
private slots:
void handleNotice(uint notice, const QVariantMap &data);
private:
inline void connected();
......
......@@ -72,7 +72,7 @@ HostAuthenticationInput::Availability CliAuthenticator::availability() const
const int attempts = currentAttempts();
if (maximum > 0 && attempts >= maximum) {
return PermanentlyLocked;
return CodeEntryLockedPermanent;
} else {
return CanAuthenticate;
}
......
......@@ -61,7 +61,7 @@ HostAuthenticationInput::Availability CliDeviceLock::availability() const
const int attempts = currentAttempts();
if (maximum > 0 && attempts >= maximum) {
return PermanentlyLocked;
return CodeEntryLockedPermanent;
} else {
return CanAuthenticate;
}
......
......@@ -34,6 +34,8 @@
#include "settingswatcher.h"
#include <QFile>
namespace NemoDeviceLock
{
......@@ -61,6 +63,11 @@ void HostAuthenticationInputAdaptor::EnterSecurityCode(const QDBusObjectPath &pa
m_authenticationInput->handleEnterSecurityCode(path.path(), code);
}
void HostAuthenticationInputAdaptor::RequestSecurityCode(const QDBusObjectPath &path)
{
m_authenticationInput->handleRequestSecurityCode(path.path());
}
void HostAuthenticationInputAdaptor::Cancel(const QDBusObjectPath &path)
{
m_authenticationInput->handleCancel(path.path());
......@@ -83,15 +90,27 @@ HostAuthenticationInput::~HostAuthenticationInput()
void HostAuthenticationInput::authenticationStarted(
Authenticator::Methods methods,
AuthenticationInput::Feedback feedback)
AuthenticationInput::Feedback)
{
qCDebug(daemon, "Authentication started");
m_authenticating = true;
m_activeMethods = methods & m_supportedMethods;
}
void HostAuthenticationInput::startAuthentication(
AuthenticationInput::Feedback feedback,
const QVariantMap &data,
Authenticator::Methods methods)
{
qCDebug(daemon, "Authentication started");
const uint pid = connectionPid(QDBusContext::connection());
if (pid != 0 && !m_inputStack.isEmpty()) {
m_authenticating = true;
m_activeMethods = methods & m_supportedMethods;
authenticationStarted(methods, feedback);
NemoDBus::send(
m_inputStack.last().connection,
m_inputStack.last().path,
......@@ -99,10 +118,12 @@ void HostAuthenticationInput::authenticationStarted(
QStringLiteral("AuthenticationStarted"),
pid,
uint(m_activeMethods),
uint(feedback));
uint(feedback),
data);
}
}
void HostAuthenticationInput::authenticationUnavailable(AuthenticationInput::Error error)
{
qCDebug(daemon, "Authentication unavailable");
......@@ -122,7 +143,9 @@ void HostAuthenticationInput::authenticationUnavailable(AuthenticationInput::Err
void HostAuthenticationInput::authenticationResumed(
AuthenticationInput::Feedback feedback, Authenticator::Methods utilizedMethods)
AuthenticationInput::Feedback feedback,
const QVariantMap &data,
Authenticator::Methods utilizedMethods)
{
qCDebug(daemon, "Authentication resumed");
......@@ -139,7 +162,8 @@ void HostAuthenticationInput::authenticationResumed(
clientInterface,
QStringLiteral("AuthenticationResumed"),
uint(m_activeMethods),
uint(feedback));
uint(feedback),
data);
}
}
......@@ -270,9 +294,25 @@ int HostAuthenticationInput::currentAttempts() const
return m_settings->currentAttempts;
}
AuthenticationInput::CodeGeneration HostAuthenticationInput::codeGeneration() const
{
return m_settings->codeGeneration;
}
QString HostAuthenticationInput::generateCode() const
{
quint64 number = 0;
QFile file(QStringLiteral("/dev/random"));
if (file.open(QIODevice::ReadOnly)) {
file.read(reinterpret_cast<char *>(&number), sizeof(number));
file.close();
}
return QString::number(number).right(m_settings->minimumLength).rightJustified(m_settings->minimumLength, QLatin1Char('0'));
}
void HostAuthenticationInput::feedback(
AuthenticationInput::Feedback feedback,
int attemptsRemaining,
const QVariantMap &data,
Authenticator::Methods utilizedMethods)
{
if (!m_inputStack.isEmpty()) {
......@@ -287,30 +327,51 @@ void HostAuthenticationInput::feedback(
clientInterface,
QStringLiteral("Feedback"),
uint(feedback),
uint(attemptsRemaining),
data,
uint(m_activeMethods));
}
}
void HostAuthenticationInput::feedback(
AuthenticationInput::Feedback feedback,
int attemptsRemaining,
Authenticator::Methods utilizedMethods)
{
QVariantMap data;
data.insert(QStringLiteral("attemptsRemaining"), attemptsRemaining);
HostAuthenticationInput::feedback(feedback, data, utilizedMethods);
}
void HostAuthenticationInput::lockedOut()
{
switch (availability()) {
case ManagerLocked:
abortAuthentication(AuthenticationInput::LockedByManager);
feedback(AuthenticationInput::ContactSupport, -1);
break;
case TemporarilyLocked:
abortAuthentication(AuthenticationInput::MaximumAttemptsExceeded);
lockedOut(availability(), &HostAuthenticationInput::abortAuthentication);
}
void HostAuthenticationInput::lockedOut(
Availability availability,
void (HostAuthenticationInput::*errorFunction)(AuthenticationInput::Error error))
{
switch (availability) {
case CodeEntryLockedRecoverable:
(this->*errorFunction)(AuthenticationInput::MaximumAttemptsExceeded);
feedback(AuthenticationInput::TemporarilyLocked, -1);
break;
case PermanentlyLocked:
abortAuthentication(AuthenticationInput::MaximumAttemptsExceeded);
case CodeEntryLockedPermanent:
(this->*errorFunction)(AuthenticationInput::MaximumAttemptsExceeded);
feedback(AuthenticationInput::PermanentlyLocked, -1);
break;
case ManagerLockedRecoverable:
(this->*errorFunction)(AuthenticationInput::LockedByManager);
feedback(AuthenticationInput::ContactSupport, -1);
break;
case ManagerLockedPermanent:
(this->*errorFunction)(AuthenticationInput::LockedByManager);
feedback(AuthenticationInput::PermanentlyLocked, -1);
break;
default:
// Locked out but availability doesn't reflect this. This shouldn't be reachable
// under normal circumstances.
abortAuthentication(AuthenticationInput::SoftwareError);
(this->*errorFunction)(AuthenticationInput::SoftwareError);
}
}
......@@ -359,6 +420,16 @@ void HostAuthenticationInput::handleEnterSecurityCode(const QString &path, const
}
}
void HostAuthenticationInput::handleRequestSecurityCode(const QString &path)
{
const auto connection = QDBusContext::connection().name();
if (!m_inputStack.isEmpty()
&& m_inputStack.last().connection == connection
&& m_inputStack.last().path == path) {
requestSecurityCode();
}
}
void HostAuthenticationInput::handleCancel(const QString &path)
{
const auto connection = QDBusContext::connection().name();
......
......@@ -55,6 +55,7 @@ public slots:
void SetRegistered(const QDBusObjectPath &path, bool registered);
void SetActive(const QDBusObjectPath &path, bool active);
void EnterSecurityCode(const QDBusObjectPath &path, const QString &code);
void RequestSecurityCode(const QDBusObjectPath &path);
void Cancel(const QDBusObjectPath &path);
private:
......@@ -79,11 +80,15 @@ public:
CanAuthenticate,
CanAuthenticateSecurityCode,
SecurityCodeRequired,
ManagerLocked,
TemporarilyLocked,
PermanentlyLocked
CodeEntryLockedRecoverable,
CodeEntryLockedPermanent,
ManagerLockedRecoverable,
ManagerLockedPermanent
};
typedef void (HostAuthenticationInput::*FeedbackFunction)(
AuthenticationInput::Feedback, const QVariantMap &, Authenticator::Methods);
explicit HostAuthenticationInput(
const QString &path,
Authenticator::Methods supportedMethods = Authenticator::SecurityCode,
......@@ -100,16 +105,25 @@ public:
virtual int maximumAttempts() const;
virtual int currentAttempts() const;
virtual AuthenticationInput::CodeGeneration codeGeneration() const;
virtual QString generateCode() const;
virtual void enterSecurityCode(const QString &code) = 0;
virtual void requestSecurityCode() = 0;
void cancel() override = 0;
// Client
void startAuthentication(
AuthenticationInput::Feedback feedback,
const QVariantMap &data,
Authenticator::Methods methods);
virtual void authenticationStarted(
Authenticator::Methods methods,
AuthenticationInput::Feedback feedback = AuthenticationInput::EnterSecurityCode);
void authenticationUnavailable(AuthenticationInput::Error error);
void authenticationResumed(
AuthenticationInput::Feedback feedback,
const QVariantMap &data = QVariantMap(),
Authenticator::Methods utilizedMethods = Authenticator::Methods());
void authenticationEvaluating();
void authenticationProgress(int current, int maximum);
......@@ -122,6 +136,10 @@ public:
virtual void abortAuthentication(AuthenticationInput::Error error);
// Signals
void feedback(
AuthenticationInput::Feedback feedback,
const QVariantMap &data,
Authenticator::Methods utilizedMethods = Authenticator::Methods());
void feedback(
AuthenticationInput::Feedback feedback,
int attemptsRemaining,
......@@ -132,6 +150,9 @@ public:
protected:
void lockedOut();
void lockedOut(
Availability availability,
void (HostAuthenticationInput::*errorFunction)(AuthenticationInput::Error error));
private:
friend class HostAuthenticationInputAdaptor;
......@@ -146,6 +167,7 @@ private:
};
inline void handleEnterSecurityCode(const QString &client, const QString &code);
inline void handleRequestSecurityCode(const QString &path);
inline void handleCancel(const QString &client);
inline void setRegistered(const QString &path, bool registered);
......
......@@ -130,7 +130,8 @@ void HostAuthenticator::authenticate(
m_state = Authenticating;
m_challengeCode = challengeCode;
switch (availability()) {
const auto availability = this->availability();
switch (availability) {
case AuthenticationNotRequired:
qCDebug(daemon, "Authentication requested. Unsecured, authenticating immediately.");
confirmAuthentication();
......@@ -140,26 +141,18 @@ void HostAuthenticator::authenticate(
// Fall through.
case CanAuthenticate:
qCDebug(daemon, "Authentication requested using methods %i.", int(methods));
authenticationStarted(methods, AuthenticationInput::EnterSecurityCode);
startAuthentication(AuthenticationInput::EnterSecurityCode, QVariantMap(), methods);
break;
case SecurityCodeRequired:
m_challengeCode.clear();
authenticationUnavailable(AuthenticationInput::FunctionUnavailable);
break;
case ManagerLocked:
m_challengeCode.clear();
authenticationUnavailable(AuthenticationInput::LockedByManager);
feedback(AuthenticationInput::ContactSupport, -1);
break;
case TemporarilyLocked:
case CodeEntryLockedRecoverable:
case CodeEntryLockedPermanent:
case ManagerLockedRecoverable:
case ManagerLockedPermanent:
m_challengeCode.clear();
authenticationUnavailable(AuthenticationInput::MaximumAttemptsExceeded);
feedback(AuthenticationInput::TemporarilyLocked, -1);
break;
case PermanentlyLocked:
m_challengeCode.clear();
authenticationUnavailable(AuthenticationInput::MaximumAttemptsExceeded);
feedback(AuthenticationInput::PermanentlyLocked, -1);
lockedOut(availability, &HostAuthenticationInput::authenticationUnavailable);
break;
}
}
......@@ -181,16 +174,16 @@ void HostAuthenticator::handleChangeSecurityCode(const QString &client, const QV
switch (availability()) {
case AuthenticationNotRequired:
case SecurityCodeRequired:
m_state = EnteringNewSecurityCode;
authenticationStarted(Authenticator::SecurityCode, AuthenticationInput::EnterNewSecurityCode);
enterCodeChangeState(&HostAuthenticationInput::startAuthentication, Authenticator::SecurityCode);
break;
case CanAuthenticateSecurityCode:
case CanAuthenticate:
authenticationStarted(Authenticator::SecurityCode, AuthenticationInput::EnterSecurityCode);
startAuthentication(AuthenticationInput::EnterSecurityCode, QVariantMap(), Authenticator::SecurityCode);
break;
case ManagerLocked:
case TemporarilyLocked:
case PermanentlyLocked:
case CodeEntryLockedRecoverable:
case CodeEntryLockedPermanent:
case ManagerLockedRecoverable:
case ManagerLockedPermanent:
m_challengeCode.clear();
authenticationUnavailable(AuthenticationInput::FunctionUnavailable);
break;
......@@ -217,12 +210,14 @@ void HostAuthenticator::handleClearSecurityCode(const QString &client)
break;
case CanAuthenticateSecurityCode:
case CanAuthenticate:
authenticationStarted(Authenticator::SecurityCode, AuthenticationInput::EnterSecurityCode);
startAuthentication(
AuthenticationInput::EnterSecurityCode, QVariantMap(), Authenticator::SecurityCode);
break;
case SecurityCodeRequired:
case ManagerLocked:
case TemporarilyLocked:
case PermanentlyLocked:
case CodeEntryLockedRecoverable:
case CodeEntryLockedPermanent:
case ManagerLockedRecoverable:
case ManagerLockedPermanent:
authenticationUnavailable(AuthenticationInput::FunctionUnavailable);
break;
}
......@@ -252,9 +247,9 @@ void HostAuthenticator::enterSecurityCode(const QString &code)
switch ((attempts = checkCode(code))) {
case Success:
case SecurityCodeExpired:
m_state = EnteringNewSecurityCode;
m_currentCode = code;
feedback(AuthenticationInput::EnterNewSecurityCode, -1);
enterCodeChangeState(&HostAuthenticationInput::feedback, Authenticator::SecurityCode);
return;
case LockedOut:
lockedOut();
......@@ -267,6 +262,16 @@ void HostAuthenticator::enterSecurityCode(const QString &code)
m_state = RepeatingNewSecurityCode;
feedback(AuthenticationInput::RepeatNewSecurityCode, -1);
return;
case ExpectingGeneratedSecurityCode:
if (m_generatedCode == code) {
m_newCode = code;
m_state = RepeatingNewSecurityCode;
feedback(AuthenticationInput::RepeatNewSecurityCode, -1);
} else {
feedback(AuthenticationInput::SecurityCodesDoNotMatch, QVariantMap());
feedback(AuthenticationInput::SuggestSecurityCode, generatedCodeData());
}
return;
case RepeatingNewSecurityCode: {
qCDebug(daemon, "New lock code confirmation entered.");
if (m_newCode != code) {
......@@ -278,8 +283,7 @@ void HostAuthenticator::enterSecurityCode(const QString &code)
switch (availability()) {
case AuthenticationNotRequired:
case SecurityCodeRequired:
m_state = EnteringNewSecurityCode;
feedback(AuthenticationInput::EnterNewSecurityCode, -1);
enterCodeChangeState(&HostAuthenticationInput::feedback, Authenticator::SecurityCode);
break;
default:
m_state = AuthenticatingForChange;
......@@ -325,6 +329,16 @@ void HostAuthenticator::enterSecurityCode(const QString &code)
}
}
void HostAuthenticator::requestSecurityCode()
{
if (m_state == EnteringNewSecurityCode
&& codeGeneration() != AuthenticationInput::NoCodeGeneration) {
feedback(AuthenticationInput::EnterNewSecurityCode, generatedCodeData());
} else if (m_state == ExpectingGeneratedSecurityCode) {
feedback(AuthenticationInput::SuggestSecurityCode, generatedCodeData());
}
}
void HostAuthenticator::setCodeFinished(int result)
{
switch (result) {
......@@ -339,9 +353,8 @@ void HostAuthenticator::setCodeFinished(int result)
securityCodeChangeAborted();
} else {
qCDebug(daemon, "Security code disallowed.");
m_state = EnteringNewSecurityCode;
feedback(AuthenticationInput::SecurityCodeInHistory, -1);
feedback(AuthenticationInput::EnterNewSecurityCode, -1);
enterCodeChangeState(&HostAuthenticationInput::feedback, Authenticator::SecurityCode);
}
break;
case Evaluating:
......@@ -375,6 +388,7 @@ void HostAuthenticator::abortAuthentication(AuthenticationInput::Error error)
case AuthenticatingForChange:
case EnteringNewSecurityCode:
case RepeatingNewSecurityCode:
case ExpectingGeneratedSecurityCode:
m_state = ChangeError;
break;
case AuthenticatingForClear:
......@@ -409,6 +423,7 @@ void HostAuthenticator::cancel()
case AuthenticatingForChange:
case EnteringNewSecurityCode:
case RepeatingNewSecurityCode:
case ExpectingGeneratedSecurityCode:
case ChangeError:
securityCodeChangeAborted();
break;
......@@ -485,4 +500,24 @@ void HostAuthenticator::handleCancel(const QString &client)
}
}
QVariantMap HostAuthenticator::generatedCodeData()
{
m_generatedCode = generateCode();
QVariantMap data;
data.insert(QStringLiteral("securityCode"), m_generatedCode);
return data;
}
void HostAuthenticator::enterCodeChangeState(FeedbackFunction feedback, Authenticator::Methods methods)
{
if (codeGeneration