接前一篇文章: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事务的结束 */
……
}
(3)pam_authenticate函数
代码片段:
while (!authenticated && retry < MAX_RETRIES)
{
status = pam_authenticate(pamh, 0);/* 认证,检查用户输入的密码是否正确 */
}
/* 认证失败则应用程序退出*/
if (status != PAM_SUCCESS)
{
……
exit(1);
}
作用:
对用户进行身份验证。pam_authenticate函数用于对用户进行身份验证。用户被要求提供一个基于身份验证服务的身份验证令牌,通常这是一个密码,但也可能是指纹。
PAM服务模块可以请求用户通过对话机制输入其用户名(参见pam_start()和pam_conv)。经过身份验证的用户名称将出现在PAM的PAM_USER项中。可以通过调用pam_get_item()来恢复此项目。
参数详解:
- pam_handle_t *pamh
pamh参数是通过先前调用pam_start()获得的身份验证句柄。
此处传给pamh的实参为main函数中定义的pam_handle_t *pamh的地址&pamh。
- int flags
flags参数是以下值中的零或更多的二进制或:
PAM_SILENT
不发出任何消息。
PAM_DISALLOW_NULL_AUTHTOK
如果用户的身份验证令牌为空,PAM模块服务应返回PAM_NEW_AUTHTOK_REQD。
此处传给flags的实参为0。
(4)pam_acct_mgmt函数
代码片段:
/* 通过了密码认证之后再调用帐号管理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);
}
}
作用:
账户验证管理。pam_acct_mgmt函数用于确定用户的帐户是否有效。它检查身份验证令牌和帐户过期与否,并验证访问限制。其通常在用户经过身份验证后调用。
参数说详解:
- pam_handle_t *pamh
pamh参数是通过先前调用pam_start()获得的身份验证句柄。
此处传给pamh的实参为main函数中定义的pam_handle_t *pamh的地址&pamh。
- int flags
flags参数是以下值中的零或更多的二进制或:
PAM_SILENT
不发出任何消息。
PAM_DISALLOW_NULL_AUTHTOK
如果用户的身份验证令牌为空,PAM模块服务应返回PAM_NEW_AUTHTOK_REQD。
此处传给flags的实参为0。
(5)pam_chauthtok函数
代码片段:
/* 通过了密码认证之后再调用帐号管理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);
}
}
作用:
更新身份验证令牌。pam_chauthtok函数用于更改给定用户的身份验证令牌。
参数详解:
- pam_handle_t *pamh
pamh参数是通过先前调用pam_start()获得的身份验证句柄。
此处传给pamh的实参为main函数中定义的pam_handle_t *pamh的地址&pamh。
- int flags
flags参数是以下值中的零或更多的二进制或:
PAM_SILENT
不发出任何消息。
PAM_CHANGE_EXPIRED_AUTHTOK
此参数向模块指示,用户的身份验证令牌(密码)只有在过期时才应更改。如果未传递此参数,则应用程序要求更改所有身份验证令牌。
此处传给flags的实参为0。
更多讲解请看下回。