Linux的鉴别(Authentication)机制--PAM
Linux的鉴别(Authentication)机制--PAM
转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd
作者联系方式:李先静<xianjimli at hotmail dot com>
更新时间:2007-4-23
随着智能手机的日益普及,手机中储存的隐私信息越来越多,而手机的丢失率又居高不下,所以手机的安全性就显得更加重要了。为了保障数据的安全性,我们手机中的很多功能都需要鉴别(Authentication)之后才能使用。为了遵循标准的做法,不想自己搞一套鉴别(Authentication)机制,我花了一些时间去研究Linux-PAM。
有人说鉴别(Authentication)不就是对用户名和密码进行验证,以确认使用者的身份吗?没错,最简单的情况就是如此。但是,让用于单机的Login方法去代替于网络环境的 Kerberos方法,用户一定会觉得有很多不便。除此之外,事情也不那简单,比如对用户有效期的检查、对使用者的时间限制、对用户组的限制和对本地用户和远程用户的区分等等,处理方法都是不同的。由此可见,不同的场境需要不同的鉴别(Authentication)方法,或者需要多种鉴别(Authentication)方法的组合。
实际上,不仅有多种不同的鉴别(Authentication)方法存在,而且即使同一种方法也可能多种不同的表现形式。比如,同是普通用户名和密码验证方法,在Client/Server下,在Console下和在GUI下,它们的表现形式也不一样,这也是需要特别注意的。
不同的鉴别(Authentication)方法有自己的适用范围,把这些鉴别(Authentication)方法独立出来,供不同的应用程序使用,可以大大提高代码的复用率。而同一个应用程序,在不同环境,甚至在不同的时期,也可能会选择不同的鉴别(Authentication)方法。所以让鉴别(Authentication)方法的使用者和实现者分离开来,让它们各自独立发展,互不影响,显然是有利于软件维护的。这正是PAM(Pluggable Authentication Modules)的动机所在。
顾名思义,PAM就是基于插件式设计的一套鉴别(Authentication)方法框架和相应的模块实现代码。我们可以从以下几个方面来看PAM:
1. PAM的使用者。
任何需要鉴别(Authentication)功能的软件都是可以是PAM的使用者。它调用PAM提供的统一的接口函数,去确认用户的身份,保证相关功能不会被非法使用。PAM的使用者只关心鉴别(Authentication)的结果,以决定让不让用户使用这个功能,而不关心鉴别(Authentication)方法。
PAM的使用者不关心鉴别(Authentication)方法,并不意味着所有PAM的使用者都不毫无区别,su的鉴别(Authentication)方法和FTP的鉴别(Authentication)方法肯定有所不同。如何区分它们呢,那就是靠配置文件,用不同的配置文件区分它们。
有时候,鉴别(Authentication)方法的实现模块需要向用户显示一些信息,比如鉴别(Authentication)失败,或者要求用户输入一些信息,比如用户名和密码。这都是与用户界面相关的,要根据PAM的使用者的要求,以不种的风格出现(Console或者GUI)。这可以在pam_start函数的pam_conv结构中传入一个回调函数,它由PAM使用者实现,由PAM的实现模块调用(有的提示语可以通过pam_set_item函数设置)。
2. 系统管理员。
PAM的使用者需要指定一个配置文件,这只是为了与其它PAM的使用者区分开来,PAM的使用者并不关心配置文件的内容。配置文件的内容是系统管理员根据安全策略来决定的,比如,来自本机的root用户可以不输入密码,来自局域网内部的用户可以访问,而来自外网的用户禁止访问,或者全部使用用户名/密码方法鉴别,或者使用Kerberos方法鉴别。总之,这都是配置文件决定的。
系统管理员只修改配置文件,就可以使用不同的鉴别(Authentication)方法,而不需要修改源代码,不需要重新编译,这大大提高了鉴别(Authentication)的灵活性。
配置文件可以放在/etc/pam.d目录下,或者/etc/pam.conf文件中,下面是gdm的配置文件:
#%PAM-1.0 auth required pam_env.so auth include system-auth account required pam_nologin.so account include system-auth password include system-auth session optional pam_keyinit.so force revoke session include system-auth session required pam_loginuid.so session optional pam_console.so |
如果没有指定配置文件,那么PAM就会用缺省的配置文件other,other的配置通常是禁止一切访问。
3. PAM框架。
PAM框架采用了插件式设计和职责链模式。每种鉴别(Authentication)方法都是一个插件,要实现指定的插件接口函数。基于职责链模式,PAM框架可以把多种鉴别(Authentication)方法组合起来,以实现功能更强大的鉴别(Authentication)方法。
在配置文件中,用required、requisite、optional和sufficient等几个关键来决定职责链的执行/停止规则。
框架的实现代码在libpam目录里,pam_start函数里会读取配置文件,根据配置文件中描述的规则加载并组合插件,而pam_authenticate等函数则会调用_pam_dispatch去驱动职责链的执行。
4. PAM鉴别(Authentication)方法的实现者。
每种PAM鉴别(Authentication)方法都是PAM框架的一个插件,PAM内置的鉴别(Authentication)插件可以静态编译到框架中去,也编译成共享库,由框架动态加载。插件要求实现下列接口(静态编译):
struct pam_module { const char *name; /* Name of the module */ /* These are function pointers to the module's key functions. */ int (*pam_sm_authenticate)(pam_handle_t *pamh, int flags, int argc, const char **argv); int (*pam_sm_setcred)(pam_handle_t *pamh, int flags, int argc, const char **argv); int (*pam_sm_acct_mgmt)(pam_handle_t *pamh, int flags, int argc, const char **argv); int (*pam_sm_open_session)(pam_handle_t *pamh, int flags, int argc, const char **argv); int (*pam_sm_close_session)(pam_handle_t *pamh, int flags, int argc, const char **argv); int (*pam_sm_chauthtok)(pam_handle_t *pamh, int flags, int argc, const char **argv); }; |
这些函数基本上和PAM的API一一对应,插件并不要求实现以上全部函数,可以根据需要有选择的实现。插件之间可以用pam_putenv/pam_getenv通信,实现数据共享。
参考资料:
http://www.kernel.org/pub/linux/libs/pam/
http://www.ibm.com/developerworks/cn/linux/l-pam/index.html
~~end~~