2013-10-17 18:02:55 -04: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 11:35:24 -04:00
# include <time.h>
2013-10-19 14:07:30 -04:00
# include "config.h"
2013-10-17 18:02:55 -04:00
# include "util.h"
2013-10-18 05:33:02 -04:00
extern char * * environ ;
2014-04-22 11:35:24 -04:00
static const char * randreply ( void ) ;
2014-06-03 07:29:16 -04:00
static int dologin ( struct passwd * ) ;
2013-10-18 06:14:36 -04:00
2013-10-17 18:02:55 -04:00
static void
usage ( void )
{
2014-04-13 12:23:04 -04:00
eprintf ( " usage: %s [-lp] [user] \n " , argv0 ) ;
2013-10-17 18:02:55 -04:00
}
2013-10-18 05:33:02 -04:00
static int lflag = 0 ;
2013-10-18 09:26:14 -04:00
static int pflag = 0 ;
2013-10-18 05:33:02 -04:00
2013-10-17 18:02:55 -04:00
int
2014-04-18 06:49:10 -04:00
main ( int argc , char * argv [ ] )
2013-10-17 18:02:55 -04:00
{
2014-02-14 08:49:34 -05:00
char * usr = " root " , * pass , * cryptpass ;
2014-06-05 07:12:18 -04:00
char * shell ;
2013-10-17 18:02:55 -04:00
struct spwd * spw ;
struct passwd * pw ;
2014-06-05 06:28:08 -04:00
char * newargv [ 2 ] ;
2013-10-17 18:02:55 -04:00
uid_t uid ;
ARGBEGIN {
2013-10-18 05:33:02 -04:00
case ' l ' :
lflag = 1 ;
break ;
2013-10-18 09:26:14 -04:00
case ' p ' :
pflag = 1 ;
break ;
2013-10-17 18:02:55 -04:00
default :
usage ( ) ;
} ARGEND ;
if ( argc < 1 )
2014-02-14 08:49:34 -05:00
;
2013-10-17 18:02:55 -04:00
else if ( argc = = 1 )
usr = argv [ 0 ] ;
else
usage ( ) ;
2014-04-22 11:35:24 -04:00
srand ( time ( NULL ) ) ;
2013-10-18 05:20:13 -04:00
errno = 0 ;
2014-06-03 07:09:25 -04:00
pw = getpwnam ( usr ) ;
2013-10-18 05:20:13 -04:00
if ( errno )
2014-06-03 07:09:25 -04:00
eprintf ( " getpwnam: %s: " , usr ) ;
else if ( ! pw )
2014-02-27 09:57:22 -05:00
eprintf ( " who are you? \n " ) ;
2013-10-17 18:02:55 -04:00
2014-06-03 07:09:25 -04:00
switch ( pw - > pw_passwd [ 0 ] ) {
2013-10-17 18:02:55 -04:00
case ' ! ' :
case ' * ' :
2014-06-02 12:14:53 -04:00
eprintf ( " denied \n " ) ;
2013-10-17 18:02:55 -04:00
}
2014-06-03 07:09:25 -04:00
/* Empty password? Su now */
if ( pw - > pw_passwd [ 0 ] = = ' \0 ' )
goto dosu ;
2014-02-14 08:49:34 -05:00
uid = getuid ( ) ;
2013-10-17 18:02:55 -04:00
if ( uid ) {
pass = getpass ( " Password: " ) ;
if ( ! pass )
eprintf ( " getpass: " ) ;
2014-06-03 07:09:25 -04:00
}
2013-10-17 18:02:55 -04:00
2014-06-03 07:09:25 -04: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 05:25:39 -04:00
}
2013-10-17 18:02:55 -04:00
2014-06-03 07:09:25 -04:00
dosu :
2013-10-17 18:02:55 -04: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 06:14:36 -04:00
if ( lflag ) {
2014-06-03 07:29:16 -04:00
return dologin ( pw ) ;
2013-10-18 06:14:36 -04:00
} else {
2014-06-05 07:12:18 -04:00
shell = pw - > pw_shell [ 0 ] = = ' \0 ' ? " /bin/sh " : pw - > pw_shell ;
newargv [ 0 ] = shell ;
2014-06-05 06:28:08 -04:00
newargv [ 1 ] = NULL ;
2013-10-18 09:26:14 -04:00
if ( ! pflag ) {
setenv ( " HOME " , pw - > pw_dir , 1 ) ;
2014-06-05 07:12:18 -04:00
setenv ( " SHELL " , shell , 1 ) ;
2013-10-18 09:26:14 -04:00
if ( strcmp ( pw - > pw_name , " root " ) ! = 0 ) {
setenv ( " USER " , pw - > pw_name , 1 ) ;
setenv ( " LOGNAME " , pw - > pw_name , 1 ) ;
}
2013-10-18 06:20:59 -04:00
}
2013-10-19 14:07:30 -04:00
if ( strcmp ( pw - > pw_name , " root " ) = = 0 )
setenv ( " PATH " , ENV_SUPATH , 1 ) ;
else
setenv ( " PATH " , ENV_PATH , 1 ) ;
2014-06-05 07:12:18 -04:00
execve ( pflag ? getenv ( " SHELL " ) : shell ,
2013-10-18 11:22:24 -04:00
newargv , environ ) ;
2014-06-05 07:12:18 -04:00
weprintf ( " execve %s: " , shell ) ;
2014-06-03 07:29:16 -04:00
return ( errno = = ENOENT ) ? 127 : 126 ;
2013-10-18 06:14:36 -04:00
}
2014-06-03 07:29:16 -04:00
return EXIT_SUCCESS ;
2013-10-17 18:02:55 -04:00
}
2013-10-18 06:14:36 -04:00
2014-04-22 11:35:24 -04: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 07:29:16 -04:00
static int
2013-10-18 06:14:36 -04:00
dologin ( struct passwd * pw )
{
2014-06-05 07:12:18 -04:00
char * shell = pw - > pw_shell [ 0 ] = = ' \0 ' ? " /bin/sh " : pw - > pw_shell ;
2014-06-03 07:24:17 -04:00
char * term = getenv ( " TERM " ) ;
clearenv ( ) ;
setenv ( " HOME " , pw - > pw_dir , 1 ) ;
2014-06-05 07:12:18 -04:00
setenv ( " SHELL " , shell , 1 ) ;
2014-06-03 07:24:17 -04:00
setenv ( " USER " , pw - > pw_name , 1 ) ;
setenv ( " LOGNAME " , pw - > pw_name , 1 ) ;
2014-06-03 13:19:31 -04:00
setenv ( " TERM " , term ? term : " linux " , 1 ) ;
2014-06-03 07:24:17 -04:00
if ( strcmp ( pw - > pw_name , " root " ) = = 0 )
setenv ( " PATH " , ENV_SUPATH , 1 ) ;
else
setenv ( " PATH " , ENV_PATH , 1 ) ;
2013-10-18 06:14:36 -04:00
if ( chdir ( pw - > pw_dir ) < 0 )
eprintf ( " chdir %s: " , pw - > pw_dir ) ;
2014-06-05 07:12:18 -04:00
execlp ( shell , shell , " -l " , NULL ) ;
weprintf ( " execlp %s: " , shell ) ;
2014-06-03 07:29:16 -04:00
return ( errno = = ENOENT ) ? 127 : 126 ;
2013-10-18 06:14:36 -04:00
}