LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1425|回复: 2

Linux下的第三方登录认证实现

[复制链接]
发表于 2011-6-30 11:57:43 | 显示全部楼层 |阅读模式
Linux下的第三方登录认证实现

Eric Yang<kkndyu@gmail.com>

本文的动机来自于一个项目,即:实现linux下的刷卡登录系统。因为使用ubuntu的缘故,接到项目时的第一感觉就是改写GDM。在GDM代码差不多看完以后,发现GDM认证采用了PAM机制。这种将认证交由第三方模块实现的做法,使开发者只要实现自己的认证模块,无需更改GDM本身的代码,大大降低了系统耦合。相比较于Windows xp的Gina以及vista下的provider,第三方认证机制虽然简洁优雅,但是文档方面还有所欠缺。故现将Linux PAM、GDM等相关资料整理出来,以便来者。

本文的测试开发环境:ubuntu9.04,虚拟机 virtualbox 3.2,GDM版本2.20.7,PAM版本1.0.1。将分别介绍GDM,PAM,然后简要说明gtk+以及linux下的串口读写。

1、GDM

GDM全称Gnome Display Manage,即Gnome显示管理器。狭义的理解可以把它看作一个登录管理器,但是gdm做的远比登录验证要多,如:gdm启动Xserver,管理基于XDMCP的远程连接,允许用户重启、关机等。
GDM有一个主进程。主守护进程异步运行,不会挂起。守护进程会启动很多slave进程,每一个slave进程代表一个Xserver,以及其中涉及的会话,slave进程可以挂起。我们看到的登录对话界面是一个greeter程序,由salve进程fork出来。主进程是root权限,slave进程是gdm用户权限,由slave进程fork出来的登录界面进程只能与slave进程通信,转发slave进程的问题给user,将user的回答给slave,这个设计可以保证安全性。即使用户利用gtk+的漏洞取得了一个shell,所能造成的破坏仅限于gdm本身。

下面简要分析一下gdm的启动流程,关于配置文件的分析等,可以参考gdm的官方文档,GNOME Display Manager Reference Manual。(http://library.gnome.org/admin/gdm/stable/security.html.en)

3.2节这段话直接说明了如何实现gdm下的第三方认证,动手前官方文档还是要认真看一遍。
If you wish to make GDM work with other types of authentication mechanisms (such as a fingerprint or SmartCard reader), then you should implement this by using a PAM service module for the desired authentication type rather than by trying to modify the GDM code directly. Refer to the PAM documentation on your system.

(如果你想让GDM配合其他类型的认证机制,如:指纹、智能卡等,你可以通过编写pam的service模块的方式,而不是试图直接修改GDM源码)

与用户认证有关的的代码启动顺序如下:
gdm.c       main()->gdm_start_first_unborn_local()->
display.c   gboolean gdm_display_manage (GdmDisplay *d)->void gdm_slave_start (GdmDisplay *d)->
slave.c     gdm_slave_run (GdmDisplay *display)->gdm_slave_greeter ()

上述是gdm的调用关系,gdm_slave_greeter ()最终fork出了greeter程序,即前台我们看到的登录对话界面。gdm_slave_run (GdmDisplay *display)在fork完greeter后,调用gdm_slave_wait_for_login ()函数,这个函数中初始化pam库,调用

verify-pam.c中  gdm_verify_user ()实现用户验证;主要包括:与前台greeter交互,取得用户名和密码,调用pam验证函数,验证是否能够登录。与前台交互采用管道,将标准输入输出绑定到管道上,注意所有的通信发起者都是slave进程,greeter只负责应答。

gdm_verify_user ()中pam相关的部分,遵循的是pam的规则,首先初始化pam库,指定pam对话函数gdm_verify_pam_conv()。在调用pam的验证函数pam_authenticate()时,pam将会使用此对话函数与前台greeter程序交互。也就是说使用pam,需要给pam提供一个与前台交互的函数。作为通用库的pam并不需要知道前台代码的逻辑,当pam验证用户的时候发现信息不足,就会调用交互函数。交互函数将用户输入存入约定的变量,pam取得后验证,返回认证的结果:通过或者不通过。

2、PAM

pam是由sun,对不起,现在应该叫oracle了,首先在solaris中实现的。

系统管理员通过PAM配置文件来制定认证策略,即指定什么服务该采用什么样的认证方法;应用程序开发者通过在服务程序中使用PAM API而实现对认证方法的调用;而PAM服务模块(service module)的开发者则利用PAM SPI(Service Module API)来编写认证模块(主 要是 引出一些函数pam_sm_xxxx( )供libpam调用),将不同的认证机制(比如传统的UNIX认证方 法、Kerberos等)加入到系统中;PAM核 心库(libpam)则读取配置文件,以此为根据将服务程序和相应的认证方法联系起来。

这个机制很好,很符合逻辑,很好的满足了第三方认证的需求:程序调用标准api,需要什么验证,由配置文件决定;怎么认证,则由第三方的认证提供者决定,比如指纹认证,编写一个符合规范的pam***.so即可。

Pam服务端的开发方法可以参照这个文档:
http://download.oracle.com/docs/ ... h3pam-01/index.html

转眼间,sun就变成了oracle,唉 。。。

3、gtk+和串口读写以及部署

auth需要实现两个函数

  1. pam_sm_authenticate(pam_handle_t *pamh, int flags,
  2.                                    int argc, const char **argv)

  3. pam_sm_setcred(pam_handle_t *pamh, int flags,
  4.                               int argc, const char **argv)
复制代码


pam_sm_authenticate中实现,在gdm用户名密码验证之前,跳一个窗口,提示刷卡;后台一个进程读串口,检测到刷卡事件给给前台窗口发信息,验证。pam_sm_setcred直接返回PAM_SUCCESS即可。

编译出来的pam_rfid.so拷贝到 /lib/security下

在gdm的pam配置文件中加一行即可:(/etc/pam.d/gdm)

  1. auth    requisite       pam_rfid.so
复制代码

4、enjoy

2011.06.30
发表于 2011-7-3 20:14:49 | 显示全部楼层
请问,楼主原创?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-7-4 13:07:20 | 显示全部楼层
Post by realtang;2143878
请问,楼主原创?



yep 。。。 算是把网上找到的资料整到一起  顺带加点感慨 。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表