@ -33,8 +33,10 @@
static void usage ( void ) ;
static int perm_set ( const char * , const char * ) ;
static int authenticate ( const char * ) ;
// FIXME: misc_conv is a separate library, should stick to plain PAM
// FIXME: misc_conv is a separate library, should stick to plain PAM or make
// our own pam module
static struct pam_conv conv = { misc_conv , NULL } ;
int main ( int argc , char * argv [ ] )
@ -66,14 +68,16 @@ int main (int argc, char *argv[])
}
}
// Copy argv and argc
int c_argc = argc - optind ;
/*
int c_argc = argc - optind + 2 ;
char * * c_argv = malloc ( ( c_argc + 1 ) * sizeof ( char * ) ) ;
if ( ! c_argv ) {
fprintf ( stderr , " malloc: %s \n " , strerror ( errno ) ) ;
goto fail_end ;
}
for ( int i = 0 ; optind < argc ; i + + , optind + + ) {
c_argv [ 0 ] = shell ;
c_argv [ 1 ] = " -c " ;
for ( int i = 2 ; optind < argc ; i + + , optind + + ) {
c_argv [ i ] = strdup ( argv [ optind ] ) ;
if ( ! c_argv [ i ] ) {
fprintf ( stderr , " getpwid: %s \n " , strerror ( errno ) ) ;
@ -81,45 +85,50 @@ int main (int argc, char *argv[])
}
}
c_argc [ c_argv ] = NULL ;
*/
if ( c_argc = = 0 ) {
usage ( ) ;
exit ( EINVAL ) ;
/* Set argc and argv */
// TODO: get the right shell for the user (it is in the passwd struct)
char * shell = " /bin/sh " ;
char * command , * * c_argv ;
int size , popind = optind ;
int c_argc = 3 ; // /bin/sh -c command
c_argv = malloc ( ( c_argc + 1 ) * sizeof ( char * ) ) ;
if ( ! c_argv ) {
fprintf ( stderr , " malloc: %s \n " , strerror ( errno ) ) ;
exit ( errno ) ;
}
for ( size = 0 ; optind < argc ; optind + + )
size + = strlen ( argv [ optind ] ) + 1 ;
command = malloc ( sizeof ( char ) * size ) ;
if ( ! command ) {
fprintf ( stderr , " malloc: %s \n " , strerror ( errno ) ) ;
exit ( errno ) ;
}
for ( optind = popind ; optind < argc ; optind + + ) {
strcat ( command , argv [ optind ] ) ;
strcat ( command , " " ) ;
}
c_argv [ 0 ] = shell ;
// FIXME: this should be optional if size is zero: we want just a shell
c_argv [ 1 ] = " -c " ;
c_argv [ 2 ] = command ;
c_argv [ c_argc ] = NULL ;
/* Authenticate */
uid_t ruid = getuid ( ) ;
struct passwd * pw = getpwuid ( ruid ) ;
if ( ! pw ) {
fprintf ( stderr , " getpwid: %s \n " , strerror ( errno ) ) ;
exit ( errno ) ;
return errno ;
}
const char * uname = pw - > pw_name ;
if ( authenticate ( uname ) ! = PAM_SUCCESS )
exit ( EXIT_FAILURE ) ;
pam_handle_t * pamh ;
int pam_err , count = 0 ;
pam_err = pam_start ( " User Switcher " , uname , & conv , & pamh ) ;
if ( pam_err ! = PAM_SUCCESS ) {
fprintf ( stderr , " pam_start: %s \n " , pam_strerror ( pamh , pam_err ) ) ;
exit ( pam_err ) ;
}
do {
pam_err = pam_authenticate ( pamh , 0 ) ;
if ( pam_err ! = PAM_SUCCESS )
printf ( " Auth failed: %s \n " , pam_strerror ( pamh , pam_err ) ) ;
count + + ;
} while ( pam_err ! = PAM_SUCCESS & & count < 4 ) ;
if ( pam_err ! = PAM_SUCCESS ) {
fprintf ( stderr , " better luck next time \n " ) ;
pam_end ( pamh , pam_err ) ;
exit ( pam_err ) ;
}
// FIXME: check again for the validity of the login for more security
// as in: https://docs.oracle.com/cd/E19120-01/open.solaris/819-2145/pam-20/index.html
// FIXME: ^C [SIGINT] will interrupt this call possibly causing a
// vulnerability
pam_end ( pamh , pam_err ) ;
// TODO: clean up env
errno = 0 ;
@ -130,7 +139,7 @@ int main (int argc, char *argv[])
}
/* Execute the command */
if ( execvp ( * c_argv , c_argv ) = = - 1 ) // execvp searches in path
if ( execv ( * c_argv , c_argv ) = = - 1 ) // execvp searches in path
fprintf ( stderr , " execv: %s \n " , strerror ( errno ) ) ;
/* Cleanup and return */
@ -231,3 +240,35 @@ static int perm_set (const char *user, const char *group)
return 0 ;
}
static int authenticate ( const char * uname )
{
pam_handle_t * pamh ;
int pam_err , count = 0 ;
pam_err = pam_start ( " User Switcher " , uname , & conv , & pamh ) ;
if ( pam_err ! = PAM_SUCCESS ) {
fprintf ( stderr , " pam_start: %s \n " , pam_strerror ( pamh , pam_err ) ) ;
return pam_err ;
}
do {
pam_err = pam_authenticate ( pamh , 0 ) ;
if ( pam_err ! = PAM_SUCCESS )
printf ( " Auth failed: %s \n " , pam_strerror ( pamh , pam_err ) ) ;
// FIXME: count gets ignored because authentication service has
// a set amount of retries giving an error:
// Have exhausted maximum number of retries for service
count + + ;
} while ( pam_err ! = PAM_SUCCESS & & count < 4 ) ;
if ( pam_err ! = PAM_SUCCESS ) {
fprintf ( stderr , " better luck next time \n " ) ;
pam_end ( pamh , pam_err ) ;
return pam_err ;
}
// FIXME: check again for the validity of the login for more security
// as in: https://docs.oracle.com/cd/E19120-01/open.solaris/819-2145/pam-20/index.html
// FIXME: ^C [SIGINT] will interrupt this call possibly causing a
// vulnerability
return pam_end ( pamh , pam_err ) ;
}