Subject: Re: bin/2905: setting environment vars from login
To: None <andreas@planix.com>
From: Perry E. Metzger <perry@piermont.com>
List: netbsd-bugs
Date: 10/29/1996 18:31:45
This makes me nervous. System V suffers from many security holes made
possible by this facility. I'm not personally sure that I would want
to see it done unless it was very carefully studied.

Perry

andreas@planix.com writes:
> 
> >Number:         2905
> >Category:       bin
> >Synopsis:       setting environment variables from the login: prompt
> >Confidential:   no
> >Severity:       non-critical
> >Priority:       medium
> >Responsible:    bin-bug-people (Utility Bug People)
> >State:          open
> >Class:          change-request
> >Submitter-Id:   net
> >Arrival-Date:   Tue Oct 29 12:20:00 1996
> >Last-Modified:
> >Originator:     Andreas Wrede
> >Organization:
> Planix, Inc.
> >Release:        <NetBSD-current source date> Oct 27 11:52 EST 1996
> >Environment:
> 	
> System: NetBSD woffi 1.2B NetBSD 1.2B (WOFFI) #0: Sun Oct 27 17:50:01 EST 199
6 root@woffi:/local/src/netbsd-current/src/sys/arch/i386/compile/WOFFI i386
> 
> 
> >Description:
> 	
> This change to login allows a user to set environment variables from the 
> login: prompt, via: 'login: username VAR1=value1 VAR2=value2'
> This for example allows the use the same account for interactive (=shell)
> and encapsulated (=PPP/SLIP) sessions by having the PPP/SLIP specify 
> a variable at the login: prompt and the system profile act on it. The idea 
> for this was shamelessly stolen from Solaris.
> 
> 
> >How-To-Repeat:
> 	
> N/A
> >Fix:
> 	
> 
> diff -c /usr/src/usr.bin/login/login.1 ./login.1
> *** /usr/src/usr.bin/login/login.1	Fri Oct 13 23:14:44 1995
> --- ./login.1	Tue Oct 29 14:12:22 1996
> ***************
> *** 44,49 ****
> --- 44,50 ----
>   .Op Fl fp
>   .Op Fl h Ar hostname
>   .Op Ar user
> + .Op Ar environ
>   .Sh DESCRIPTION
>   The
>   .Nm login
> ***************
> *** 115,120 ****
> --- 116,128 ----
>   specifying the user's home directory (HOME), command interpreter (SHELL),
>   search path (PATH), terminal type (TERM) and user name (both LOGNAME and
>   USER).
> + .Pp
> + Additional environment values may be specified via
> + .Op Ar environ
> + on the command line or after the username in response to the 
> + login: prompt. Each argument takes the form NAME=value, where NAME 
> + is the name of the environment variable and VALUE is the value to 
> + assigne to it.  Attempts to set PATH, HOME, SHELL, LOGNAME or USER are igno
red.
>   .Pp
>   The standard shells,
>   .Xr csh 1
> diff -c /usr/src/usr.bin/login/login.c ./login.c
> *** /usr/src/usr.bin/login/login.c	Mon Oct 14 12:55:01 1996
> --- ./login.c	Tue Oct 29 14:13:48 1996
> ***************
> *** 102,107 ****
> --- 102,108 ----
>    * be patched on machines where it's too small.
>    */
>   u_int	timeout = 300;
> + char nbuf[BUFSIZ];
>   
>   #if defined(KERBEROS) || defined(KERBEROS5)
>   int	notickets = 1;
> ***************
> *** 112,118 ****
>   
>   struct	passwd *pwd;
>   int	failures;
> ! char	term[64], *envinit[1], *hostname, *username, *tty;
>   
>   int
>   main(argc, argv)
> --- 113,119 ----
>   
>   struct	passwd *pwd;
>   int	failures;
> ! char	term[64], *envinit[1], *hostname, *username, *logenv, *tty;
>   
>   int
>   main(argc, argv)
> ***************
> *** 126,132 ****
>   	struct utmp utmp;
>   	int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
>   	uid_t uid;
> ! 	char *domain, *p, *salt, *ttyn;
>   	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
>   	char localhost[MAXHOSTNAMELEN];
>   
> --- 127,133 ----
>   	struct utmp utmp;
>   	int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
>   	uid_t uid;
> ! 	char *domain, *p, *salt, *ttyn, *val;
>   	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
>   	char localhost[MAXHOSTNAMELEN];
>   
> ***************
> *** 174,187 ****
>   			if (!uid)
>   				syslog(LOG_ERR, "invalid flag %c", ch);
>   			(void)fprintf(stderr,
> ! 			    "usage: login [-fp] [-h hostname] [username]\n");
>   			exit(1);
>   		}
>   	argc -= optind;
>   	argv += optind;
>   
>   	if (*argv) {
> ! 		username = *argv;
>   		ask = 0;
>   	} else
>   		ask = 1;
> --- 175,194 ----
>   			if (!uid)
>   				syslog(LOG_ERR, "invalid flag %c", ch);
>   			(void)fprintf(stderr,
> ! 			    "usage: login [-fp] [-h hostname] [username] [envir
on]\n");
>   			exit(1);
>   		}
>   	argc -= optind;
>   	argv += optind;
>   
>   	if (*argv) {
> ! 		nbuf[0]='\0';
> ! 		for (cnt = 0; cnt < argc; cnt++ ) {
> ! 			if (nbuf[0])
> ! 				strncat(nbuf," ",sizeof(nbuf)-strlen(nbuf)-1);
> ! 			strncat(nbuf,argv[cnt],sizeof(nbuf)-strlen(nbuf)-1);
> ! 		}
> ! 		username=nbuf;
>   		ask = 0;
>   	} else
>   		ask = 1;
> ***************
> *** 208,213 ****
> --- 215,223 ----
>   			getloginname();
>   		}
>   		rootlogin = 0;
> + 		if ((logenv = strchr(username, ' ')) != NULL) {
> + 			*logenv++ = '\0';
> + 		}
>   #ifdef	KERBEROS
>   		if ((instance = strchr(username, '.')) != NULL) {
>   			if (strncmp(instance, ".root", 5) == 0)
> ***************
> *** 394,399 ****
> --- 404,414 ----
>   	/* Destroy environment unless user has requested its preservation. */
>   	if (!pflag)
>   		environ = envinit;
> + 	for (p = logenv; p != NULL; ) {
> + 		while ((val = strsep(&p," \t")) != NULL && *val == '\0');
> + 		if (strncasecmp(val,"PATH=",5) != 0)
> + 			putenv(val);
> + 	}
>   	(void)setenv("HOME", pwd->pw_dir, 1);
>   	(void)setenv("SHELL", pwd->pw_shell, 1);
>   	if (term[0] == '\0')
> ***************
> *** 476,486 ****
>   	return strcmp(crypt(p, salt), passwd);
>   }
>   
> - #if defined(KERBEROS) || defined(KERBEROS5)
> - #define	NBUFSIZ		(UT_NAMESIZE + 1 + 5)	/* .root suffix */
> - #else
> - #define	NBUFSIZ		(UT_NAMESIZE + 1)
> - #endif
>   
>   #if defined(KERBEROS) || defined(KERBEROS5)
>   /*
> --- 491,496 ----
> ***************
> *** 517,523 ****
>   {
>   	int ch;
>   	char *p;
> - 	static char nbuf[NBUFSIZ];
>   
>   	for (;;) {
>   		(void)printf("login: ");
> --- 527,532 ----
> ***************
> *** 526,532 ****
>   				badlogin(username);
>   				exit(0);
>   			}
> ! 			if (p < nbuf + (NBUFSIZ - 1))
>   				*p++ = ch;
>   		}
>   		if (p > nbuf)
> --- 535,541 ----
>   				badlogin(username);
>   				exit(0);
>   			}
> ! 			if (p < nbuf + (BUFSIZ - 1))
>   				*p++ = ch;
>   		}
>   		if (p > nbuf)
> >Audit-Trail:
> >Unformatted: