my issue is with PAM -https://linux.die.net/man/3/pam my code enter twice to the API function PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) ; during one ssh session entrance. in this function i am sending request to a server so i added session is to the pamh, but after pam_set_date i can't get the data via pam_get _data and i cna/t get this variable. my code :
#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);
}
the prints i made:
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
i can see that a diffrent procces is calling pam_sm_authenticate, why ? and why it does not get the data i set sesion_id ?
my pam configuration
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
compiled it with :
gcc -fPIC -Wall -shared -lpam -o pam_hook.so pam_hook.c
sshd uses privilege separation by default. This means that the authentication occurs in a separate process, with a defined channel of data being passed back and forth.
So, in the case of sshd use of pam_set_data
only works within the same PAM section. In other words data stored in the auth
section will not be available to the session
section - this is because the data is stored in the context of the auth process, which doesn't share data with the session process.
Using pam_set_data might work if you turn off privilege separation for sshd, however this is not a long term solution as the option is removed from sshd 7.5 onwards so you would need to reimplement it using another mechanism
A mechanism you can use would be environment variables - pam_putenv
works just fine for passing data back from the auth process to the session management section from what I can tell.
So in the auth section, store the data in environment variables - pam_putenv(handle, "VAR=value")
and retrieve them using pam_getenv(handle, "VAR")
.
The only issue is, of course, if the data is in a binary form, you won't be able to transfer it in this manner unencoded, and in addition, you probably want to pam_putenv(handle, "VAR")
to prevent the PAM environment variable from leaking into the user session.