了解为什么 pam c API 函数 pam_get_data() " No module specific data is present "获得未初始化的值错误?



我的问题与PAM -https://linux.die.net/man/3/pam 我的代码在 API 函数中输入两次 PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) ;在一个SSH会话入口期间。 在此函数中,我正在向服务器发送请求,因此我将会话添加到 PAMH,但pam_set_date后我无法通过 pam_get _data 获取数据,并且我无法/无法获取此变量。我的代码 :

#define _GNU_SOURCE
#include "pam_hook.h" /*standart c includes file and defines */

/*PAM includes */
#include <security/pam_modules.h>
#include <security/pam_modutil.h>
#include <security/pam_ext.h>
/*PAM defintion */
#define PAM_SM_AUTH
#define PAM_SM_SESSION
/*
* 0 - it's first time in SHM ,  else -1 error , 1- it's not fist time and  
*/
int pam_set_or_get_data(pam_handle_t *pamh){
int retval;
void *dataptr;
const void * getData;
retval = pam_get_data(pamh, "pam_session_id",(const void **) &getData);
if (retval== PAM_SUCCESS) 
{
PAM_LOG_args( "pam_set_or_get_data not first time ", pam_strerror(pamh,retval));
return 1;
}
else
{
PAM_LOG_args( "pam_set_or_get_data yes first time get failed du to ", pam_strerror(pamh,retval));
}
dataptr = strdup ("sesion_ID");
if(dataptr==NULL)
{
PAM_LOG_args( "pam_set_or_get_data strdup error ", pam_strerror(pamh,retval));
perror("strdup insufficient memory was available");
return -1;
}
retval = pam_set_data (pamh,"pam_session_id", dataptr, sesion_id_cleanup);
if (retval == PAM_SUCCESS)
{
PAM_LOG_args( "pam_set_or_get_data yes first time ", pam_strerror(pamh,retval));
retval = pam_get_data(pamh,"pam_session_id",(const void **) &getData);
if (retval== PAM_SUCCESS) 
{
PAM_LOG_args( "pam_set_or_get_data get after set ", pam_strerror(pamh,retval));
}
return 0;
}
else
{
PAM_LOG_args( "pam_set_data returned when expecting PAM_SYSTEM_ERR ", pam_strerror(pamh,retval)); 
free (dataptr);  
return -1;
}
}
/* The actual pam functions are merely wrappers around succeed_if */
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
const char * password=NULL;
struct passwd *pwd;
const char *user;
int pam_err=0;
PAM_LOG_args( "pam_sm_authenticate", strerror(errno));
debugPrint("pam_sm_authenticate ","",0,pamh);
printTime();
/* identify user */
pam_err = pam_get_user(pamh, &user, NULL);
if (pam_err != PAM_SUCCESS)
{
debugPrint("error in getting the user name :",(char *)pam_strerror(pamh, pam_err),0,pamh);
return (pam_err);
}
if ((pwd = getpwnam(user)) == NULL)
{
debugPrint("user not defined in the system :",(char *)pam_strerror(pamh, pam_err),0,pamh);
return (PAM_USER_UNKNOWN);
}
/*note : if user is not deefined pawsword return will be "^H$^M^?INCORRECT^@" */
pam_err  = pam_get_authtok(pamh, PAM_AUTHTOK, &password , NULL);
if (pam_err!=PAM_SUCCESS)
{
debugPrint("error in getting the pasword :",(char *)pam_strerror(pamh, pam_err),0,pamh);
return (PAM_AUTH_ERR);
}

/*tacacs/radius auhtenticate */
if( pam_set_or_get_data(pamh) ==0)
{
debugPrint("pam_sm_authenticate already_send_req!=1 goto isAuthenticate user: ",(char *)user,0,pamh);
pam_err = isAuthenticate((char *)user,(char *)password);
if (pam_err != PAM_OK)
{
debugPrint("user is not valid with tacacs/radius","",0,pamh);
return (PAM_AUTH_ERR);
}
}

return (PAM_SUCCESS);
}

我制作的印刷品:

function :  pam_sm_authenticate  my  PID: 29452  parent PID 29445 Success stererr :Success
function :  pam_set_or_get_data yes first time get failed du to   my  PID: 29452  parent PID 29445 No module specific data is present stererr :Success
function :  pam_set_or_get_data yes first time   my  PID: 29452  parent PID 29445 Success stererr :Success
function :  pam_set_or_get_data get after set   my  PID: 29452  parent PID 29445 Success stererr :Success
function :  isAuthenticate  my  PID: 29452  parent PID 29445 Success stererr :Success
function :  pam_sm_open_session   my  PID: 29452  parent PID 29445 Unknown error -3 stererr :Unknown error -3
function :  pam_sm_authenticate  my  PID: 29459  parent PID 29445 Success stererr :Success
function :  pam_set_or_get_data yes first time get failed du to   my  PID: 29459  parent PID 29445 No module specific data is present stererr :Success
function :  pam_set_or_get_data yes first time   my  PID: 29459  parent PID 29445 Success stererr :Success
function :  pam_set_or_get_data get after set   my  PID: 29459  parent PID 29445 Success stererr :Success
function :  isAuthenticate  my  PID: 29459  parent PID 29445 Success stererr :Success
function :  sesion_id_cleanup   my  PID: 29459  parent PID 29445 Authentication failure stererr :Broken pipe
function :  pam_sm_close_session   my  PID: 29452  parent PID 29445 No such file or directory stererr :No such file or directory
function :  pam_sm_close_session succses get pam sesion id  my  PID: 29452  parent PID 29445 sesion_ID stererr :No such file or directory
function :  sesion_id_cleanup   my  PID: 29452  parent PID 29445 Success stererr :Unknown error -6

我可以看到不同的过程正在调用pam_sm_authenticate,为什么?以及为什么它没有获得我sesion_id设置的数据?

我的 PAM 配置

root@compute:/# cat /etc/pam.d/sshd
auth        requisite       /root/my_target/disk2/Sw-Pack/Active/iu_pam_hook.so
session     optional       /root/my_target/disk2/Sw-Pack/Active/iu_pam_hook.so

编译它与:

gcc -fPIC -Wall -shared -lpam -o pam_hook.so pam_hook.c

sshd 默认使用权限分离。这意味着身份验证发生在一个单独的进程中,并有一个定义的数据通道来回传递。

因此,在 sshd 的情况下,pam_set_data仅在相同的 PAM 部分中工作。换句话说,存储在auth部分的数据将不适用于session部分 - 这是因为数据存储在身份验证进程的上下文中,该进程不与会话进程共享数据。

如果您关闭 sshd 的权限分离,则使用 pam_set_data可能会起作用,但这不是一个长期的解决方案,因为该选项从 sshd 7.5 开始删除,因此您需要使用另一种机制重新实现它

您可以使用的一种机制是环境变量 -pam_putenv可以很好地将数据从身份验证进程传递回会话管理部分。

因此,在身份验证部分中,将数据存储在环境变量中 -pam_putenv(handle, "VAR=value")并使用pam_getenv(handle, "VAR")检索它们。

当然,唯一的问题是,如果数据是二进制形式,您将无法以这种方式传输未经编码的数据,此外,您可能希望pam_putenv(handle, "VAR")以防止 PAM 环境变量泄漏到用户会话中。

最新更新