接前一篇文章:PAM从入门到精通(十八)
本文参考:
《The Linux-PAM Application Developers' Guide》
PAM 的应用开发和内部实现源码分析
先再来重温一下PAM系统架构:
更加形象的形式:
六、整体流程示例
2. 更为完整的例程及解析
上一回讲解了更为详细复杂例程的第二部分,本文继续讲解其余部分。再来贴一下完整代码:
/* 使用PAM所必需的两个头文件*/
#include <security/pam_appl.h>
#include <security/pam_misc.h>
static struct pam_conv conv = {
misc_conv,
NULL
}
void main(int argc, char *argv[], char **renvp)
{
pam_handle_t *pamh = NULL;
int status;
/* 初始化,并提供一个回调函数 */
if ((pam_start("login", user_name, &conv, &pamh)) != PAM_SUCCESS)
exit(1);
/* 设置一些关于认证用户信息的参数 */
pam_set_item(pamh, PAM_TTY, ttyn);
pam_set_item(pamh, PAM_RHOST, remote_host);
while (!authenticated && retry < MAX_RETRIES)
{
status = pam_authenticate(pamh, 0);/* 认证,检查用户输入的密码是否正确 */
}
/* 认证失败则应用程序退出*/
if (status != PAM_SUCCESS)
{
……
exit(1);
}
/* 通过了密码认证之后再调用帐号管理API,检查用户帐号是否已经过期 */
if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS)
{
if (status == PAM_AUTHTOK_EXPIRED)
{
status = pam_chauthtok(pamh, 0); /* 过期则要求用户更改密码 */
if (status != PAM_SUCCESS)
exit(1);
}
}
/* 通过帐户管理检查之后则打开会话 */
if (status = pam_open_session(pamh, 0) != PAM_SUCCESS)
exit(status);
……
/* 建立认证服务的用户证书*/
status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
if (status != PAM_SUCCESS)
exit(status);
……
pam_end(pamh, PAM_SUCCESS); /* PAM事务的结束 */
……
}
(6)pam_open_session函数
代码片段:
/* 通过帐户管理检查之后则打开会话 */
if (status = pam_open_session(pamh, 0) != PAM_SUCCESS)
exit(status);
作用:
启动PAM会话管理。pam_open_session函数为先前成功通过身份验证的用户设置用户会话。会话稍后应通过调用pam_close_session()来终止。
应该注意的是,应用程序的有效uid(通过geteuid()获得)应该具有足够的权限来执行例如创建或挂载用户主目录之类的任务。
参数详解:
- pam_handle_t *pamh
pamh参数是通过先前调用pam_start()获得的身份验证句柄。
此处传给pamh的实参为main函数中定义的pam_handle_t *pamh的地址&pamh。
- int flags
flags参数是以下值中的零个或多个的二进制或:
PAM_SILENT
不发出任何消息。
此处传给flags的实参为0。
(7)pam_setcred函数
代码片段:
/* 建立认证服务的用户证书*/
status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
if (status != PAM_SUCCESS)
exit(status);
作用:
设置用户凭证。pam_setcred函数用于建立、维护和删除用户的资格(凭据)。在对用户进行身份验证之后,在为用户打开会话之前(使用pam_open_session()),应该调用它来设置凭据。应在会话关闭后删除凭据(使用pam_close_session())。
凭据(credential)是用户所拥有的东西。它是一些属性,如Kerberos票证或者构成给定用户的唯一性的补附加组成员资格。在Linux系统上,用户的UID和GID也是凭据。但是,已经决定这些属性(以及用户所属的默认补充组)是应由应用程序而不是PAM直接设置的凭据。应用程序应在调用此函数之前建立此类凭据。例如,initgroups()(或等效操作)应该(已)被执行。
参数详解:
- pam_handle_t *pamh
pamh参数是通过先前调用pam_start()获得的身份验证句柄。
此处传给pamh的实参为main函数中定义的pam_handle_t *pamh的地址&pamh。
- int flags
有效标志,其中任何一个可以与PAM_SILENT进行逻辑“或”运算,它们是:
PAM_ESTABLISH_CRED
初始化用户的凭据。
PAM_DELETE_CRED
删除用户的凭据。
PAM_REINITIALIZE_CRED
完全重新初始化用户凭据。
PAM_REFRESH_CRED
延长现有凭据的生命期(使用期限)。
此处传给flags的实参为PAM_ESTABLISH_CRED。
至此,代码流程中的所有函数就全部解析完了。