了解为什么 pam c api function pam_get_data() 得到未初始化的值错误“不存在模块特定数据”?
understanding why pam c api function pam_get_data() get uninitialized value error " 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 获取数据,而我 cna/t 获取此变量.我的代码:
#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
部分不可用 - 这是因为数据存储在 auth 进程的上下文中,不与会话共享数据过程。
如果您关闭 sshd 的特权分离,使用 pam_set_data 可能 工作,但这不是一个长期的解决方案,因为该选项从 sshd 7.5 开始被删除所以您需要使用另一种机制重新实现它
您可以使用的一种机制是环境变量 - pam_putenv
据我所知,可以很好地将数据从 auth 进程传回会话管理部分。
因此在 auth 部分,将数据存储在环境变量中 - pam_putenv(handle, "VAR=value")
并使用 pam_getenv(handle, "VAR")
检索它们。
当然,唯一的问题是,如果数据是二进制形式,您将无法以这种未编码的方式传输它,此外,您可能希望 pam_putenv(handle, "VAR")
防止 PAM 环境变量泄漏到用户会话中。
我的问题是 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 获取数据,而我 cna/t 获取此变量.我的代码:
#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
部分不可用 - 这是因为数据存储在 auth 进程的上下文中,不与会话共享数据过程。
如果您关闭 sshd 的特权分离,使用 pam_set_data 可能 工作,但这不是一个长期的解决方案,因为该选项从 sshd 7.5 开始被删除所以您需要使用另一种机制重新实现它
您可以使用的一种机制是环境变量 - pam_putenv
据我所知,可以很好地将数据从 auth 进程传回会话管理部分。
因此在 auth 部分,将数据存储在环境变量中 - pam_putenv(handle, "VAR=value")
并使用 pam_getenv(handle, "VAR")
检索它们。
当然,唯一的问题是,如果数据是二进制形式,您将无法以这种未编码的方式传输它,此外,您可能希望 pam_putenv(handle, "VAR")
防止 PAM 环境变量泄漏到用户会话中。