2013-10-17 22:02:55 +00:00
/* See LICENSE file for copyright and license details. */
# include <sys/types.h>
# include <unistd.h>
# include <errno.h>
# include <pwd.h>
# include <grp.h>
# include <shadow.h>
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
2014-04-22 15:35:24 +00:00
# include <time.h>
2013-10-19 18:07:30 +00:00
# include "config.h"
2013-10-17 22:02:55 +00:00
# include "util.h"
2013-10-18 09:33:02 +00:00
extern char * * environ ;
2014-04-22 15:35:24 +00:00
static const char * randreply ( void ) ;
2013-10-18 10:14:36 +00:00
static char * msetenv ( const char * , const char * ) ;
static void dologin ( struct passwd * ) ;
2013-10-17 22:02:55 +00:00
static void
usage ( void )
{
2014-04-13 16:23:04 +00:00
eprintf ( " usage: %s [-lp] [user] \n " , argv0 ) ;
2013-10-17 22:02:55 +00:00
}
2013-10-18 09:33:02 +00:00
static int lflag = 0 ;
2013-10-18 13:26:14 +00:00
static int pflag = 0 ;
2013-10-18 09:33:02 +00:00
2013-10-17 22:02:55 +00:00
int
2014-04-18 10:49:10 +00:00
main ( int argc , char * argv [ ] )
2013-10-17 22:02:55 +00:00
{
2014-02-14 13:49:34 +00:00
char * usr = " root " , * pass , * cryptpass ;
2013-10-18 09:08:10 +00:00
char * const * newargv ;
2013-10-17 22:02:55 +00:00
struct spwd * spw ;
struct passwd * pw ;
uid_t uid ;
ARGBEGIN {
2013-10-18 09:33:02 +00:00
case ' l ' :
lflag = 1 ;
break ;
2013-10-18 13:26:14 +00:00
case ' p ' :
pflag = 1 ;
break ;
2013-10-17 22:02:55 +00:00
default :
usage ( ) ;
} ARGEND ;
if ( argc < 1 )
2014-02-14 13:49:34 +00:00
;
2013-10-17 22:02:55 +00:00
else if ( argc = = 1 )
usr = argv [ 0 ] ;
else
usage ( ) ;
2014-04-22 15:35:24 +00:00
srand ( time ( NULL ) ) ;
2013-10-18 09:20:13 +00:00
errno = 0 ;
2013-10-17 22:02:55 +00:00
spw = getspnam ( usr ) ;
2013-10-18 09:20:13 +00:00
if ( errno )
2013-10-17 22:02:55 +00:00
eprintf ( " getspnam: %s: " , usr ) ;
2013-10-18 09:20:13 +00:00
else if ( ! spw )
2014-02-27 14:57:22 +00:00
eprintf ( " who are you? \n " ) ;
2013-10-17 22:02:55 +00:00
switch ( spw - > sp_pwdp [ 0 ] ) {
case ' ! ' :
case ' * ' :
2014-04-22 15:35:24 +00:00
eprintf ( " Denied. \n " ) ;
2013-10-17 22:02:55 +00:00
case ' $ ' :
break ;
default :
2014-02-27 14:57:22 +00:00
eprintf ( " Invalid shadow record \n " ) ;
2013-10-17 22:02:55 +00:00
}
2014-02-14 13:49:34 +00:00
uid = getuid ( ) ;
2013-10-17 22:02:55 +00:00
if ( uid ) {
pass = getpass ( " Password: " ) ;
if ( ! pass )
eprintf ( " getpass: " ) ;
2013-10-18 09:25:39 +00:00
cryptpass = crypt ( pass , spw - > sp_pwdp ) ;
2014-04-30 11:26:27 +00:00
explicit_bzero ( pass , strlen ( pass ) ) ;
2013-10-18 09:25:39 +00:00
if ( ! cryptpass )
eprintf ( " crypt: " ) ;
2013-10-17 22:02:55 +00:00
2013-10-18 09:25:39 +00:00
if ( strcmp ( cryptpass , spw - > sp_pwdp ) ! = 0 )
2014-04-22 15:35:24 +00:00
eprintf ( randreply ( ) ) ;
2013-10-18 09:25:39 +00:00
}
2013-10-17 22:02:55 +00:00
errno = 0 ;
pw = getpwnam ( usr ) ;
if ( errno )
eprintf ( " getpwnam: %s " , usr ) ;
else if ( ! pw )
2014-02-27 14:57:22 +00:00
eprintf ( " who are you? \n " ) ;
2013-10-17 22:02:55 +00:00
if ( initgroups ( usr , pw - > pw_gid ) < 0 )
eprintf ( " initgroups: " ) ;
if ( setgid ( pw - > pw_gid ) < 0 )
eprintf ( " setgid: " ) ;
if ( setuid ( pw - > pw_uid ) < 0 )
eprintf ( " setuid: " ) ;
2013-10-18 10:14:36 +00:00
if ( lflag ) {
dologin ( pw ) ;
} else {
newargv = ( char * const [ ] ) { pw - > pw_shell , NULL } ;
2013-10-18 13:26:14 +00:00
if ( ! pflag ) {
setenv ( " HOME " , pw - > pw_dir , 1 ) ;
2013-10-18 19:57:24 +00:00
setenv ( " SHELL " , pw - > pw_shell , 1 ) ;
2013-10-18 13:26:14 +00:00
if ( strcmp ( pw - > pw_name , " root " ) ! = 0 ) {
setenv ( " USER " , pw - > pw_name , 1 ) ;
setenv ( " LOGNAME " , pw - > pw_name , 1 ) ;
}
2013-10-18 10:20:59 +00:00
}
2013-10-19 18:07:30 +00:00
if ( strcmp ( pw - > pw_name , " root " ) = = 0 )
setenv ( " PATH " , ENV_SUPATH , 1 ) ;
else
setenv ( " PATH " , ENV_PATH , 1 ) ;
2013-10-18 15:22:24 +00:00
execve ( pflag ? getenv ( " SHELL " ) : pw - > pw_shell ,
newargv , environ ) ;
2013-10-18 10:14:36 +00:00
}
2013-10-17 22:02:55 +00:00
return ( errno = = ENOENT ) ? 127 : 126 ;
}
2013-10-18 10:14:36 +00:00
2014-04-22 15:35:24 +00:00
static const char *
randreply ( void )
{
static const char * replies [ ] = {
" Time flies like an arrow, fruit flies like a banana. \n " ,
" Denied. \n " ,
" You type like a dairy farmer. \n " ,
" CChheecckk yyoouurr dduupplleexx sswwiittcchh.. \n " ,
" I met a girl with 12 nipples, it sounds weird dozen tit? \n " ,
" Here I am, brain the size of a planet and they ask me to keep hashing rubbish. \n " ,
" Clones are people two. \n " ,
" Your mom is an interesting su response. \n " ,
" no. \n " ,
" Your mom forgot to null-terminate???B?33??Abort (core dumped) \n " ,
" A fool-proof method for sculpting an elephant: first, get a huge block of marble; then you chip away everything that doesn't look like an elephant. \n " ,
" Bloating .data for fun and profit. \n " ,
} ;
return replies [ rand ( ) % LEN ( replies ) ] ;
}
2013-10-18 10:14:36 +00:00
static char *
msetenv ( const char * name , const char * value )
{
char * buf ;
size_t sz ;
sz = strlen ( name ) + strlen ( value ) + 2 ;
buf = malloc ( sz ) ;
if ( ! buf )
eprintf ( " malloc: " ) ;
snprintf ( buf , sz , " %s=%s " , name , value ) ;
return buf ;
}
static void
dologin ( struct passwd * pw )
{
char shbuf [ strlen ( pw - > pw_shell ) + 1 ] ;
char * const * newargv ;
char * const * newenv ;
strcpy ( shbuf , pw - > pw_shell ) ;
newargv = ( char * const [ ] ) { shbuf , NULL } ;
newenv = ( char * const [ ] ) {
msetenv ( " HOME " , pw - > pw_dir ) ,
msetenv ( " SHELL " , pw - > pw_shell ) ,
msetenv ( " USER " , pw - > pw_name ) ,
msetenv ( " LOGNAME " , pw - > pw_name ) ,
msetenv ( " TERM " , getenv ( " TERM " ) ) ,
2013-10-19 18:07:30 +00:00
msetenv ( " PATH " ,
strcmp ( pw - > pw_name , " root " ) = = 0 ?
ENV_SUPATH : ENV_PATH ) ,
2013-10-18 10:14:36 +00:00
NULL
} ;
if ( chdir ( pw - > pw_dir ) < 0 )
eprintf ( " chdir %s: " , pw - > pw_dir ) ;
execve ( pw - > pw_shell , newargv , newenv ) ;
}