[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

accessing telnet/ssh Server IP adress information within PAM module.. HOW?



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 */

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]