xref: /original-bsd/usr.bin/su/su.c (revision 241757c4)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif not lint
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)su.c	5.5 (Berkeley) 01/18/87";
15 #endif not lint
16 
17 #include <stdio.h>
18 #include <pwd.h>
19 #include <grp.h>
20 #include <syslog.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/resource.h>
24 
25 char	userbuf[16]	= "USER=";
26 char	homebuf[128]	= "HOME=";
27 char	shellbuf[128]	= "SHELL=";
28 char	pathbuf[128]	= "PATH=:/usr/ucb:/bin:/usr/bin";
29 char	*cleanenv[] = { userbuf, homebuf, shellbuf, pathbuf, 0, 0 };
30 char	*user = "root";
31 char	*shell = "/bin/sh";
32 int	fulllogin;
33 int	fastlogin;
34 
35 extern char	**environ;
36 struct	passwd *pwd;
37 char	*crypt();
38 char	*getpass();
39 char	*getenv();
40 char	*getlogin();
41 
42 main(argc,argv)
43 	int argc;
44 	char *argv[];
45 {
46 	char *password;
47 	char buf[1000];
48 	FILE *fp;
49 	register char *p;
50 
51 	openlog("su", LOG_ODELAY, LOG_AUTH);
52 
53 again:
54 	if (argc > 1 && strcmp(argv[1], "-f") == 0) {
55 		fastlogin++;
56 		argc--, argv++;
57 		goto again;
58 	}
59 	if (argc > 1 && strcmp(argv[1], "-") == 0) {
60 		fulllogin++;
61 		argc--, argv++;
62 		goto again;
63 	}
64 	if (argc > 1 && argv[1][0] != '-') {
65 		user = argv[1];
66 		argc--, argv++;
67 	}
68 	if ((pwd = getpwuid(getuid())) == NULL) {
69 		fprintf(stderr, "Who are you?\n");
70 		exit(1);
71 	}
72 	strcpy(buf, pwd->pw_name);
73 	if ((pwd = getpwnam(user)) == NULL) {
74 		fprintf(stderr, "Unknown login: %s\n", user);
75 		exit(1);
76 	}
77 	/*
78 	 * Only allow those in group zero to su to root.
79 	 */
80 	if (pwd->pw_uid == 0) {
81 		struct	group *gr;
82 		int i;
83 
84 		if ((gr = getgrgid(0)) != NULL) {
85 			for (i = 0; gr->gr_mem[i] != NULL; i++)
86 				if (strcmp(buf, gr->gr_mem[i]) == 0)
87 					goto userok;
88 			fprintf(stderr, "You do not have permission to su %s\n",
89 				user);
90 			exit(1);
91 		}
92 	userok:
93 		setpriority(PRIO_PROCESS, 0, -2);
94 	}
95 
96 #define Getlogin()  (((p = getlogin()) && *p) ? p : buf)
97 	if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
98 		goto ok;
99 	password = getpass("Password:");
100 	if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
101 		fprintf(stderr, "Sorry\n");
102 		if (pwd->pw_uid == 0) {
103 			syslog(LOG_CRIT, "BAD SU %s on %s",
104 					Getlogin(), ttyname(2));
105 		}
106 		exit(2);
107 	}
108 ok:
109 	endpwent();
110 	if (pwd->pw_uid == 0) {
111 		syslog(LOG_NOTICE, "%s on %s", Getlogin(), ttyname(2));
112 		closelog();
113 	}
114 	if (setgid(pwd->pw_gid) < 0) {
115 		perror("su: setgid");
116 		exit(3);
117 	}
118 	if (initgroups(user, pwd->pw_gid)) {
119 		fprintf(stderr, "su: initgroups failed\n");
120 		exit(4);
121 	}
122 	if (setuid(pwd->pw_uid) < 0) {
123 		perror("su: setuid");
124 		exit(5);
125 	}
126 	if (pwd->pw_shell && *pwd->pw_shell)
127 		shell = pwd->pw_shell;
128 	if (fulllogin) {
129 		cleanenv[4] = getenv("TERM");
130 		environ = cleanenv;
131 	}
132 	if (fulllogin || strcmp(user, "root") != 0)
133 		setenv("USER", pwd->pw_name, userbuf);
134 	setenv("SHELL", shell, shellbuf);
135 	setenv("HOME", pwd->pw_dir, homebuf);
136 	setpriority(PRIO_PROCESS, 0, 0);
137 	if (fastlogin) {
138 		*argv-- = "-f";
139 		*argv = "su";
140 	} else if (fulllogin) {
141 		if (chdir(pwd->pw_dir) < 0) {
142 			fprintf(stderr, "No directory\n");
143 			exit(6);
144 		}
145 		*argv = "-su";
146 	} else
147 		*argv = "su";
148 	execv(shell, argv);
149 	fprintf(stderr, "No shell\n");
150 	exit(7);
151 }
152 
153 setenv(ename, eval, buf)
154 	char *ename, *eval, *buf;
155 {
156 	register char *cp, *dp;
157 	register char **ep = environ;
158 
159 	/*
160 	 * this assumes an environment variable "ename" already exists
161 	 */
162 	while (dp = *ep++) {
163 		for (cp = ename; *cp == *dp && *cp; cp++, dp++)
164 			continue;
165 		if (*cp == 0 && (*dp == '=' || *dp == 0)) {
166 			strcat(buf, eval);
167 			*--ep = buf;
168 			return;
169 		}
170 	}
171 }
172 
173 char *
174 getenv(ename)
175 	char *ename;
176 {
177 	register char *cp, *dp;
178 	register char **ep = environ;
179 
180 	while (dp = *ep++) {
181 		for (cp = ename; *cp == *dp && *cp; cp++, dp++)
182 			continue;
183 		if (*cp == 0 && (*dp == '=' || *dp == 0))
184 			return (*--ep);
185 	}
186 	return ((char *)0);
187 }
188