当笔记本电脑盖子关闭时如何禁用指纹认证?

我最近成功在我的笔记本电脑上实现了指纹认证,这要归功于Goodix Linux Development的Discord社区和GitHub用户Infinytum以及Michael Teuscher在driver/538d分支上的贡献。你可以在https://github.com/infinytum/libfprint/tree/driver/538d找到相关内容。 但是,在使用外接显示器工作并关闭笔记本盖子时,我发现了一个问题: 每当我需要输入sudo密码时,必须等待指纹认证超时,这会导致几秒钟的延迟。为此,我已经通过fprintd-enroll启用了指纹登录和通过sudo pam-auth-update启用了sudo访问权限。
username@host:~/ron/libfprint$ sudo ls
Place your finger on the fingerprint reader
Place your finger on the reader again
Place your finger on the reader again
Place your finger on the reader again
Verification timed out
[sudo] password for username:
如何在笔记本电脑盖子关闭时禁用指纹身份验证,以便在等待指纹超时之前输入 sudo 密码?
2个回答

为了在笔记本电脑盖子关闭时禁用指纹认证,并在打开时重新启用,我们将使用acpid绑定到button/lid.*事件的自定义脚本。该脚本将在盖子关闭时停止和屏蔽fprintd服务,并在盖子打开时取消屏蔽并启动fprintd服务。

我们还通过测试/sys/class/drm/card0-HDMI-A-1/status的内容来检查HDMI电缆是否连接。

请按照以下步骤操作:

  1. 创建文件/etc/acpi/laptop-lid.sh,内容如下:

    #!/bin/bash
    
    lock=$HOME/fprint-disabled
    
    if grep -Fq closed /proc/acpi/button/lid/LID0/state &&
       grep -Fxq connected /sys/class/drm/card0-HDMI-A-1/status
    then
      touch "$lock"
      systemctl stop fprintd
      systemctl mask fprintd
    elif [ -f "$lock" ]
    then
      systemctl unmask fprintd
      systemctl start fprintd
      rm "$lock"
    fi
    
    
  2. 使用以下命令使文件可执行:

    chmod +x /etc/acpi/laptop-lid.sh
    
  3. 创建文件/etc/acpi/events/laptop-lid,内容如下:

    event=button/lid.*
    action=/etc/acpi/laptop-lid.sh
    
  4. 使用以下命令重新启动acpid服务:

    sudo service acpid restart
    
现在指纹仅在盖子打开时使用。 为了在笔记本关闭时断开/重连以恢复fprintd服务的正确状态,您可以从systemd init文件中调用上述脚本。执行此操作的步骤如下:
  1. 创建一个名为/etc/systemd/system/laptop-lid.service的文件,内容如下:

    [Unit]
    Description=Laptop Lid
    After=suspend.target
    
    [Service]
    ExecStart=/etc/acpi/laptop-lid.sh
    
    [Install]
    WantedBy=multi-user.target
    WantedBy=suspend.target
    
  2. 重新加载systemd配置文件:

    sudo systemctl daemon-reload
    
  3. 启动服务:

    sudo systemctl start laptop-lid.service
    
  4. 将该服务设置为开机自启动:

    sudo systemctl enable laptop-lid.service
    
现在,即使在计算机关闭时连接/断开连接,状态应该也是正确的。 用于创建答案中的代码的参考资料: - [如何在盖子关闭时运行脚本?](link1) - [在Ubuntu 14.04中关闭盖子时笔记本电脑不会休眠](link2) - [捕捉盖子关闭和打开事件](link3)

1这是一个自问自答的问题,因为我觉得与其他可能面临相同问题的社区成员分享会很有用。但我对更好/更高效的解决方案感兴趣,所以请随时发布更多答案和/或提出对这个答案的改进建议。 - user000001
1谢谢,这正是我在寻找的。对我的(连接)XPS 13 9310来说非常好用! - Benjamin Barrois
不客气 @BenjaminBarrois,我更新了脚本并进行了一些更改,以避免一些竞态条件,并且只在HDMI连接时激活。 - user000001
当我关闭电脑盖子并打开后,遇到了一个问题。在这种情况下,Ubuntu的登录界面上不会显示任何用户,我认为这是因为fprintd服务未启动。也许在启动时应该触发一些操作来纠正这个问题? - Benjamin Barrois
@BenjaminBarrois:请查看更新的答案,我最初忘记包含那部分。 - user000001
1太棒了!这恰好是我过去在插入或拔出电源适配器时所使用的系统来更改CPU调度器。 - Benjamin Barrois
1我的机器有一个DisplayPort而不是HDMI,所以我需要使用/sys/class/drm/card0-DP-1/status。不过,这篇文章真是太棒了 - 谢谢! - Richard Vodden

在Linux中,指纹认证通过PAM实现。有一个名为pam_fprintd.so的模块与fprintd服务进行通信。当fprintd服务无法工作时,pam_fprintd无法与其通信,PAM认证会跳过配置中的下一个模块。但是另一个PAM模块也可能跳过pam_fprintd。 假设您的/etc/pam.d/system-auth文件包含以下内容:
auth            sufficient      pam_fprintd.so
auth            required        pam_unix.so

您的实际配置可能会有所不同,甚至位于不同的位置,但关键是 pam_fprintdpam_unix,它们负责密码验证。

您可以在配置中添加另一个条目,在 pam_fprintd.so 之前跳过该模块,以便在关闭笔记本电脑盖子时跳过该模块。一种方法是通过 pam_exec.so 模块来实现。创建一个可执行脚本 /usr/local/bin/pam_check_lid,内容如下:

#!/bin/sh
LID_STATE=$(cat /proc/acpi/button/lid/LID/state | cut -d':' -f2 | tr -d ' ')

case ${LID_STATE} in
    closed)
    echo closed
    exit 1
    ;;
    open*)
    echo open
    exit 0
    ;;
    *)
    # LID is open by default
    echo unknown
    exit 0
    ;;
esac

重要: 确保此文件不可全局写入。否则,您可能会在系统中引入安全漏洞。此外,您可以通过 DBus 检查 LID 状态,详细信息请查看this

然后,在pam_fprintd之前添加以下行:

auth   [success=ignore default=1]   pam_exec.so quiet /usr/local/bin/pam_check_lid
所以你的配置应该是这样的:
auth   [success=ignore default=1]  pam_exec.so quiet /usr/local/bin/pam_check_lid
auth   sufficient                  pam_fprintd.so
auth   required                    pam_unix.so
现在PAM身份验证将在尝试指纹验证之前执行您的脚本,如果您的脚本返回非零退出代码(失败),它将执行默认操作,跳过PAM配置中的1个条目(因此它会跳过pam_fprintd到下一个身份验证模块pam_unix)。当LID打开时,它将返回0退出代码,成功时不会执行任何操作,因为配置中有“ignore”关键字。 另外,您可以使用与脚本相同行为的自己制作的PAM模块,而不是使用带有脚本的pam_exec.so。 关于调试和实际实现的一些建议。如果您在使用pam_exec时遇到问题,可以添加像debug和log这样的调试选项,详细信息请参考pam_exec文档documentation。另外,建议您在新的PAM配置上测试更改,而不是修改现有的配置,因为配置文件中的错误可能会导致您无法登录到您的帐户。例如,您可以将system-auth复制为system-auth-new,并在system-auth-new上进行更改和测试,然后在测试通过后再替换原来的配置文件。对于测试,您可以使用pamtesterpamtester。例如:
cp /etc/pam.d/system-auth /etc/pam.d/system-auth-new
# UPDATE /etc/pam.d/system-auth-new
pamtester system-auth-new YOUR_USER_NAME authenticate
当它按预期工作时,用您的新配置替换system-auth

在我的笔记本电脑上,状态位于/proc/acpi/button/lid/LID0/state - rudolfbyker