diff --git a/dbus/org.nemomobile.devicelock.AuthenticationInput.xml b/dbus/org.nemomobile.devicelock.AuthenticationInput.xml
index db58394..0f0d227 100644
--- a/dbus/org.nemomobile.devicelock.AuthenticationInput.xml
+++ b/dbus/org.nemomobile.devicelock.AuthenticationInput.xml
@@ -14,6 +14,9 @@
+
+
+
diff --git a/dbus/org.nemomobile.devicelock.DeviceLock.xml b/dbus/org.nemomobile.devicelock.DeviceLock.xml
index 2f449b8..15ba7bf 100644
--- a/dbus/org.nemomobile.devicelock.DeviceLock.xml
+++ b/dbus/org.nemomobile.devicelock.DeviceLock.xml
@@ -7,5 +7,9 @@
+
+
+
+
diff --git a/dbus/org.nemomobile.devicelock.client.AuthenticationInput.xml b/dbus/org.nemomobile.devicelock.client.AuthenticationInput.xml
index af159a9..b04788f 100644
--- a/dbus/org.nemomobile.devicelock.client.AuthenticationInput.xml
+++ b/dbus/org.nemomobile.devicelock.client.AuthenticationInput.xml
@@ -22,7 +22,7 @@
-
+
diff --git a/src/nemo-devicelock/authenticationinput.cpp b/src/nemo-devicelock/authenticationinput.cpp
index a3a2b46..0aa8807 100644
--- a/src/nemo-devicelock/authenticationinput.cpp
+++ b/src/nemo-devicelock/authenticationinput.cpp
@@ -44,12 +44,14 @@ AuthenticationInputAdaptor::AuthenticationInputAdaptor(AuthenticationInput *auth
{
}
-void AuthenticationInputAdaptor::AuthenticationStarted(uint pid, uint utilizedMethods, uint instruction)
+void AuthenticationInputAdaptor::AuthenticationStarted(
+ uint pid, uint utilizedMethods, uint instruction, const QVariantMap &data)
{
m_authenticationInput->handleAuthenticationStarted(
pid,
Authenticator::Methods(utilizedMethods),
- AuthenticationInput::Feedback(instruction));
+ AuthenticationInput::Feedback(instruction),
+ data);
}
void AuthenticationInputAdaptor::AuthenticationUnavailable(uint pid, uint error)
@@ -59,11 +61,13 @@ void AuthenticationInputAdaptor::AuthenticationUnavailable(uint pid, uint error)
AuthenticationInput::Error(error));
}
-void AuthenticationInputAdaptor::AuthenticationResumed(uint utilizedMethods, uint instruction)
+void AuthenticationInputAdaptor::AuthenticationResumed(
+ uint utilizedMethods, uint instruction, const QVariantMap &data)
{
m_authenticationInput->handleAuthenticationResumed(
Authenticator::Methods(utilizedMethods),
- AuthenticationInput::Feedback(instruction));
+ AuthenticationInput::Feedback(instruction),
+ data);
}
void AuthenticationInputAdaptor::AuthenticationEvaluating()
@@ -81,11 +85,11 @@ void AuthenticationInputAdaptor::AuthenticationEnded(bool confirmed)
m_authenticationInput->handleAuthenticationEnded(confirmed);
}
-void AuthenticationInputAdaptor::Feedback(uint feedback, uint attemptsRemaining, uint utilizedMethods)
+void AuthenticationInputAdaptor::Feedback(uint feedback, const QVariantMap &data, uint utilizedMethods)
{
m_authenticationInput->handleFeedback(
AuthenticationInput::Feedback(feedback),
- attemptsRemaining,
+ data,
Authenticator::Methods(utilizedMethods));
}
@@ -115,6 +119,92 @@ void AuthenticationInputAdaptor::Error(uint error)
as fingerprint scanning should now also accept input.
*/
+/*!
+ \enum AuthenticationInput::Feedback
+
+ Message codes for primary feedback during authentication or supplementary feedback following
+ a primary message or error.
+
+ \value EnterSecurityCode Instruct the user to enter their current security code.
+ \value EnterNewSecurityCode Instruct the user to enter a new security code.
+ \value RepeatNewSecurityCode Instruct the user to repeat the new security code.
+ \value SuggestSecurityCode Suggest a new security code the user should use. The code is
+ provided as the \c securityCode member of the feedback data.
+ \value SecurityCodesDoNotMatch Inform the user the user that they entered a different code when
+ repeating their new security code.
+ \value SecurityCodeInHistory Inform the user that the code they entered has already been used.
+ \value SecurityCodeExpired Inform the user that their current code has expired.
+ \value SecurityCodeDueToExpire Inform the user that their current code is due to expire. The
+ expiration date is provided as the \c expirationDate member of the feedback data.
+ \value PartialPrint Inform the user that the fingerprint reader wasn't able to capture a full
+ print.
+ \value PrintIsUnclear Inform the user that fingerprint reader wasn't able to capture a clear
+ print.
+ \value SensorIsDirty Inform the user that the fingerprint reader sensor is dirty.
+ \value SwipeFaster Ask the user to user a faster motion when swiping the fingerprint reader.
+ \value SwipeSlower Ask the user to user a slower motion when swiping the fingerprint reader.
+ \value UnrecognizedFinger Inform the user that the scanned fingerprint did not match any
+ authorized print. The number of times the user may attempt another finger is passed as the
+ \c attemptsRemaining member of the feedback data.
+ \value IncorrectSecurityCode Inform the user that the entered security code is incorrect. The
+ number of times the user may attempt to enter another cod is passed as the \c attemptsRemaining
+ member of the feedback data.
+ \value ContactSupport Inform the user to contact support for help with the preceding error.
+ \value TemporarilyLocked Inform the user that the device has been temporarily locked.
+ \value PermanentlyLocked Inform the user that the device has been permanently locked.
+ \value UnlockToPerformOperation. Inform the user they must unlock the device before they are
+ able to continue.
+*/
+
+/*!
+ \enum AuthenticationInput::Error
+
+ Message codes for feedback when authentication cannot continue.
+
+ \value FunctionUnavailable Authentication could not be performed at this time.
+ \value LockedByManager The device manager has locked down the device and it cannot be unlocked
+ by the user.
+ \value MaximumAttemptsExceeded Too many incorrect security codes have been tried and no more
+ will be accepted.
+ \value Canceled Authentication was canceled.
+ \value SoftwareError The device lock has entered an unexpected state and cannot provide
+ authentication.
+*/
+
+/*!
+ \enum AuthenticationInput::Type
+
+ The type of input.
+
+ \value Authentication Provides authentication for changing settings.
+ \value DeviceLock Provides authentication for unlocking the device.
+*/
+
+/*!
+ \enum AuthenticationInput::Status
+
+ The status of the authentication input.
+
+ \value Idle Nothing is currently trying to authenticate.
+ \value Authenticating Authentication input is currently being accepted.
+ \value Evaluating Authentication is active but not currently accepting input. This may be
+ because a time consuming action is taking place post confirmation, or a forced delay between
+ code entry attempts is being enforced.
+ \value AuthenticationError Authentication is not being accepted following an error.
+*/
+
+/*!
+ \enum AuthenticationInput::CodeGeneration
+
+ The level of support for code generation.
+
+ \value NoCodeGeneration Code generation is supported.
+ \value OptionalCodeGeneration Code generation is available as an alternative to the user
+ choosing their own security code.
+ \value MandatoryCodeGeneration The user is required to use a generated code instead of picking
+ their own.
+*/
+
/*!
Constructs an authentication input which handles requests of a given \a type as a child of
\a parent.
@@ -139,6 +229,8 @@ AuthenticationInput::AuthenticationInput(Type type, QObject *parent)
this, &AuthenticationInput::maximumAttemptsChanged);
connect(m_settings.data(), &SettingsWatcher::inputIsKeyboardChanged,
this, &AuthenticationInput::codeInputIsKeyboardChanged);
+ connect(m_settings.data(), &SettingsWatcher::codeGenerationChanged,
+ this, &AuthenticationInput::codeGenerationChanged);
m_connection->onConnected(this, [this] {
connected();
@@ -207,6 +299,17 @@ int AuthenticationInput::maximumAttempts() const
return m_settings->maximumAttempts;
}
+/*!
+ \property NemoDeviceLock::AuthenticationInput::codeGeneration
+
+ This property holds the level of support for generated security codes.
+*/
+AuthenticationInput::CodeGeneration AuthenticationInput::codeGeneration() const
+{
+ return m_settings->codeGeneration;
+}
+
+
/*!
\property NemoDeviceLock::AuthenticationInput::codeInputIsKeyboard
@@ -322,6 +425,15 @@ void AuthenticationInput::enterSecurityCode(const QString &code)
call(QStringLiteral("EnterSecurityCode"), m_localPath, code);
}
+/*!
+ Sends a request for the security daemon to suggest a new security code.
+*/
+
+void AuthenticationInput::requestSecurityCode()
+{
+ call(QStringLiteral("RequestSecurityCode"), m_localPath);
+}
+
/*!
Sends a request to cancel authentication to the security daemon.
*/
@@ -336,14 +448,15 @@ void AuthenticationInput::cancel()
}
/*!
- \signal NemoDeviceLock::AuthenticationInput::authenticationStarted(Feedback feedback)
+ \signal NemoDeviceLock::AuthenticationInput::authenticationStarted(Feedback feedback, object data)
Signals that an application has requested authentication and that the input should be displayed
- with the given initial \a feedback message.
+ with the given initial \a feedback message. Arguments associated with the feedback message
+ are passed through the \a data object.
*/
void AuthenticationInput::handleAuthenticationStarted(
- int pid, Authenticator::Methods utilizedMethods, Feedback feedback)
+ int pid, Authenticator::Methods utilizedMethods, Feedback feedback, const QVariantMap &data)
{
qCDebug(devicelock, "Authentication started. Methods: %i, Feedback: %i.",
int(utilizedMethods), int(feedback));
@@ -368,7 +481,7 @@ void AuthenticationInput::handleAuthenticationStarted(
emit utilizedMethodsChanged();
}
- emit authenticationStarted(feedback);
+ emit authenticationStarted(feedback, data);
if (m_status != previousStatus) {
emit statusChanged();
@@ -411,7 +524,7 @@ void AuthenticationInput::handleAuthenticationUnavailable(int pid, Error error)
void AuthenticationInput::handleAuthenticationResumed(
- Authenticator::Methods utilizedMethods, Feedback feedback)
+ Authenticator::Methods utilizedMethods, Feedback feedback, const QVariantMap &data)
{
const auto previousStatus = m_status;
const auto previousMethods = m_utilizedMethods;
@@ -423,7 +536,7 @@ void AuthenticationInput::handleAuthenticationResumed(
emit utilizedMethodsChanged();
}
- emit AuthenticationInput::feedback(feedback, -1);
+ emit AuthenticationInput::feedback(feedback, data);
if (m_status != previousStatus) {
emit statusChanged();
@@ -469,24 +582,25 @@ void AuthenticationInput::handleAuthenticationEnded(bool confirmed)
}
/*!
- \signal NemoDeviceLock::AuthenticationInput::feedback(Feedback feedback, int attemptsRemaining)
+ \signal NemoDeviceLock::AuthenticationInput::feedback(Feedback feedback, object data)
- Signals that a \a feedback message should be shown to the user incorporating
- \a attemptsRemaining if it is not equal to -1.
+ Signals that a \a feedback message should be shown to the user. Some feedback will also
+ include \a data that should be incorporated into the message, the members of data
+ accompanying a feedback message will be described in the documentation for that feedback.
*/
void AuthenticationInput::handleFeedback(
- Feedback feedback, int attemptsRemaining, Authenticator::Methods utilizedMethods)
+ Feedback feedback, const QVariantMap &data, Authenticator::Methods utilizedMethods)
{
if (m_status != Idle) {
- qCDebug(devicelock, "Authentication feedback %i. Attempts remaining: %i. Methods: %i",
- int(feedback), attemptsRemaining, int(utilizedMethods));
+ qCDebug(devicelock, "Authentication feedback %i. Methods: %i",
+ int(feedback), int(utilizedMethods));
const bool methodsChanged = m_utilizedMethods != utilizedMethods;
m_utilizedMethods = utilizedMethods;
- emit AuthenticationInput::feedback(feedback, attemptsRemaining);
+ emit AuthenticationInput::feedback(feedback, data);
if (methodsChanged) {
emit utilizedMethodsChanged();
diff --git a/src/nemo-devicelock/authenticationinput.h b/src/nemo-devicelock/authenticationinput.h
index 476d4d4..43461e6 100644
--- a/src/nemo-devicelock/authenticationinput.h
+++ b/src/nemo-devicelock/authenticationinput.h
@@ -34,6 +34,7 @@
#define NEMODEVICELOCK_AUTHENTICATIONINPUT_H
#include
+#include
namespace NemoDeviceLock {
@@ -46,13 +47,13 @@ class AuthenticationInputAdaptor : public QDBusAbstractAdaptor
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 @@ class NEMODEVICELOCK_EXPORT AuthenticationInput : public QObject, private Connec
PermanentlyLocked,
UnlockToPerformOperation
};
+ Q_ENUM(Feedback)
enum Error {
FunctionUnavailable,
@@ -103,6 +105,7 @@ class NEMODEVICELOCK_EXPORT AuthenticationInput : public QObject, private Connec
Canceled,
SoftwareError
};
+ Q_ENUM(Error)
enum Type {
Authentication,
@@ -115,6 +118,14 @@ class NEMODEVICELOCK_EXPORT AuthenticationInput : public QObject, private Connec
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 @@ class NEMODEVICELOCK_EXPORT AuthenticationInput : public QObject, private Connec
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 @@ class NEMODEVICELOCK_EXPORT AuthenticationInput : public QObject, private Connec
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 @@ class NEMODEVICELOCK_EXPORT AuthenticationInput : public QObject, private Connec
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;
diff --git a/src/nemo-devicelock/devicelock.cpp b/src/nemo-devicelock/devicelock.cpp
index b721257..d63fc60 100644
--- a/src/nemo-devicelock/devicelock.cpp
+++ b/src/nemo-devicelock/devicelock.cpp
@@ -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(QStringLiteral("Enabled"), [this](bool enabled) {
if (m_enabled != enabled) {
m_enabled = enabled;
diff --git a/src/nemo-devicelock/devicelock.h b/src/nemo-devicelock/devicelock.h
index a891eff..e73b12b 100644
--- a/src/nemo-devicelock/devicelock.h
+++ b/src/nemo-devicelock/devicelock.h
@@ -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 @@ class NEMODEVICELOCK_EXPORT DeviceLock : public QObject, private ConnectionClien
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 @@ class NEMODEVICELOCK_EXPORT DeviceLock : public QObject, private ConnectionClien
void unlocked();
void unlockError();
+ void notice(Notice notice, const QVariantMap &data);
+
+private slots:
+ void handleNotice(uint notice, const QVariantMap &data);
+
private:
inline void connected();
diff --git a/src/nemo-devicelock/host/cli/cliauthenticator.cpp b/src/nemo-devicelock/host/cli/cliauthenticator.cpp
index b2094ad..b81449b 100644
--- a/src/nemo-devicelock/host/cli/cliauthenticator.cpp
+++ b/src/nemo-devicelock/host/cli/cliauthenticator.cpp
@@ -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;
}
diff --git a/src/nemo-devicelock/host/cli/clidevicelock.cpp b/src/nemo-devicelock/host/cli/clidevicelock.cpp
index d1a3b89..85d5f3e 100644
--- a/src/nemo-devicelock/host/cli/clidevicelock.cpp
+++ b/src/nemo-devicelock/host/cli/clidevicelock.cpp
@@ -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;
}
diff --git a/src/nemo-devicelock/host/hostauthenticationinput.cpp b/src/nemo-devicelock/host/hostauthenticationinput.cpp
index 66fc79d..9c00b39 100644
--- a/src/nemo-devicelock/host/hostauthenticationinput.cpp
+++ b/src/nemo-devicelock/host/hostauthenticationinput.cpp
@@ -34,6 +34,8 @@
#include "settingswatcher.h"
+#include
+
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(&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();
diff --git a/src/nemo-devicelock/host/hostauthenticationinput.h b/src/nemo-devicelock/host/hostauthenticationinput.h
index e1ec8fc..04d9dc4 100644
--- a/src/nemo-devicelock/host/hostauthenticationinput.h
+++ b/src/nemo-devicelock/host/hostauthenticationinput.h
@@ -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 @@ class HostAuthenticationInput : public HostObject
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 @@ class HostAuthenticationInput : public HostObject
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 @@ class HostAuthenticationInput : public HostObject
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 @@ class HostAuthenticationInput : public HostObject
protected:
void lockedOut();
+ void lockedOut(
+ Availability availability,
+ void (HostAuthenticationInput::*errorFunction)(AuthenticationInput::Error error));
private:
friend class HostAuthenticationInputAdaptor;
@@ -146,6 +167,7 @@ class HostAuthenticationInput : public HostObject
};
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);
diff --git a/src/nemo-devicelock/host/hostauthenticator.cpp b/src/nemo-devicelock/host/hostauthenticator.cpp
index 21ddc77..4b5b894 100644
--- a/src/nemo-devicelock/host/hostauthenticator.cpp
+++ b/src/nemo-devicelock/host/hostauthenticator.cpp
@@ -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() == AuthenticationInput::MandatoryCodeGeneration) {
+ m_state = ExpectingGeneratedSecurityCode;
+ (this->*feedback)(AuthenticationInput::SuggestSecurityCode, generatedCodeData(), methods);
+ } else {
+ m_state = EnteringNewSecurityCode;
+ (this->*feedback)(AuthenticationInput::EnterNewSecurityCode, QVariantMap(), methods);
+ }
+}
+
}
diff --git a/src/nemo-devicelock/host/hostauthenticator.h b/src/nemo-devicelock/host/hostauthenticator.h
index 17fa81c..f1d59b0 100644
--- a/src/nemo-devicelock/host/hostauthenticator.h
+++ b/src/nemo-devicelock/host/hostauthenticator.h
@@ -115,6 +115,7 @@ class HostAuthenticator : public HostAuthenticationInput
int setCode(const QString &oldCode, const QString &newCode) override = 0;
void enterSecurityCode(const QString &code) override;
+ void requestSecurityCode() override;
void cancel() override;
void confirmAuthentication() override;
@@ -144,6 +145,7 @@ class HostAuthenticator : public HostAuthenticationInput
AuthenticatingForChange,
EnteringNewSecurityCode,
RepeatingNewSecurityCode,
+ ExpectingGeneratedSecurityCode,
Changing,
ChangeError,
ChangeCanceled,
@@ -157,6 +159,9 @@ class HostAuthenticator : public HostAuthenticationInput
inline void handleChangeSecurityCode(const QString &client, const QVariant &challengeCode);
inline void handleClearSecurityCode(const QString &client);
inline void handleCancel(const QString &client);
+ inline QVariantMap generatedCodeData();
+ inline void enterCodeChangeState(
+ FeedbackFunction feedback, Authenticator::Methods methods = Authenticator::Methods());
friend class HostAuthenticatorAdaptor;
friend class HostSecurityCodeSettingsAdaptor;
@@ -166,6 +171,7 @@ class HostAuthenticator : public HostAuthenticationInput
QVariant m_challengeCode;
QString m_currentCode;
QString m_newCode;
+ QString m_generatedCode;
State m_state;
};
diff --git a/src/nemo-devicelock/host/hostdevicelock.cpp b/src/nemo-devicelock/host/hostdevicelock.cpp
index 6a91b0a..73c9660 100644
--- a/src/nemo-devicelock/host/hostdevicelock.cpp
+++ b/src/nemo-devicelock/host/hostdevicelock.cpp
@@ -111,37 +111,29 @@ void HostDeviceLock::unlock()
m_state = Authenticating;
- switch (availability()) {
+ switch (const auto availability = this->availability()) {
case AuthenticationNotRequired:
m_state = Idle;
setLocked(false);
return;
case CanAuthenticate:
- authenticationStarted(
- Authenticator::SecurityCode | Authenticator::Fingerprint,
- AuthenticationInput::EnterSecurityCode);
+ startAuthentication(
+ AuthenticationInput::EnterSecurityCode,
+ QVariantMap(),
+ Authenticator::SecurityCode | Authenticator::Fingerprint);
break;
case CanAuthenticateSecurityCode:
- authenticationStarted(Authenticator::SecurityCode, AuthenticationInput::EnterSecurityCode);
+ startAuthentication(AuthenticationInput::EnterSecurityCode, QVariantMap(), Authenticator::SecurityCode);
break;
case SecurityCodeRequired:
- m_state = EnteringNewSecurityCode;
- authenticationStarted(Authenticator::SecurityCode, AuthenticationInput::EnterNewSecurityCode);
- break;
- case ManagerLocked:
- m_state = AuthenticationError;
- authenticationUnavailable(AuthenticationInput::LockedByManager);
- feedback(AuthenticationInput::ContactSupport, -1);
+ enterCodeChangeState(&HostAuthenticationInput::startAuthentication);
break;
- case TemporarilyLocked:
+ case CodeEntryLockedRecoverable:
+ case CodeEntryLockedPermanent:
+ case ManagerLockedRecoverable:
+ case ManagerLockedPermanent:
m_state = AuthenticationError;
- authenticationUnavailable(AuthenticationInput::MaximumAttemptsExceeded);
- feedback(AuthenticationInput::TemporarilyLocked, -1);
- break;
- case PermanentlyLocked:
- m_state = AuthenticationError;
- authenticationUnavailable(AuthenticationInput::MaximumAttemptsExceeded);
- feedback(AuthenticationInput::PermanentlyLocked, -1);
+ lockedOut(availability, &HostAuthenticationInput::authenticationUnavailable);
break;
}
@@ -162,7 +154,7 @@ void HostDeviceLock::enterSecurityCode(const QString &code)
m_state = EnteringNewSecurityCode;
m_currentCode = code;
feedback(AuthenticationInput::SecurityCodeExpired, -1);
- feedback(AuthenticationInput::EnterNewSecurityCode, -1);
+ enterCodeChangeState(&HostAuthenticationInput::feedback);
break;
case SecurityCodeInHistory:
break;
@@ -191,6 +183,16 @@ void HostDeviceLock::enterSecurityCode(const QString &code)
m_state = RepeatingNewSecurityCode;
feedback(AuthenticationInput::RepeatNewSecurityCode, -1);
break;
+ 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());
+ }
+ break;
case RepeatingNewSecurityCode:
if (m_newCode != code) {
m_newCode.clear();
@@ -200,8 +202,7 @@ void HostDeviceLock::enterSecurityCode(const QString &code)
switch (availability()) {
case AuthenticationNotRequired:
case SecurityCodeRequired:
- m_state = EnteringNewSecurityCode;
- feedback(AuthenticationInput::EnterNewSecurityCode, -1);
+ enterCodeChangeState(&HostAuthenticationInput::feedback);
break;
default:
m_state = Authenticating;
@@ -221,6 +222,16 @@ void HostDeviceLock::enterSecurityCode(const QString &code)
}
}
+void HostDeviceLock::requestSecurityCode()
+{
+ if (m_state == EnteringNewSecurityCode
+ && codeGeneration() != AuthenticationInput::NoCodeGeneration) {
+ feedback(AuthenticationInput::EnterNewSecurityCode, generatedCodeData());
+ } else if (m_state == ExpectingGeneratedSecurityCode) {
+ feedback(AuthenticationInput::SuggestSecurityCode, generatedCodeData());
+ }
+}
+
void HostDeviceLock::unlockFinished(int result)
{
switch (result) {
@@ -271,9 +282,8 @@ void HostDeviceLock::setCodeFinished(int result)
break;
case SecurityCodeInHistory:
qCDebug(daemon, "Security code disallowed.");
- m_state = EnteringNewSecurityCode;
feedback(AuthenticationInput::SecurityCodeInHistory, -1);
- feedback(AuthenticationInput::EnterNewSecurityCode, -1);
+ enterCodeChangeState(&HostAuthenticationInput::feedback);
break;
case Evaluating:
if (m_state == RepeatingNewSecurityCode) {
@@ -327,9 +337,10 @@ void HostDeviceLock::confirmAuthentication()
authenticationEnded(true);
break;
- case ManagerLocked:
- case TemporarilyLocked:
- case PermanentlyLocked:
+ case CodeEntryLockedRecoverable:
+ case CodeEntryLockedPermanent:
+ case ManagerLockedRecoverable:
+ case ManagerLockedPermanent:
authenticationEnded(false);
break;
}
@@ -347,6 +358,7 @@ void HostDeviceLock::abortAuthentication(AuthenticationInput::Error error)
case Unlocking:
case EnteringNewSecurityCode:
case RepeatingNewSecurityCode:
+ case ExpectingGeneratedSecurityCode:
case ChangingSecurityCode:
m_state = AuthenticationError;
break;
@@ -357,19 +369,26 @@ void HostDeviceLock::abortAuthentication(AuthenticationInput::Error error)
HostAuthenticationInput::abortAuthentication(error);
}
+void HostDeviceLock::notice(DeviceLock::Notice notice, const QVariantMap &data)
+{
+ broadcastSignal(
+ QStringLiteral("org.nemomobile.devicelock.DeviceLock"),
+ QStringLiteral("Notice"),
+ NemoDBus::marshallArguments(uint(notice), data));
+}
+
void HostDeviceLock::stateChanged()
{
const auto previousState = m_lockState;
switch (availability()) {
- case ManagerLocked:
- m_lockState = DeviceLock::ManagerLockout;
- break;
- case TemporarilyLocked:
- m_lockState = DeviceLock::TemporaryLockout;
+ case CodeEntryLockedRecoverable:
+ case CodeEntryLockedPermanent:
+ m_lockState = DeviceLock::CodeEntryLockout;
break;
- case PermanentlyLocked:
- m_lockState = DeviceLock::PermanentLockout;
+ case ManagerLockedRecoverable:
+ case ManagerLockedPermanent:
+ m_lockState = DeviceLock::ManagerLockout;
break;
case SecurityCodeRequired:
m_lockState = DeviceLock::Locked;
@@ -395,14 +414,14 @@ void HostDeviceLock::lockedChanged()
void HostDeviceLock::availabilityChanged()
{
- const auto available = availability();
+ const auto availability = this->availability();
propertyChanged(
QStringLiteral("org.nemomobile.devicelock.DeviceLock"),
QStringLiteral("Enabled"),
- available != AuthenticationNotRequired);
+ availability != AuthenticationNotRequired);
- switch (available) {
+ switch (availability) {
case AuthenticationNotRequired:
switch (m_state) {
case Authenticating:
@@ -431,7 +450,7 @@ void HostDeviceLock::availabilityChanged()
break;
case AuthenticationError:
m_state = Authenticating;
- authenticationResumed(AuthenticationInput::EnterSecurityCode, Authenticator::SecurityCode);
+ authenticationResumed(AuthenticationInput::EnterSecurityCode, QVariantMap(), Authenticator::SecurityCode);
break;
default:
break;
@@ -440,48 +459,19 @@ void HostDeviceLock::availabilityChanged()
case SecurityCodeRequired:
switch (m_state) {
case Authenticating:
- m_state = EnteringNewSecurityCode;
- feedback(AuthenticationInput::EnterNewSecurityCode, -1, Authenticator::SecurityCode);
- break;
- case AuthenticationError:
- m_state = EnteringNewSecurityCode;
- authenticationResumed(AuthenticationInput::EnterNewSecurityCode, Authenticator::SecurityCode);
- break;
- default:
- break;
- }
- break;
- case ManagerLocked:
- setLocked(true);
-
- switch (m_state) {
- case Authenticating:
- case EnteringNewSecurityCode:
- case RepeatingNewSecurityCode:
- case AuthenticationError:
- abortAuthentication(AuthenticationInput::LockedByManager);
- feedback(AuthenticationInput::ContactSupport, -1);
- break;
- default:
+ enterCodeChangeState(&HostAuthenticationInput::feedback, Authenticator::SecurityCode);
break;
- }
- break;
- case TemporarilyLocked:
- setLocked(true);
-
- switch (m_state) {
- case Authenticating:
- case EnteringNewSecurityCode:
- case RepeatingNewSecurityCode:
case AuthenticationError:
- abortAuthentication(AuthenticationInput::MaximumAttemptsExceeded);
- feedback(AuthenticationInput::TemporarilyLocked, -1);
+ enterCodeChangeState(&HostAuthenticationInput::authenticationResumed, Authenticator::SecurityCode);
break;
default:
break;
}
break;
- case PermanentlyLocked:
+ case CodeEntryLockedRecoverable:
+ case CodeEntryLockedPermanent:
+ case ManagerLockedRecoverable:
+ case ManagerLockedPermanent:
setLocked(true);
switch (m_state) {
@@ -489,8 +479,7 @@ void HostDeviceLock::availabilityChanged()
case EnteringNewSecurityCode:
case RepeatingNewSecurityCode:
case AuthenticationError:
- abortAuthentication(AuthenticationInput::MaximumAttemptsExceeded);
- feedback(AuthenticationInput::PermanentlyLocked, -1);
+ lockedOut(availability, &HostAuthenticationInput::abortAuthentication);
break;
default:
break;
@@ -513,4 +502,24 @@ void HostDeviceLock::automaticLockingChanged()
{
}
+QVariantMap HostDeviceLock::generatedCodeData()
+{
+ m_generatedCode = generateCode();
+
+ QVariantMap data;
+ data.insert(QStringLiteral("securityCode"), m_generatedCode);
+ return data;
+}
+
+void HostDeviceLock::enterCodeChangeState(FeedbackFunction feedback, Authenticator::Methods methods)
+{
+ if (codeGeneration() == AuthenticationInput::MandatoryCodeGeneration) {
+ m_state = ExpectingGeneratedSecurityCode;
+ (this->*feedback)(AuthenticationInput::SuggestSecurityCode, generatedCodeData(), methods);
+ } else {
+ m_state = EnteringNewSecurityCode;
+ (this->*feedback)(AuthenticationInput::EnterNewSecurityCode, QVariantMap(), methods);
+ }
+}
+
}
diff --git a/src/nemo-devicelock/host/hostdevicelock.h b/src/nemo-devicelock/host/hostdevicelock.h
index 8025def..63625fb 100644
--- a/src/nemo-devicelock/host/hostdevicelock.h
+++ b/src/nemo-devicelock/host/hostdevicelock.h
@@ -82,6 +82,7 @@ class HostDeviceLock : public HostAuthenticationInput
void unlock();
void enterSecurityCode(const QString &code) override;
+ void requestSecurityCode() override;
void cancel() override;
Availability availability() const override = 0;
@@ -104,6 +105,9 @@ class HostDeviceLock : public HostAuthenticationInput
void unlockFinished(int result);
void setCodeFinished(int result);
+ // Signals
+ void notice(DeviceLock::Notice notice, const QVariantMap &data);
+
protected:
virtual void stateChanged();
@@ -115,6 +119,7 @@ class HostDeviceLock : public HostAuthenticationInput
Authenticating,
Unlocking,
EnteringNewSecurityCode,
+ ExpectingGeneratedSecurityCode,
RepeatingNewSecurityCode,
ChangingSecurityCode,
Canceled,
@@ -123,11 +128,15 @@ class HostDeviceLock : public HostAuthenticationInput
inline bool isEnabled() const;
inline void unlockingChanged();
+ inline QVariantMap generatedCodeData();
+ inline void enterCodeChangeState(
+ FeedbackFunction feedback, Authenticator::Methods methods = Authenticator::Methods());
HostDeviceLockAdaptor m_adaptor;
QExplicitlySharedDataPointer m_settings;
QString m_currentCode;
QString m_newCode;
+ QString m_generatedCode;
State m_state;
DeviceLock::LockState m_lockState;
};
diff --git a/src/nemo-devicelock/host/hostobject.cpp b/src/nemo-devicelock/host/hostobject.cpp
index 2ecf2bb..94b9e48 100644
--- a/src/nemo-devicelock/host/hostobject.cpp
+++ b/src/nemo-devicelock/host/hostobject.cpp
@@ -100,12 +100,17 @@ void HostObject::propertyChanged(const QString &interface, const QString &proper
const QVariantMap properties = { { property, value } };
- QDBusMessage message = QDBusMessage::createSignal(
- m_path,
+ broadcastSignal(
QStringLiteral("org.freedesktop.DBus.Properties"),
- QStringLiteral("PropertiesChanged"));
+ QStringLiteral("PropertiesChanged"),
+ NemoDBus::marshallArguments(interface, properties, QStringList()));
+}
+
+void HostObject::broadcastSignal(const QString &interface, const QString &name, const QVariantList &arguments)
+{
+ QDBusMessage message = QDBusMessage::createSignal(m_path, interface, name);
- message.setArguments(NemoDBus::marshallArguments(interface, properties, QStringList()));
+ message.setArguments(arguments);
for (const auto connectionName : m_connections) {
QDBusConnection(connectionName).send(message);
diff --git a/src/nemo-devicelock/host/hostobject.h b/src/nemo-devicelock/host/hostobject.h
index 6bc1b0d..97171c7 100644
--- a/src/nemo-devicelock/host/hostobject.h
+++ b/src/nemo-devicelock/host/hostobject.h
@@ -70,6 +70,7 @@ class HostObject : public QObject, protected QDBusContext
protected:
void propertyChanged(const QString &interface, const QString &property, const QVariant &value);
+ void broadcastSignal(const QString &interface, const QString &name, const QVariantList &arguments);
template inline bool sendToActiveClient(
const QString &interface,
diff --git a/src/nemo-devicelock/private/settingswatcher.cpp b/src/nemo-devicelock/private/settingswatcher.cpp
index c1d653c..447b8ef 100644
--- a/src/nemo-devicelock/private/settingswatcher.cpp
+++ b/src/nemo-devicelock/private/settingswatcher.cpp
@@ -92,6 +92,7 @@ SettingsWatcher::SettingsWatcher(QObject *parent)
, maximumAutomaticLocking(-1)
, absoluteMaximumAttempts(-1)
, supportedDeviceResetOptions(DeviceReset::Reboot)
+ , codeGeneration(AuthenticationInput::NoCodeGeneration)
, inputIsKeyboard(false)
, currentCodeIsDigitOnly(true)
, isHomeEncrypted(false)
@@ -268,6 +269,7 @@ void SettingsWatcher::reloadSettings()
read(settings, this, "absolute_maximum_attempts", -1, &absoluteMaximumAttempts, &SettingsWatcher::absoluteMaximumAttemptsChanged);
read(settings, this, "supported_device_reset_options", DeviceReset::Options(DeviceReset::Reboot), &supportedDeviceResetOptions, &SettingsWatcher::supportedDeviceResetOptionsChanged);
read(settings, this, "code_is_mandatory", false, &codeIsMandatory, &SettingsWatcher::codeIsMandatoryChanged);
+ read(settings, this, "code_generation", AuthenticationInput::NoCodeGeneration, &codeGeneration, &SettingsWatcher::codeGenerationChanged);
g_key_file_free(settings);
}
diff --git a/src/nemo-devicelock/private/settingswatcher.h b/src/nemo-devicelock/private/settingswatcher.h
index 7bc1142..b262a77 100644
--- a/src/nemo-devicelock/private/settingswatcher.h
+++ b/src/nemo-devicelock/private/settingswatcher.h
@@ -33,7 +33,7 @@
#ifndef NEMODEVICELOCK_SETTINGSWATCHER_H
#define NEMODEVICELOCK_SETTINGSWATCHER_H
-#include
+#include
#include
#include
@@ -57,6 +57,11 @@ template <> inline QMetaEnum resolveMetaEnum() {
template <> inline DeviceReset::Options settingsValueFromString(const char *string) {
return flagsFromString(string); }
+template <> inline QMetaEnum resolveMetaEnum() {
+ return resolveMetaEnum(&AuthenticationInput::staticMetaObject, "CodeGeneration"); }
+template <> inline AuthenticationInput::CodeGeneration settingsValueFromString(const char *string) {
+ return AuthenticationInput::CodeGeneration(flagsFromString(resolveMetaEnum(), string)); }
+
class NEMODEVICELOCK_EXPORT SettingsWatcher : public QSocketNotifier, public QSharedData
{
Q_OBJECT
@@ -65,7 +70,6 @@ class NEMODEVICELOCK_EXPORT SettingsWatcher : public QSocketNotifier, public QSh
static SettingsWatcher *instance();
-
int automaticLocking;
int minimumLength;
int maximumLength;
@@ -77,6 +81,7 @@ class NEMODEVICELOCK_EXPORT SettingsWatcher : public QSocketNotifier, public QSh
int maximumAutomaticLocking;
int absoluteMaximumAttempts;
DeviceReset::Options supportedDeviceResetOptions;
+ AuthenticationInput::CodeGeneration codeGeneration;
bool inputIsKeyboard;
bool currentCodeIsDigitOnly;
bool isHomeEncrypted;
@@ -111,6 +116,7 @@ class NEMODEVICELOCK_EXPORT SettingsWatcher : public QSocketNotifier, public QSh
void inputIsKeyboardChanged();
void currentCodeIsDigitOnlyChanged();
void codeIsMandatoryChanged();
+ void codeGenerationChanged();
private:
explicit SettingsWatcher(QObject *parent = nullptr);