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 ) ;
2014-06-03 11:29:16 +00:00
static int dologin ( struct passwd * ) ;
2013-10-18 10:14:36 +00:00
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 ;
2014-06-03 11:09:25 +00:00
pw = getpwnam ( usr ) ;
2013-10-18 09:20:13 +00:00
if ( errno )
2014-06-03 11:09:25 +00:00
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
2014-06-03 11:09:25 +00:00
switch ( pw - > pw_passwd [ 0 ] ) {
2013-10-17 22:02:55 +00:00
case ' ! ' :
case ' * ' :
2014-06-02 16:14:53 +00:00
eprintf ( " denied \n " ) ;
2013-10-17 22:02:55 +00:00
}
2014-06-03 11:09:25 +00:00
/* Empty password? Su now */
if ( pw - > pw_passwd [ 0 ] = = ' \0 ' )
goto dosu ;
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: " ) ;
2014-06-03 11:09:25 +00:00
}
2013-10-17 22:02:55 +00:00
2014-06-03 11:09:25 +00:00
if ( pw - > pw_passwd [ 0 ] = = ' x ' & & pw - > pw_passwd [ 1 ] = = ' \0 ' ) {
errno = 0 ;
spw = getspnam ( usr ) ;
if ( errno )
eprintf ( " getspnam: %s: " , usr ) ;
else if ( ! spw )
eprintf ( " who are you? \n " ) ;
switch ( spw - > sp_pwdp [ 0 ] ) {
case ' ! ' :
case ' * ' :
eprintf ( " denied \n " ) ;
}
if ( uid ) {
cryptpass = crypt ( pass , spw - > sp_pwdp ) ;
if ( ! cryptpass )
eprintf ( " crypt: " ) ;
if ( strcmp ( cryptpass , spw - > sp_pwdp ) ! = 0 )
eprintf ( randreply ( ) ) ;
}
} else {
if ( uid ) {
cryptpass = crypt ( pass , pw - > pw_passwd ) ;
if ( ! cryptpass )
eprintf ( " crypt: " ) ;
if ( strcmp ( cryptpass , pw - > pw_passwd ) ! = 0 )
eprintf ( " login failed \n " ) ;
}
2013-10-18 09:25:39 +00:00
}
2013-10-17 22:02:55 +00:00
2014-06-03 11:09:25 +00:00
dosu :
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 ) {
2014-06-03 11:29:16 +00:00
return dologin ( pw ) ;
2013-10-18 10:14:36 +00:00
} 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 ) ;
2014-06-03 11:29:16 +00:00
weprintf ( " execve %s: " , pw - > pw_shell ) ;
return ( errno = = ENOENT ) ? 127 : 126 ;
2013-10-18 10:14:36 +00:00
}
2014-06-03 11:29:16 +00:00
return EXIT_SUCCESS ;
2013-10-17 22:02:55 +00:00
}
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 ) ] ;
}
2014-06-03 11:29:16 +00:00
static int
2013-10-18 10:14:36 +00:00
dologin ( struct passwd * pw )
{
2014-06-03 11:24:17 +00:00
char * term = getenv ( " TERM " ) ;
clearenv ( ) ;
setenv ( " HOME " , pw - > pw_dir , 1 ) ;
setenv ( " SHELL " , pw - > pw_shell , 1 ) ;
setenv ( " USER " , pw - > pw_name , 1 ) ;
setenv ( " LOGNAME " , pw - > pw_name , 1 ) ;
2014-06-03 17:19:31 +00:00
setenv ( " TERM " , term ? term : " linux " , 1 ) ;
2014-06-03 11:24:17 +00:00
if ( strcmp ( pw - > pw_name , " root " ) = = 0 )
setenv ( " PATH " , ENV_SUPATH , 1 ) ;
else
setenv ( " PATH " , ENV_PATH , 1 ) ;
2013-10-18 10:14:36 +00:00
if ( chdir ( pw - > pw_dir ) < 0 )
eprintf ( " chdir %s: " , pw - > pw_dir ) ;
2014-06-03 11:24:17 +00:00
execlp ( pw - > pw_shell , pw - > pw_shell , " -l " , NULL ) ;
2014-06-03 11:29:16 +00:00
weprintf ( " execlp %s: " , pw - > pw_shell ) ;
return ( errno = = ENOENT ) ? 127 : 126 ;
2013-10-18 10:14:36 +00:00
}