需求:在用户对之间快速切换。
在系统上有一对在某种程度上等同的用户帐户。
更具体地说,对于给定的一对:
- 这两个帐户都是常规的 Unix 帐户,只是恰好由同一个物理用户(人)使用。
- 同一个人几乎总是打开两个图形 X 会话,每个用户帐户一个,但只需要在屏幕上一次看到一个。
- 这些是完全独立的帐户,具有不同的邮件配置、浏览器历史记录、文件以及不同的安全级别。
- 账户之间没有任何共享内容,在同一个 X 会话中混合使用这些账户是没有意义的(即使在这些账户之间进行复制粘贴也是没有意义的)。
- 然而用户每天需要在它们之间切换多次。
- 放置一个呼叫按钮很容易
dm-tool switch-to-user
,但实际上用户必须在每次切换时重新进行身份验证,并且那是生产力的损失。
需要允许在两个图形 X 会话之间快速切换(例如,单击面板上的按钮)无需重新认证。
系统信息和安全隐患(放宽本地安全应该没问题)
- 系统是Xubuntu 16.04 Xenial。
- X 席位、登录、锁定、切换均由 lightdm 开箱即用完成。
我知道,在保证其他操作安全的同时,放松用户对之间的安全性比通常的锁定和切换方法更复杂。幸运的是,在我们的案例中,由于机器处于受控场所,因此即使失去一些本地安全性也没关系。例如,如果解决方案导致某些通常会自动锁定会话(如暂停+恢复)的场景不再锁定,那么对于这对用户,甚至系统上的每个用户来说,这可能是可以接受的。
不过,如果用户可以手动锁定会话,那就更好了。
此外,必须保护远程安全(例如,这些帐户的 SSH 访问不能受到此问题的解决方案的影响)。
发帖前先搜索
方法 1:使用 lightdm 工具但进行一些调整
基本上,使用dm-tool switch-to-user *username*
并安排用户会话不被锁定。
在 12.04 中工作
在 Ubuntu 12.04 中,我们禁用了 light-locker 以防止会话锁定,并在每个用户的桌面上设置一个运行以下命令的图标:
dbus-send --system --type=method_call --print-reply --dest=org.freedesktop.DisplayManager $XDG_SEAT_PATH org.freedesktop.DisplayManager.Seat.SwitchToUser string:$CALLEDUSERNAME string:somesessionname
这有效:会话切换到提到的用户$CALLEDUSERNAME
。
在 16.04 中失败
这在 16.04 上是不令人满意的:它切换到带有预选的欢迎程序$CALLEDUSERNAME
,但仍需要身份验证。因此,结果基本上与相同dm-tool switch-to-user *username*
。我还没有完全检查,但可能只是走的是与导致原因完全相同的代码路径dm-tool
。
更多搜索
寻找提示错误 #1205384 “可以通过切换到控制台来绕过锁定”:错误:lxsession 包:Ubuntu,没有任何具体工作。
我查看了dm-tool
源代码http://archive.ubuntu.com/ubuntu/pool/main/l/lightdm/lightdm_1.18.1-0ubuntu1.tar.gz(来自链接Ubuntu – 在 xenial 中的 lightdm 软件包详细信息)。
原理如下:
dm-tool
可执行文件调用 dbus 发送消息至lightdm
。lightdm
接收 dbus 事件handle_seat_call()
,调用seat_switch_to_user()
seat_switch_to_user()
调用g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat);
注册回调switch_authentication_complete_cb()
。seat_switch_to_user()
然后调用session_start()
,显然会创建一个全新的 X 会话来获取身份验证(不确定细节,也许运行session_child_run()
调用 PAM 的程序)switch_authentication_complete_cb()
然后切换到现有会话或创建新会话
下一步
我们能否以某种方式指示 PAM 在这种情况下不提示就直接允许,但这种更改不会干扰任何其他情况?理想情况下,PAM 行为只会在切换用户的情况下发生变化,而不会在登录或解锁的情况下发生变化。也许额外的 X 会话仍会启动,但不会等待用户输入密码。
方法 2:只需找出 VT 编号并使用 chvt
- 随时获取目标用户所对应的 VT(可能是因为在登录时,脚本会读取 XDG_SEAT_PATH 来获取座位号,然后与
Xorg
命令行连接,告知相应的 vt 号,并将结果写入常规位置)。 当需要切换到用户时,获取 vt 编号并使用
chvt
。可能需要一些 sudo 配置。lightdm
优点:更简单,不会与PAM 等混淆,甚至没有明确的依赖lightdm
,因此可以在其他地方工作。- 缺点:用不太正规的方式找出用户和 VT 号码之间的连接?
结论,复述问题
- 对第一种方法(通过
dm-tool
PAM 调整)有什么评论吗? - 对第二种方法(通过
chvt
)有什么评论吗?
感谢您的关注。
答案1
总结:完成,可用,当前解决方案仅在协作的多用户环境中可接受,并且可以改进。
我编写了一个可用的概念验证补丁来lightdm
完成这项工作。
它满足了我们的需求!
请参阅下面的安装说明。
先决条件
- 一个至少拥有两个用户帐户的系统,并且用户愿意允许在图形会话之间快速切换而无需重新输入密码。
- 每个用户都可以使用任何充分利用的桌面环境
lightdm
,包括使用light-locker
进行会话锁定。Unity 和 XFCE 应该可以工作。
使用 XFCE 测试。
如何使用、如何查看更改
在进行更改之前尝试以下操作:
- 让用户 A 打开图形会话
- 让用户 B 打开另一个图形会话
现在您可以从两个会话中的任何一个会话中执行以下操作:
dm-tool switch-to-user userA
或者
dm-tool switch-to-user userB
变更的影响
如果没有更改,您将看到要求输入密码的登录提示。
更改后,您将看到无需登录提示即可立即切换。
这里的切换非常快。比 Ubuntu 12.04 快得多,甚至在某些情况下没有闪烁。
实际用途
为了获得最大的利益,我建议在 dock/panel/wharf(无论它在特定的桌面环境中叫什么)的某个地方创建一个启动器图标,当点击它时运行:
dm-tool switch-to-user name-of-other-user
安全警告
应用以下命令将系统的lightdm
软件包替换为修改后的版本,允许在当前登录图形会话的任何两个用户之间切换。这会削弱系统安全性,例如用户 A 以图形方式登录,锁定会话,离开,用户 B 登录。用户 B 可以解锁用户 A 会话并在打开时随时切换到它。反之亦然(交换 A 和 B)。
sudo
如果没有管理员权限(尤其是对于包安装),则无法应用更改。
对我们来说很好,但请注意,这lightdm
是一个重要的软件包,这可能会破坏它或引入其他细微错误。破坏它将破坏所有用户使用图形登录会话的能力。您对以下命令的使用负全部责任。您已收到警告。
永久警告
更改几乎是永久性的。它们在重启后仍然存在。要恢复它们,请安装(使用aptitude
或任何其他方式)将替换已更改的软件包的synaptic
常规软件包。lightdm*
请注意,Ubuntu 每次更新lightdm
软件包并安装更新时,都会恢复更改。管理员可以再次应用它们。
可能的改进(恢复安全)
可以通过巧妙使用 Unix 组等来完善此概念验证。 lightdm
仅当当前用户和目标用户列在任何具有常规文件名的组中时才允许切换,例如lightdm-quickswitch-anystringfoo
。这样的更改(可能与其他更改一起)最终可以合并到某些官方解决方案中。
命令
我建议登录文本控制台(按 Ctrl-Alt-F1 并登录)执行以下步骤。这样可以重新启动 lightdm 而不会丢失当前 shell。
在 bash shell 中复制粘贴下面的命令,它将进行调整lightdm
以执行更改。
(
set -euxv
echo Making sure system has necessary packages.
echo Installing packages will be done only once but might be long as it may fetch around 40Mbytes of data from the Internet.
sudo apt-get --assume-yes install devscripts
echo Enabling source packages in apt.
sudo sed -i '/^#\sdeb-src /s/^# *//' "/etc/apt/sources.list"
sudo apt-get update
sudo apt-get --assume-yes --no-install-recommends build-dep lightdm
THETEMPDIR=$( mktemp -d )
cd $THETEMPDIR
echo Getting package source
apt-get source lightdm
cd */
pwd
if [ -d .pc ]
then
quilt push -a || echo "Quilt returned an error code, we ignore it because we saw it was sometimes irrelevant."
quilt new allow_switch_between_logged_users_without_authentication
quilt add src/seat.c
fi
patch -p0 <<EOF
--- src/seat.c 2016-07-29 05:19:45.000000000 +0200
+++ src/seat.c 2016-08-15 19:37:11.693364683 +0200
@@ -1578,6 +1578,20 @@
l_debug (seat, "Switching to user %s", username);
+ if (session)
+ {
+ l_debug (seat, "WIP quick switch: found inactive existing user session, switching to it: %s. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+
+ session_unlock (session);
+ seat_set_active_session (seat, session);
+
+ l_debug (seat, "WIP quick switch to user complete: %s. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+ return TRUE;
+ }
+
+ l_debug (seat, "WIP quick switch: no session for user, switching to greeter: %s. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+
+
/* Attempt to authenticate them */
session = create_user_session (seat, username, FALSE);
g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat);
EOF
if [ -d .pc ]
then
quilt refresh
ls -al debian/patches/allow_switch_between_logged_users_without_authentication
cat debian/patches/allow_switch_between_logged_users_without_authentication
fi
echo Building modified packages.
dch -lquickswitch "Allow dm-tool switch-to-user username to switch without authentication if user session is already opened. WARNING: this negates local security. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating"
head debian/changelog
time dpkg-buildpackage -rfakeroot -uc -b
echo Installing modified packages.
cd ..
PACKAGESTOINSTALL=$( for DEBNAME in *.deb ; do PACKAGENAME="$( echo "$DEBNAME" | cut -f 1 -d _ )" ; if dpkg -l $PACKAGENAME | grep -q ^ii ; then echo $DEBNAME ; fi ; done ) ; sudo dpkg --install ${PACKAGESTOINSTALL}
dpkg -l '*lightdm*'
)
请注意,以下命令将立即关闭所有图形会话而没有机会保存数据,因此所有用户都应首先正确关闭应用程序并保存所需的数据。
如果软件包安装成功,则可以使用以下命令立即激活更改:
sudo service lightdm restart
或重新启动。
反馈
它对你有用吗?你能想到一个变体吗?欢迎反馈。