on xenial help sign in
Check AccountsService and current uid to confirm user should be ID'd by fingerprint
ee69752Michael Terry
plugins/AccountsService/AccountsService.cpp+9−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013, 2015 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@
36#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
36#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
37#define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
37#define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
38#define PROP_EMAIL QStringLiteral("Email")
38#define PROP_EMAIL QStringLiteral("Email")
39+#define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
39#define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
40#define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
40#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
41#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
41#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
42#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
@@ -93,6 +94,7 @@ AccountsService::AccountsService(QObject* parent, const QString &user)
93 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral("keymapsChanged"));
94 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral("keymapsChanged"));
94 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
95 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
95 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
96 registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
97+ registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral("enableFingerprintIdentificationChanged"));
96 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
98 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
97 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
99 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
98 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
100 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
@@ -176,6 +178,12 @@ void AccountsService::markDemoEdgeCompleted(const QString &edge)
176 }
178 }
177}
179}
178
180
181+bool AccountsService::enableFingerprintIdentification() const
182+{
183+ auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
184+ return value.toBool();
185+}
186+
179bool AccountsService::enableLauncherWhileLocked() const
187bool AccountsService::enableLauncherWhileLocked() const
180{
188{
181 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
189 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
plugins/AccountsService/AccountsService.h+6−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013, 2015 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -41,6 +41,9 @@ class AccountsService: public QObject
41 Q_PROPERTY (QStringList demoEdgesCompleted
41 Q_PROPERTY (QStringList demoEdgesCompleted
42 READ demoEdgesCompleted
42 READ demoEdgesCompleted
43 NOTIFY demoEdgesCompletedChanged)
43 NOTIFY demoEdgesCompletedChanged)
44+ Q_PROPERTY (bool enableFingerprintIdentification
45+ READ enableFingerprintIdentification
46+ NOTIFY enableFingerprintIdentificationChanged)
44 Q_PROPERTY (bool enableLauncherWhileLocked
47 Q_PROPERTY (bool enableLauncherWhileLocked
45 READ enableLauncherWhileLocked
48 READ enableLauncherWhileLocked
46 NOTIFY enableLauncherWhileLockedChanged)
49 NOTIFY enableLauncherWhileLockedChanged)
@@ -91,6 +94,7 @@ public:
91 void setDemoEdges(bool demoEdges);
94 void setDemoEdges(bool demoEdges);
92 QStringList demoEdgesCompleted() const;
95 QStringList demoEdgesCompleted() const;
93 Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
96 Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
97+ bool enableFingerprintIdentification() const;
94 bool enableLauncherWhileLocked() const;
98 bool enableLauncherWhileLocked() const;
95 bool enableIndicatorsWhileLocked() const;
99 bool enableIndicatorsWhileLocked() const;
96 QString backgroundFile() const;
100 QString backgroundFile() const;
@@ -112,6 +116,7 @@ Q_SIGNALS:
112 void userChanged();
116 void userChanged();
113 void demoEdgesChanged();
117 void demoEdgesChanged();
114 void demoEdgesCompletedChanged();
118 void demoEdgesCompletedChanged();
119+ void enableFingerprintIdentificationChanged();
115 void enableLauncherWhileLockedChanged();
120 void enableLauncherWhileLockedChanged();
116 void enableIndicatorsWhileLockedChanged();
121 void enableIndicatorsWhileLockedChanged();
117 void backgroundFileChanged();
122 void backgroundFileChanged();
plugins/IntegratedLightDM/liblightdm/UsersModel.cpp+4−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -52,6 +52,7 @@ UsersModel::UsersModel(QObject *parent) :
52 roles[SessionRole] = "session";
52 roles[SessionRole] = "session";
53 roles[HasMessagesRole] = "hasMessages";
53 roles[HasMessagesRole] = "hasMessages";
54 roles[ImagePathRole] = "imagePath";
54 roles[ImagePathRole] = "imagePath";
55+ roles[UidRole] = "uid";
55 setRoleNames(roles);
56 setRoleNames(roles);
56
57
57 connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
58 connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
@@ -101,6 +102,8 @@ QVariant UsersModel::data(const QModelIndex &index, int role) const
101 return d->entries[row].has_messages;
102 return d->entries[row].has_messages;
102 case UsersModel::ImagePathRole:
103 case UsersModel::ImagePathRole:
103 return "";
104 return "";
105+ case UsersModel::UidRole:
106+ return d->entries[row].uid;
104 default:
107 default:
105 return QVariant();
108 return QVariant();
106 }
109 }
plugins/IntegratedLightDM/liblightdm/UsersModel.h+2−1
@@ -50,7 +50,8 @@ public:
50 SessionRole,
50 SessionRole,
51 HasMessagesRole,
51 HasMessagesRole,
52 ImagePathRole,
52 ImagePathRole,
53− BackgroundPathRole
53+ BackgroundPathRole,
54+ UidRole
54 };
55 };
55
56
56 int rowCount(const QModelIndex &parent) const override;
57 int rowCount(const QModelIndex &parent) const override;
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp+5−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
26#include <QDir>
26#include <QDir>
27#include <QSettings>
27#include <QSettings>
28#include <QStringList>
28#include <QStringList>
29+#include <unistd.h>
29
30
30namespace QLightDM
31namespace QLightDM
31{
32{
@@ -37,6 +38,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
37{
38{
38 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
39 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
39 QString currentUser = g_get_user_name();
40 QString currentUser = g_get_user_name();
41+ uid_t currentUid = getuid();
40
42
41 if (demoFile.exists()) {
43 if (demoFile.exists()) {
42 QSettings settings(demoFile.filePath(), QSettings::NativeFormat);
44 QSettings settings(demoFile.filePath(), QSettings::NativeFormat);
@@ -46,10 +48,10 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
46 Q_FOREACH(const QString &user, users)
48 Q_FOREACH(const QString &user, users)
47 {
49 {
48 QString name = settings.value(user + "/name", user).toString();
50 QString name = settings.value(user + "/name", user).toString();
49− entries.append({user, name, 0, 0, false, false, 0, 0});
51+ entries.append({user, name, 0, 0, false, false, 0, 0, currentUid++});
50 }
52 }
51 } else {
53 } else {
52− entries.append({currentUser, 0, 0, 0, false, false, 0, 0});
54+ entries.append({currentUser, 0, 0, 0, false, false, 0, 0, currentUid});
53
55
54 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
56 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
55 this, [this](const QString &user) {
57 this, [this](const QString &user) {
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h+2−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@ public:
40 bool has_messages;
40 bool has_messages;
41 QString session;
41 QString session;
42 QString infographic;
42 QString infographic;
43+ uid_t uid;
43};
44};
44
45
45class UsersModelPrivate : public QObject
46class UsersModelPrivate : public QObject
qml/Greeter/Greeter.qml+19−10
@@ -487,6 +487,9 @@ Showable {
487 objectName: "biometryd"
487 objectName: "biometryd"
488
488
489 property var operation: null
489 property var operation: null
490+ readonly property bool idEnabled: root.active &&
491+ Biometryd.defaultDevice &&
492+ AccountsService.enableFingerprintIdentification
490
493
491 function cancelOperation() {
494 function cancelOperation() {
492 if (operation) {
495 if (operation) {
@@ -498,29 +501,35 @@ Showable {
498 function restartOperation() {
501 function restartOperation() {
499 cancelOperation();
502 cancelOperation();
500
503
501− if (Biometryd.defaultDevice && true /* FIXME check AS */) {
504+ if (idEnabled) {
502 var identifier = Biometryd.defaultDevice.identifier;
505 var identifier = Biometryd.defaultDevice.identifier;
503 operation = identifier.identifyUser();
506 operation = identifier.identifyUser();
504 operation.start(biometryd);
507 operation.start(biometryd);
505 }
508 }
506 }
509 }
507
510
511+ function failOperation(reason) {
512+ console.log("Failed to identify user by fingerprint:", reason);
513+ d.fingerprintFailureCount++;
514+ restartOperation();
515+ if (loader.item)
516+ loader.item.showErrorMessage(i18n.tr("Try again"));
517+ }
518+
508 Component.onCompleted: restartOperation()
519 Component.onCompleted: restartOperation()
509 Component.onDestruction: cancelOperation()
520 Component.onDestruction: cancelOperation()
521+ onIdEnabledChanged: restartOperation()
510
522
511 onSucceeded: {
523 onSucceeded: {
512− // FIXME validate result.uid
524+ if (result.uid !== lightDM.users.data(d.currentIndex, lightDM.userRoles.UidRole)) {
525+ failOperation("not the selected user");
526+ return;
527+ }
528+ console.log("Identified user by fingerprint:" result.uid);
513 d.fingerprintFailureCount = 0;
529 d.fingerprintFailureCount = 0;
514− restartOperation();
515 if (root.active)
530 if (root.active)
516 root.forcedUnlock = true;
531 root.forcedUnlock = true;
517 }
532 }
518− onFailed: {
533+ onFailed: failOperation(reason)
519− console.log("Failed to identify user:", reason);
520− d.fingerprintFailureCount++;
521− restartOperation();
522− if (loader.item)
523− loader.item.showErrorMessage(i18n.tr("Try again"));
524− }
525 }
534 }
526}
535}
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cpp+4−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -46,6 +46,7 @@ UsersModel::UsersModel(QObject *parent) :
46 roles[SessionRole] = "session";
46 roles[SessionRole] = "session";
47 roles[HasMessagesRole] = "hasMessages";
47 roles[HasMessagesRole] = "hasMessages";
48 roles[ImagePathRole] = "imagePath";
48 roles[ImagePathRole] = "imagePath";
49+ roles[UidRole] = "uid";
49 setRoleNames(roles);
50 setRoleNames(roles);
50}
51}
51
52
@@ -95,6 +96,8 @@ QVariant UsersModel::data(const QModelIndex &index, int role) const
95 return d->entries[row].has_messages;
96 return d->entries[row].has_messages;
96 case UsersModel::ImagePathRole:
97 case UsersModel::ImagePathRole:
97 return "";
98 return "";
99+ case UsersModel::UidRole:
100+ return d->entries[row].uid;
98 default:
101 default:
99 return QVariant();
102 return QVariant();
100 }
103 }
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.h+2−1
@@ -50,7 +50,8 @@ public:
50 SessionRole,
50 SessionRole,
51 HasMessagesRole,
51 HasMessagesRole,
52 ImagePathRole,
52 ImagePathRole,
53− BackgroundPathRole
53+ BackgroundPathRole,
54+ UidRole
54 };
55 };
55
56
56 int rowCount(const QModelIndex &parent) const override;
57 int rowCount(const QModelIndex &parent) const override;
tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp+29−23
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -47,6 +47,12 @@ void UsersModelPrivate::resetEntries()
47 resetEntries_full();
47 resetEntries_full();
48 }
48 }
49
49
50+ // Assign uids in a loop, just to avoid having to muck with them when
51+ // adding or removing test users.
52+ for (int i = 0; i < entries.size(); i++) {
53+ entries[i].uid = i + 1;
54+ }
55+
50 q->endResetModel();
56 q->endResetModel();
51}
57}
52
58
@@ -54,7 +60,7 @@ void UsersModelPrivate::resetEntries_single()
54{
60{
55 entries =
61 entries =
56 {
62 {
57− { "single", "Single User", 0, 0, false, false, 0, 0 },
63+ { "single", "Single User", 0, 0, false, false, 0, 0, 0 },
58 };
64 };
59}
65}
60
66
@@ -62,7 +68,7 @@ void UsersModelPrivate::resetEntries_singlePassphrase()
62{
68{
63 entries =
69 entries =
64 {
70 {
65− { "single", "Single User", 0, 0, false, false, 0, 0 },
71+ { "single", "Single User", 0, 0, false, false, 0, 0, 0 },
66 };
72 };
67}
73}
68
74
@@ -70,7 +76,7 @@ void UsersModelPrivate::resetEntries_singlePin()
70{
76{
71 entries =
77 entries =
72 {
78 {
73− { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
79+ { "has-pin", "Has PIN", 0, 0, false, false, 0, 0, 0 },
74 };
80 };
75}
81}
76
82
@@ -78,26 +84,26 @@ void UsersModelPrivate::resetEntries_full()
78{
84{
79 entries =
85 entries =
80 {
86 {
81− { "has-password", "Has Password", 0, 0, false, false, 0, 0 },
87+ { "has-password", "Has Password", 0, 0, false, false, 0, 0, 0 },
82− { "has-pin", "Has PIN", 0, 0, false, false, 0, 0 },
88+ { "has-pin", "Has PIN", 0, 0, false, false, 0, 0, 0 },
83− { "different-prompt", "Different Prompt", 0, 0, false, false, 0, 0 },
89+ { "different-prompt", "Different Prompt", 0, 0, false, false, 0, 0, 0 },
84− { "no-password", "No Password", 0, 0, false, false, 0, 0 },
90+ { "no-password", "No Password", 0, 0, false, false, 0, 0, 0 },
85− { "auth-error", "Auth Error", 0, 0, false, false, 0, 0 },
91+ { "auth-error", "Auth Error", 0, 0, false, false, 0, 0, 0 },
86− { "two-factor", "Two Factor", 0, 0, false, false, 0, 0 },
92+ { "two-factor", "Two Factor", 0, 0, false, false, 0, 0, 0 },
87− { "info-prompt", "Info Prompt", 0, 0, false, false, 0, 0 },
93+ { "info-prompt", "Info Prompt", 0, 0, false, false, 0, 0, 0 },
88− { "html-info-prompt", "HTML Info Prompt", 0, 0, false, false, 0, 0 },
94+ { "html-info-prompt", "HTML Info Prompt", 0, 0, false, false, 0, 0, 0 },
89− { "long-info-prompt", "Long Info Prompt", 0, 0, false, false, 0, 0 },
95+ { "long-info-prompt", "Long Info Prompt", 0, 0, false, false, 0, 0, 0 },
90− { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, 0, 0 },
96+ { "wide-info-prompt", "Wide Info Prompt", 0, 0, false, false, 0, 0, 0 },
91− { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, 0, 0 },
97+ { "multi-info-prompt", "Multi Info Prompt", 0, 0, false, false, 0, 0, 0 },
92− { "long-name", "Long name (far far too long to fit)", 0, 0, false, false, 0, 0 },
98+ { "long-name", "Long name (far far too long to fit)", 0, 0, false, false, 0, 0, 0 },
93− { "color-background", "Color Background", "#dd4814", 0, false, false, 0, 0 },
99+ { "color-background", "Color Background", "#dd4814", 0, false, false, 0, 0, 0 },
94 // white and black are a bit redundant, but useful for manually testing if UI is still readable
100 // white and black are a bit redundant, but useful for manually testing if UI is still readable
95− { "white-background", "White Background", "#ffffff", 0, false, false, 0, 0 },
101+ { "white-background", "White Background", "#ffffff", 0, false, false, 0, 0, 0 },
96− { "black-background", "Black Background", "#000000", 0, false, false, 0, 0 },
102+ { "black-background", "Black Background", "#000000", 0, false, false, 0, 0, 0 },
97− { "no-background", "No Background", "", 0, false, false, 0, 0 },
103+ { "no-background", "No Background", "", 0, false, false, 0, 0, 0 },
98− { "unicode", "가나다라마", 0, 0, false, false, 0, 0 },
104+ { "unicode", "가나다라마", 0, 0, false, false, 0, 0, 0 },
99− { "no-response", "No Response", 0, 0, false, false, 0, 0 },
105+ { "no-response", "No Response", 0, 0, false, false, 0, 0, 0 },
100− { "empty-name", "", 0, 0, false, false, 0, 0 },
106+ { "empty-name", "", 0, 0, false, false, 0, 0, 0 },
101 };
107 };
102}
108}
103
109
tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.h+2−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
@@ -35,6 +35,7 @@ public:
35 bool has_messages;
35 bool has_messages;
36 QString session;
36 QString session;
37 QString infographic;
37 QString infographic;
38+ uid_t uid;
38};
39};
39
40
40class UsersModelPrivate
41class UsersModelPrivate