}
} else {
msg_error(_("Can't get PAM_RHOST?!"));
goto last;
}
if(!read_token(&tok)) { /* 读取卡中的认证标记 */
msg_error(_("Read card failed: %s"), card_strerror());
goto last;
}
/* Mission begins */
retval = PAM_AUTH_ERR;
{
char *resp = NULL;
int ret;
ret = validate_token(&tok, NULL); /* 检查是否是有效的认证标记,是否
加密,并且在提供了PIN的时候解密 */
if(ret == VALIDATE_TOKEN_NEEDPIN) {
if(PAM_SUCCESS != pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp, _("PIN: "))) {
msg_error(_("Failed to obtain PIN"));
} else {
ret = validate_token(&tok, resp); /* 解密 */
}
}
if(!ret) {
msg_error("%s", card_strerror());
goto last;
}
}
/* 获取用户名 */
if(PAM_SUCCESS != pam_get_item(pamh, PAM_USER, (const void
**)&desired_user)) {
msg_error(_("Can't get username ?!"));
goto last;
}
uih = read_userinfo();
if(!uih) {
msg_error(_("Can't read userinfo!"));
goto last;
}
/* 如果指定了用户名,按照用户名查找,如果没有,按照认证标记中的 ID
查找 */
if(desired_user) {
u = find_user_by_name(uih, desired_user);
} else {
u = find_user_by_id(uih, tok.id);
}
if(!u) {
retval = PAM_USER_UNKNOWN;
msg_error(_("Unknown or unregistered user."));
goto last;
}
(void) digest(&tok.magic1, u->id, hash); /* 计算hash */
if(!memcmp(hash, u->hash, 64)) { /* 如果hash 匹配,认证成功 */
retval = PAM_SUCCESS;
pam_set_item(pamh, PAM_USER, u->username); /* 设定用户名: 因为用户名
可能是我们根据认证标记中的id 确定的, 要让 pam stack上的其他插件都知道 */
goto last;
} else { /* 不匹配,则认证失败 */
msg_error(_("Authenticate failure."));
goto last;
}
last:
memset(&tok, 0, sizeof tok); /* 安全起见,将认证标记清0 */
ptok = NULL;
if(uih)
free_userinfo(uih);
return retval;
}
PAM_EXTERN int pam_sm_setcred (pam_handle_t *pamh, int flags, int argc, const
char **argv)
{
/* 这个函数我也没弄明白是干什么用的,但是除了 pam_unix.so,其他的插件都是
直接返回 PAM_SUCCESS。 pam_unix.so也仅仅是缓存了pam_sm_authenticate的返回值来
作为这个函数的返回值。这样对功能没有影响 */
return PAM_SUCCESS;
}
关于智能卡和 SIM 卡的读写 |