我正在尝试编写一些服务器,它使用linux对客户端进行身份验证。我写了下面的课:
class Pam
{
public:
Pam(const char *module, const char *username)
{
mConv.appdata_ptr = nullptr;
mConv.conv = &convCallback;
const int res = pam_start("system-auth", username, &mConv, &mPamHandle);
if (res != PAM_SUCCESS)
throw std::runtime_error("Failed to initialize PAM");
}
bool authenticate(char *passwd)
{
pam_response *resp = static_cast<pam_response*>(malloc(sizeof(pam_response)));
resp->resp = passwd;
resp->resp_retcode = 0;
mConv.appdata_ptr = resp;
const int res = pam_authenticate(mPamHandle, 0);
log(res);
return res == PAM_SUCCESS;
}
~Pam()
{
if (mPamHandle)
pam_end(mPamHandle, PAM_SUCCESS);
mPamHandle = nullptr;
}
private:
static int convCallback (int msgId, const pam_message **msg, pam_response **resp, void *appData)
{
*resp = static_cast<pam_response*>(appData);
return PAM_SUCCESS;
}
private:
pam_handle_t *mPamHandle = nullptr;
pam_conv mConv;
};
然后被使用如下:
Pam pam("system-auth", username);
if (pam.authenticate(passwd))
return true;
// error handling code here
我发现pam_authenticate返回有效用户/密码的PAM_AUTHTOK_RECOVERY_ERR。手册页和Linux-pan.org authenticate中记录的可能返回值根本不包含此值。文档显示pam_chauthtok可以返回它,这意味着:
PAM_AUTHTOK_RECOVERY_ERR 模块无法获得旧的身份验证令牌。
目前还不清楚这对身份验证意味着什么。我尝试以普通用户和root用户的身份运行代码,结果是一样的。
发布于 2014-08-15 04:05:25
正在发生的事情是,您将0
视为appData
在convCallback
中的值,这是错误的来源--回复数据是空的,这意味着会话错误,这将导致PAM_AUTHTOK_RECOVERY_ERR
返回值。这是基于读取PAM源代码当前代码中的support.c
文件。
好吧,有几个问题。
pam_start
之后被视为常量。你应该在那里传递一个永远不会改变的值。如果您检查了会话函数,就会注意到appData
的值是0
。考虑到这两个方面,我稍微修改了您的代码如下,这将解决您的问题(同样,这是简化的代码):
class Pam
{
public:
Pam(const char *module, const char *username)
{
mConv.appdata_ptr = (void *)(this);
mConv.conv = &convCallback;
const int res = pam_start(module, username, &mConv, &mPamHandle);
if (res != PAM_SUCCESS)
throw std::runtime_error("Failed to initialize PAM");
}
bool authenticate(char *passwd)
{
mPassword = passwd;
const int res = pam_authenticate(mPamHandle, 0);
log(res);
return res == PAM_SUCCESS;
}
~Pam()
{
if (mPamHandle)
pam_end(mPamHandle, PAM_SUCCESS);
mPamHandle = 0;
}
private:
static int convCallback (int msgId, const pam_message **msg, pam_response **resp, void *appData)
{
Pam *me = static_cast<Pam *>(appData);
pam_response *reply = static_cast<pam_response *>(calloc(1, sizeof(pam_response)));
reply->resp = strdup(me->mPassword);
reply->resp_retcode = 0;
*resp = reply;
return PAM_SUCCESS;
}
private:
pam_handle_t *mPamHandle = 0;
pam_conv mConv;
const char *mPassword = 0;
};
https://stackoverflow.com/questions/25323600
复制