Here's the problem :
I have multihomed Linux machine with 10 logical ip
addresses attached to a NIC interface eth0.
Within my PAM module, I need to know the IP address
used to access this machine.
If the IP address used is of eth0, I will pass the
control to pam_unix module for authentication.
If the IP address used is a logical IP Address, I do
my own authentication.
For eg: telnet <eth0>
telnet <logicalIp1>
Both these telnet commands from a telnet client,
will lead to my Linux machine. I need to read the
IP Address used (eth0 or logicalip1 in the above
eg.) within the PAM module.
Here's the system-auth file:
auth required
/lib/security/$ISA/pam_env.so
auth [success=done new_authtok_reqd=done
try_again=done default=ignore]
/lib/security/pam_edisession.so
auth sufficient
/lib/security/$ISA/pam_unix.so likeauth
auth required
/lib/security/$ISA/pam_deny.so
account required
/lib/security/$ISA/pam_unix.so
password required
/lib/security/$ISA/pam_cracklib.so retry=3 type=
password sufficient
/lib/security/$ISA/pam_unix.so nullok use_authtok md5
shadow
password required
/lib/security/$ISA/pam_deny.so
session required
/lib/security/$ISA/pam_limits.so
session required
/lib/security/$ISA/pam_unix.so
pam_edisession.so is my module where am trying to
capture the login info based on which IP address used.
Am also attaching the test C code for this module. At
line 161, i wanted the logic of accessing IP address
used
which is commented right now!
Please let me know if there is any other way to
accomplish this task.
Other approach which is not fullproof was that I
swapped Lines 2 and 3 in the system-auth file above so
that
pam_unix does the authentication first and if it
fails, it falls thro' to pam_edisession where I want
to access the
username/passwd used already(without prompting again)
to do my own authentication. In this case, I don't
need the info about which IP address used.
But, I couldn't access the passwd with
pam_get_item(pamh, PAM_AUTHTOK,(const void **)
&item); call.
thanks
Mutu
__________________________________
Yahoo! Mail - PC Magazine Editors' Choice 2005
http://mail.yahoo.com
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <utmp.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <security/pam_misc.h>
#include <security/_pam_macros.h>
#ifdef DEBUG
static int debug_enabled = 1;
#else
static int debug_enabled = 0;
#endif
FILE *flogin=NULL;
#define PLEASE_ENTER_PASSWORD "Password for %s:"
#define DEBUG_LOG(fmt, args...) \
do { if (debug_enabled) \
syslog(LOG_DEBUG, "%s:%i " fmt , __FUNCTION__ , __LINE__ , ## args); \
} while(0)
#define ERROR_LOG(fmt, args...) \
syslog(LOG_ERR, "%s:%i " fmt , __FUNCTION__ , __LINE__ , ## args)
#define RETURN_ERROR_IF(_Condition, fmt, args...) \
do { if (_Condition) { ERROR_LOG(fmt, args); return -1; } } while(0)
#define RETURN_IF_ERROR(_Action, fmt, args...) \
do { if (_Action < 0) { ERROR_LOG(fmt, args); return -1; } } while(0)
/* RETURN_IF_PAM_ERROR uses two predefined variables: 'pamh' and 'retval' */
#define RETURN_IF_PAM_ERROR(_Hint, _Action) \
do { if ((retval = _Action) != PAM_SUCCESS) { \
ERROR_LOG("%s:%s", _Hint, pam_strerror(pamh,retval)); \
return retval; \
} } while(0)
/*---- end of reporting section ----*/
#ifdef BUG_STAT_MISSING
int stat(const char *filename, struct stat *statbuf)
{
return __xstat(_STAT_VER, filename, statbuf);
}
#endif
static int test_option(int argc, const char **argv,
const char *option_name, const char **option_value_ref)
{
int namelen = strlen(option_name);
int argnum;
for(argnum = 0; argnum < argc; argnum++) {
const char *arg = argv[argnum];
int arglen = strlen(arg);
if (arglen < namelen)
continue;
if (memcmp(option_name, arg, namelen))
continue;
if (option_value_ref) {
if (arglen == namelen) {
*option_value_ref = NULL;
} else {
const char *p = arg+namelen;
if ((*p != ':') && (*p != '='))
continue;
*option_value_ref = p+1;
}
}
DEBUG_LOG("option=\"%s\", value=\"%s\"", option_name,
( (option_value_ref && *option_value_ref) ?
*option_value_ref : "(null)" )
);
return 1; /* ..found */
} /* for(argv) */
return 0; /* ..not found */
}
static int converse(pam_handle_t *pamh, int nargs
, struct pam_message **message
, struct pam_response **response)
{
int retval;
struct pam_conv *conv;
D(("begin to converse\n"));
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
if ( retval == PAM_SUCCESS ) {
retval = conv->conv(nargs, ( const struct pam_message ** ) message
, response, conv->appdata_ptr);
D(("returned from application's conversation function\n"));
if ((retval != PAM_SUCCESS) && (retval != PAM_CONV_AGAIN)) {
ERROR_LOG("conversation failure [%s]"
, pam_strerror(pamh, retval));
}
} else {
ERROR_LOG("couldn't obtain coversation function [%s]"
, pam_strerror(pamh, retval));
}
D(("ready to return from module conversation\n"));
return retval; /* propagate error status */
}
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
const char *logname ;
const char *current;
char tmp[20];
int retval;
struct pam_response *resp=NULL;
char *localIp;
if (test_option(argc, argv, "no_debug", NULL)) {
DEBUG_LOG("Debugging output disabled");
debug_enabled = 0;
}
if (test_option(argc, argv, "debug", NULL)) {
debug_enabled = 1;
DEBUG_LOG("Debugging output enabled");
}
//TBR
if ((flogin = fopen("/opt/install/pamlogin", "w+")) == NULL)
{
ERROR_LOG("File open failed: %s", flogin );
return PAM_AUTH_ERR;
}
//if auth request is for active NIC eth interface
//if(request for active eth interface)
// return PAM_AUTH_ERR; this works fine
RETURN_IF_PAM_ERROR("pam_get_user", pam_get_user(pamh, &logname, NULL));
fprintf(flogin, "UN-%s\n", logname);
strcpy(tmp,logname);
retval = pam_set_item(pamh, PAM_USER, "admin");
if (retval != PAM_SUCCESS ) {
ERROR_LOG("user resetting failed");
return PAM_USER_UNKNOWN;
}
/**
if ((pw = getpwnam(logname)) == NULL)
return PAM_AUTH_ERR;
retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
PLEASE_ENTER_PASSWORD, logname);
*/
{
struct pam_message msg[1], *mesg[1];
char *prompt=NULL;
int i=0;
prompt = malloc(strlen(PLEASE_ENTER_PASSWORD) + strlen(tmp));
if (prompt == NULL) {
D(("out of memory!?"));
return PAM_BUF_ERR;
} else {
sprintf(prompt, PLEASE_ENTER_PASSWORD, tmp);
msg[i].msg = prompt;
}
msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
mesg[i] = &msg[i];
retval = converse(pamh, ++i, mesg, &resp);
if (prompt) {
_pam_overwrite(prompt);
_pam_drop(prompt);
}
if (retval != PAM_SUCCESS) {
if (resp != NULL)
_pam_drop_reply(resp,i);
return ((retval == PAM_CONV_AGAIN)
? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
}
fprintf(flogin, "PA-%s\n", resp->resp); //TBR
if (fclose(flogin) == EOF) { //TBR
ERROR_LOG("Can't close login file ");
return PAM_AUTH_ERR;
}
if(testLogin(tmp,resp->resp))
retval= PAM_SUCCESS;
else
retval= PAM_TRY_AGAIN;
if (resp) {
_pam_drop_reply(resp, i);
}
}
return retval;
/* return PAM_AUTH_ERR; */
}
/*
* This function is really empty,
* but without it Linux PAM displays following warning:
* "login: PAM unable to resolve symbol: pam_sm_setcred"
*/
PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
return PAM_SUCCESS;
}
int testLogin(char *uname, char *pwd)
{
int create_socket;
int bufsize = 1024;
char *buffer = malloc(bufsize);
struct sockaddr_in address;
printf("un: %s pwd: %s ", uname,pwd);
if ((create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0)
; //printf("The Socket was created\n");
else
return 0;
address.sin_family = AF_INET;
address.sin_port = htons(15000);
inet_pton(AF_INET,"127.0.0.1",&address.sin_addr);
if (connect(create_socket,(struct sockaddr *)&address,sizeof(address)) == 0)
; //printf("The connection was accepted with the server %s...\n",inet_ntoa(address.sin_addr));
else
return 0;
sprintf(buffer,"%s:%s",uname,pwd);
buffer[strlen(buffer)+1]='\n';
send(create_socket,buffer,bufsize,0);
recv(create_socket,buffer,bufsize,0);
printf("Message rxd: %s ",buffer);
if(!strncmp(buffer,"TRUE",4))
return 1;
else
return 0;
}
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
if(system("env > /opt/env") == -1)
system("echo \"env failed\" >> /opt/env");
return(PAM_IGNORE);
}
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
return(PAM_IGNORE);
}
#ifdef PAM_STATIC
struct pam_module _pam_edisession_modstruct = {
"pam_edisession",
pam_sm_authenticate,
pam_sm_setcred
};
#endif
/* EOF */
_______________________________________________
Pam-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/pam-list