@ -32,8 +32,10 @@
# include <security/pam_misc.h>
static void usage ( void ) ;
static int perm_set ( const char * , const char * ) ;
static int perm_set ( struct passwd * , struct group * ) ;
static int authenticate ( const char * ) ;
static struct passwd * user_to_passwd ( const char * ) ;
static struct group * group_to_grp ( const char * ) ;
// FIXME: misc_conv is a separate library, should stick to plain PAM or make
// our own pam module
@ -43,9 +45,12 @@ int main (int argc, char *argv[])
{
// TODO: Add arguments
// FIXME: change the default program to execute SHELL
char * t_usr = NULL , * t_grp = NULL ;
char * t_usr = " root " , * t_grp = NULL ;
struct passwd * t_pw ;
struct group * t_gr ;
int opt ;
while ( ( opt = getopt ( argc , argv , " A:u:g:C: " ) ) ! = - 1 ) {
int shellflag = 0 ;
while ( ( opt = getopt ( argc , argv , " A:u:g:C:s " ) ) ! = - 1 ) {
switch ( opt ) {
case ' A ' :
printf ( " -A is not yet implemented \n " ) ;
@ -61,6 +66,9 @@ int main (int argc, char *argv[])
printf ( " -C is not yet implemented \n " ) ;
exit ( EXIT_FAILURE ) ;
break ;
case ' s ' :
shellflag = 1 ;
break ;
case ' ? ' :
usage ( ) ;
exit ( EINVAL ) ;
@ -68,64 +76,51 @@ int main (int argc, char *argv[])
}
}
/*
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 ;
/* Get user info */
const char * uname ;
char * shell ;
uid_t ruid = getuid ( ) ;
struct passwd * my_pw = getpwuid ( ruid ) ;
if ( ! my_pw ) {
fprintf ( stderr , " getpwid: %s \n " , strerror ( errno ) ) ;
return errno ;
}
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 ) ) ;
exit ( errno ) ;
}
uname = my_pw - > pw_name ;
t_pw = user_to_passwd ( t_usr ) ;
if ( ! t_pw ) {
fprintf ( stderr , " user_to_passwd: %s \n " , strerror ( errno ) ) ;
return errno ;
}
c_argc [ c_argv ] = NULL ;
*/
t_gr = group_to_grp ( t_grp ) ;
/* Get target user's shell */
if ( ! shellflag )
shell = t_pw - > pw_shell ;
else
shell = getenv ( " SHELL " ) ;
if ( ! shell )
shell = " /bin/sh " ;
/* 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 ;
char * command = NULL ;
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 , " " ) ;
if ( argc - optind ) {
for ( size = 0 ; optind < argc ; optind + + )
size + = strlen ( argv [ optind ] ) + 1 ;
command = malloc ( sizeof ( char ) * size + 1 ) ;
if ( ! command ) {
fprintf ( stderr , " malloc: %s \n " , strerror ( errno ) ) ;
exit ( errno ) ;
}
memset ( command , 0 , size + 1 ) ;
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 ) ) ;
return errno ;
}
const char * uname = pw - > pw_name ;
if ( authenticate ( uname ) ! = PAM_SUCCESS )
exit ( EXIT_FAILURE ) ;
@ -133,21 +128,24 @@ int main (int argc, char *argv[])
errno = 0 ;
/* Set permissions */
if ( perm_set ( t_usr , t_grp ) = = - 1 ) { // 0 = root
if ( perm_set ( t_pw , t_gr ) = = - 1 ) {
fprintf ( stderr , " perm_set: %s \n " , strerror ( errno ) ) ;
goto fail_end ;
}
/* Execute the command */
if ( execv ( * c_argv , c_argv ) = = - 1 ) // execvp searches in path
fprintf ( stderr , " execv: %s \n " , strerror ( errno ) ) ;
int err ;
if ( command )
err = execl ( shell , shell , " -c " , command , ( char * ) NULL ) ;
else
err = execl ( shell , shell , ( char * ) NULL ) ;
if ( err = = - 1 )
fprintf ( stderr , " execl: %s \n " , strerror ( errno ) ) ;
/* Cleanup and return */
fail_end :
/* Free up the copied argv */
for ( int i = 0 ; i < c_argc ; i + + )
free ( c_argv [ i ] ) ;
free ( c_argv ) ;
free ( command ) ;
return errno ;
}
@ -161,60 +159,24 @@ static inline void usage (void)
// -c [file]: manually select config file
// something about environment
// something about non interactiveness
printf ( " usage: us [-u user] [-g group] command [args] \n " ) ;
printf ( " usage: us [-s] [- u user] [-g group] command [args] \n " ) ;
}
static int perm_set ( const char * user , const char * group )
static int perm_set ( struct passwd * pw , struct group * gr )
{
if ( ! user )
user = " root " ;
struct passwd * pw ;
struct group * gr ;
uid_t uid ;
gid_t gid ;
long uid_l , gid_l ;
errno = 0 ;
if ( user [ 0 ] ! = ' # ' ) {
pw = getpwnam ( user ) ;
} else {
uid_l = strtol ( & user [ 1 ] , NULL , 10 ) ;
if ( uid_l < 0 | | errno ) {
errno = errno ? errno : EINVAL ;
return - 1 ;
}
pw = getpwuid ( ( uid_t ) uid_l ) ;
}
if ( ! pw ) {
if ( ! errno )
errno = EINVAL ;
errno = EINVAL ;
return - 1 ;
}
uid_t uid ;
gid_t gid ;
uid = pw - > pw_uid ;
gid = pw - > pw_gid ;
if ( group ) {
if ( group [ 0 ] ! = ' # ' ) {
gr = getgrnam ( group ) ;
} else {
gid_l = strtol ( & group [ 1 ] , NULL , 10 ) ;
if ( gid_l < 0 | | errno ) {
errno = errno ? errno : EINVAL ;
return - 1 ;
}
gr = getgrgid ( ( gid_t ) gid_l ) ;
}
if ( ! gr ) {
if ( ! errno )
errno = EINVAL ;
return - 1 ;
}
if ( gr )
gid = gr - > gr_gid ;
}
/* Set permissions, setting group perms first because in the case of
* dropping from higher permissions setting the uid first results in
@ -272,3 +234,62 @@ static int authenticate (const char *uname)
return pam_end ( pamh , pam_err ) ;
}
static struct passwd * user_to_passwd ( const char * user )
{
if ( ! user ) {
errno = EINVAL ;
return NULL ;
}
struct passwd * pw ;
long uid_l ;
errno = 0 ;
if ( user [ 0 ] ! = ' # ' ) {
pw = getpwnam ( user ) ;
} else {
uid_l = strtol ( & user [ 1 ] , NULL , 10 ) ;
if ( uid_l < 0 | | errno ) {
errno = errno ? errno : EINVAL ;
return NULL ;
}
pw = getpwuid ( ( uid_t ) uid_l ) ;
}
if ( ! pw ) {
if ( ! errno )
errno = EINVAL ;
return NULL ;
}
return pw ;
}
static struct group * group_to_grp ( const char * group )
{
if ( ! group ) {
errno = EINVAL ;
return NULL ;
}
struct group * gr ;
long gid_l ;
errno = 0 ;
if ( group [ 0 ] ! = ' # ' ) {
gr = getgrnam ( group ) ;
} else {
gid_l = strtol ( & group [ 1 ] , NULL , 10 ) ;
if ( gid_l < 0 | | errno ) {
errno = errno ? errno : EINVAL ;
return NULL ;
}
gr = getgrgid ( ( gid_t ) gid_l ) ;
}
if ( ! gr ) {
if ( ! errno )
errno = EINVAL ;
return NULL ;
}
return gr ;
}