on xenial help sign in
Don't lock the screen for guest users or users in the nopasswdlogin group. (LP: #1644237)

Approved by: Josh Arenson, Unity8 CI Bot

commitd39f93f1558405da08d903578c4656f1a80e975f authorMichael Terry <mike@mterry.name> dateTue 21 Mar 2017, 10:51 (10 years ago) parentc739de1e95f44c
7 files changed+129−19
cmake/modules/QmlTest.cmake+1−1 plugins/Unity/Session/dbusunitysessionservice.cpp+29−3 qml/Components/Dialogs.qml+5−5 qml/Shell.qml+3−1 tests/plugins/Unity/Session/CMakeLists.txt+13−1 tests/plugins/Unity/Session/preload.c+43 tests/plugins/Unity/Session/sessionbackendtest.cpp+35−8
cmake/modules/QmlTest.cmake+1−1
@@ -201,7 +201,7 @@ function(add_executable_test COMPONENT_NAME TARGET)
201201 add_qmltest_target(xvfbtest${COMPONENT_NAME} ${TARGET}
202202 COMMAND $<TARGET_FILE:xvfb-run> --server-args "-screen 0 1024x768x24" --auto-servernum ${qmltest_command}
203203 ${depends}
204− ENVIRONMENT QML2_IMPORT_PATH=${imports} ${QMLTEST_ENVIRONMENT} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1
204+ ENVIRONMENT QML2_IMPORT_PATH=${imports} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1 ${QMLTEST_ENVIRONMENT}
205205 TARGETS ${xvfb_targets}
206206 )
207207 endif()
plugins/Unity/Session/dbusunitysessionservice.cpp+29−3
@@ -18,6 +18,7 @@
1818#include "dbusunitysessionservice.h"
1919
2020// system
21+#include <grp.h>
2122#include <sys/types.h>
2223#include <unistd.h>
2324#include <pwd.h>
@@ -211,6 +212,23 @@ public:
211212 QDBusConnection::SM_BUSNAME().asyncCall(msg);
212213 }
213214
215+ bool isUserInGroup(const QString &user, const QString &groupName) const
216+ {
217+ auto group = getgrnam(groupName.toUtf8().data());
218+
219+ if (group && group->gr_mem)
220+ {
221+ for (int i = 0; group->gr_mem[i]; ++i)
222+ {
223+ if (g_strcmp0(group->gr_mem[i], user.toUtf8().data()) == 0) {
224+ return true;
225+ }
226+ }
227+ }
228+
229+ return false;
230+ }
231+
214232private Q_SLOTS:
215233 void onPropertiesChanged(const QString &iface, const QVariantMap &changedProps, const QStringList &invalidatedProps)
216234 {
@@ -297,7 +315,13 @@ bool DBusUnitySessionService::CanShutdown() const
297315
298316bool DBusUnitySessionService::CanLock() const
299317{
300− return true; // FIXME
318+ auto user = UserName();
319+ if (user.startsWith(QStringLiteral("guest-")) ||
320+ d->isUserInGroup(user, QStringLiteral("nopasswdlogin"))) {
321+ return false;
322+ } else {
323+ return true;
324+ }
301325}
302326
303327QString DBusUnitySessionService::UserName() const
@@ -335,8 +359,10 @@ void DBusUnitySessionService::PromptLock()
335359 // Prompt as in quick. No locking animation needed. Usually used by
336360 // indicator-session in combination with a switch to greeter or other
337361 // user session.
338− Q_EMIT LockRequested();
339− Q_EMIT lockRequested();
362+ if (CanLock()) {
363+ Q_EMIT LockRequested();
364+ Q_EMIT lockRequested();
365+ }
340366}
341367
342368void DBusUnitySessionService::Lock()
qml/Components/Dialogs.qml+5−5
@@ -22,7 +22,6 @@ import GlobalShortcut 1.0
2222import Ubuntu.Components 1.3
2323import Unity.Platform 1.0
2424import Utils 0.1
25−import "../Greeter"
2625
2726MouseArea {
2827 id: root
@@ -116,17 +115,17 @@ MouseArea {
116115
117116 GlobalShortcut { // lock screen
118117 shortcut: Qt.Key_ScreenSaver
119− onTriggered: LightDMService.greeter.showGreeter()
118+ onTriggered: root.unitySessionService.PromptLock()
120119 }
121120
122121 GlobalShortcut { // lock screen
123122 shortcut: Qt.ControlModifier|Qt.AltModifier|Qt.Key_L
124− onTriggered: LightDMService.greeter.showGreeter()
123+ onTriggered: root.unitySessionService.PromptLock()
125124 }
126125
127126 GlobalShortcut { // lock screen
128127 shortcut: Qt.MetaModifier|Qt.Key_L
129− onTriggered: LightDMService.greeter.showGreeter()
128+ onTriggered: root.unitySessionService.PromptLock()
130129 }
131130
132131 QtObject {
@@ -179,8 +178,9 @@ MouseArea {
179178 Button {
180179 width: parent.width
181180 text: i18n.ctr("Button: Lock the system", "Lock")
181+ visible: root.unitySessionService.CanLock()
182182 onClicked: {
183− LightDMService.greeter.showGreeter()
183+ root.unitySessionService.PromptLock();
184184 logoutDialog.hide();
185185 }
186186 Component.onCompleted: if (root.hasKeyboard) forceActiveFocus(Qt.TabFocusReason)
qml/Shell.qml+3−1
@@ -426,7 +426,9 @@ StyledItem {
426426 id: showGreeterDelayed
427427 interval: 1
428428 onTriggered: {
429− greeter.forceShow();
429+ // Go through the dbus service, because it has checks for whether
430+ // we are even allowed to lock or not.
431+ DBusUnitySessionService.PromptLock();
430432 }
431433 }
432434
tests/plugins/Unity/Session/CMakeLists.txt+13−1
@@ -33,6 +33,17 @@ install(TARGETS LightDMServer
3333 DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/plugins/Unity/Session"
3434 )
3535
36+### Preload
37+add_library(SessionBackendTestPreload SHARED
38+ preload.c
39+)
40+target_link_libraries(SessionBackendTestPreload
41+ ${GLIB_LIBRARIES}
42+ )
43+install(TARGETS SessionBackendTestPreload
44+ DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/plugins/Unity/Session"
45+ )
46+
3647### SessionBackendTest
3748add_executable(sessionbackendtestExec
3849 sessionbackendtest.cpp
@@ -48,7 +59,8 @@ install(TARGETS sessionbackendtestExec
4859)
4960
5061add_unity8_unittest(SessionBackend dbus-test-runner
51− ENVIRONMENT XDG_SESSION_PATH=/session
62+ ENVIRONMENT LD_PRELOAD=$<TARGET_FILE:SessionBackendTestPreload>
63+ XDG_SESSION_PATH=/session
5264 ARG_PREFIX "--parameter"
5365 ARGS
5466 --task $<TARGET_FILE:LightDMServer>
tests/plugins/Unity/Session/preload.cnew file+43
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright © 2017 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License version 3 as
6+ * published by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#include <glib.h>
19+#include <grp.h>
20+#include <stdlib.h>
21+
22+const gchar *g_get_user_name(void)
23+{
24+ // The normal glib version parses pwent entries
25+ return g_getenv("TEST_USER");
26+}
27+
28+struct group *getgrnam(const char *group_name)
29+{
30+ static struct group rv = {NULL, NULL, 0, NULL};
31+
32+ g_free(rv.gr_name);
33+ g_strfreev(rv.gr_mem);
34+
35+ rv.gr_name = g_strdup(group_name);
36+ rv.gr_passwd = NULL;
37+ rv.gr_gid = 9999;
38+ rv.gr_mem = NULL;
39+ if (g_strcmp0(group_name, "nopasswdlogin") == 0) {
40+ rv.gr_mem = g_strsplit(g_getenv("TEST_NOPASSWD_USERS"), ",", 0);
41+ }
42+ return &rv;
43+}
tests/plugins/Unity/Session/sessionbackendtest.cpp+35−8
@@ -53,6 +53,11 @@ private Q_SLOTS:
5353 QDBusConnection::sessionBus());
5454 }
5555
56+ void init() {
57+ qputenv("TEST_USER", "testuser");
58+ qputenv("TEST_NOPASSWD_USERS", "");
59+ }
60+
5661 void testUnitySessionLogoutRequested_data() {
5762 QTest::addColumn<QString>("method");
5863 QTest::addColumn<QString>("signal");
@@ -230,14 +235,7 @@ private Q_SLOTS:
230235
231236 void testUserName() {
232237 DBusUnitySessionService dbusUnitySessionService;
233− QCoreApplication::processEvents(); // to let the service register on DBus
234−
235− QProcess * proc = new QProcess(this);
236− proc->start("id -un", QProcess::ReadOnly);
237− proc->waitForFinished();
238− const QByteArray out = proc->readAll().trimmed();
239−
240− QCOMPARE(dbusUnitySessionService.UserName(), QString::fromUtf8(out));
238+ QCOMPARE(dbusUnitySessionService.UserName(), QString("testuser"));
241239 }
242240
243241 void testRealName() {
@@ -254,6 +252,35 @@ private Q_SLOTS:
254252 }
255253 }
256254
255+ void testCanLock() {
256+ DBusUnitySessionService dbusUnitySessionService;
257+
258+ qputenv("TEST_USER", "testuser");
259+ QVERIFY(dbusUnitySessionService.CanLock());
260+
261+ qputenv("TEST_USER", "guest-abcdef"); // guest-* can't lock
262+ QVERIFY(!dbusUnitySessionService.CanLock());
263+
264+ qputenv("TEST_USER", "testuser");
265+ qputenv("TEST_NOPASSWD_USERS", "testuser"); // nopasswdlogin can't lock
266+ QVERIFY(!dbusUnitySessionService.CanLock());
267+ }
268+
269+ void testPromptLockRespectsCanLock() {
270+ DBusUnitySessionService dbusUnitySessionService;
271+
272+ QSignalSpy spy(&dbusUnitySessionService, SIGNAL(lockRequested()));
273+ QVERIFY(dbusUnitySessionService.CanLock());
274+ dbusUnitySessionService.PromptLock();
275+ QCOMPARE(spy.count(), 1);
276+
277+ spy.clear();
278+ qputenv("TEST_USER", "guest-abcdef");
279+ QVERIFY(!dbusUnitySessionService.CanLock());
280+ dbusUnitySessionService.PromptLock();
281+ QCOMPARE(spy.count(), 0);
282+ }
283+
257284private:
258285 QDBusInterface *dbusUnitySession;
259286};