(no message)
[unix-history] / usr / src / usr.bin / su / su.c
CommitLineData
31e00b32
DF
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
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
13dd8b1d 13#ifndef lint
31e00b32
DF
14static char sccsid[] = "@(#)su.c 5.1 (Berkeley) %G%";
15#endif not lint
13dd8b1d 16
3a265c7a
BJ
17#include <stdio.h>
18#include <pwd.h>
b3d7f31f 19#include <grp.h>
d3d53c7f 20#include <syslog.h>
4f4c2c68
SL
21#include <sys/types.h>
22#include <sys/time.h>
23#include <sys/resource.h>
3a265c7a 24
4f4c2c68
SL
25char userbuf[16] = "USER=";
26char homebuf[128] = "HOME=";
27char shellbuf[128] = "SHELL=";
28char pathbuf[128] = "PATH=:/usr/ucb:/bin:/usr/bin";
29char *cleanenv[] = { userbuf, homebuf, shellbuf, pathbuf, 0, 0 };
30char *user = "root";
31char *shell = "/bin/sh";
32int fulllogin;
33int fastlogin;
34
35extern char **environ;
b3d7f31f 36struct passwd *pwd;
3a265c7a
BJ
37char *crypt();
38char *getpass();
4f4c2c68 39char *getenv();
3a265c7a
BJ
40
41main(argc,argv)
13dd8b1d 42 int argc;
4f4c2c68 43 char *argv[];
3a265c7a 44{
3a265c7a 45 char *password;
a8a168db
RC
46 char buf[1000];
47 FILE *fp;
3a265c7a 48
4f4c2c68
SL
49again:
50 if (argc > 1 && strcmp(argv[1], "-f") == 0) {
51 fastlogin++;
52 argc--, argv++;
53 goto again;
54 }
55 if (argc > 1 && strcmp(argv[1], "-") == 0) {
56 fulllogin++;
57 argc--, argv++;
58 goto again;
59 }
60 if (argc > 1 && argv[1][0] != '-') {
61 user = argv[1];
62 argc--, argv++;
63 }
96f93d9e
RC
64 if ((pwd = getpwuid(getuid())) == NULL) {
65 fprintf(stderr, "Who are you?\n");
66 exit(1);
67 }
68 strcpy(buf, pwd->pw_name);
69 if ((pwd = getpwnam(user)) == NULL) {
70 fprintf(stderr, "Unknown login: %s\n", user);
71 exit(1);
72 }
73 /*
74 * Only allow those in group zero to su to root.
75 */
76 if (pwd->pw_uid == 0) {
b3d7f31f
RC
77 struct group *gr;
78 int i;
79
b3d7f31f
RC
80 if ((gr = getgrgid(0)) != NULL) {
81 for (i = 0; gr->gr_mem[i] != NULL; i++)
96f93d9e 82 if (strcmp(buf, gr->gr_mem[i]) == 0)
a8a168db 83 goto userok;
96f93d9e
RC
84 fprintf(stderr, "You do not have permission to su %s\n",
85 user);
a8a168db
RC
86 exit(1);
87 }
88 userok:
4f4c2c68 89 setpriority(PRIO_PROCESS, 0, -2);
a8a168db
RC
90 }
91
13dd8b1d 92 if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
3a265c7a
BJ
93 goto ok;
94 password = getpass("Password:");
13dd8b1d 95 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
4f4c2c68 96 fprintf(stderr, "Sorry\n");
13dd8b1d 97 if (pwd->pw_uid == 0) {
3a265c7a
BJ
98 FILE *console = fopen("/dev/console", "w");
99 if (console != NULL) {
13dd8b1d
SL
100 fprintf(console, "BADSU: %s %s\r\n",
101 getlogin(), ttyname(2));
3a265c7a
BJ
102 fclose(console);
103 }
104 }
105 exit(2);
106 }
107ok:
108 endpwent();
13dd8b1d 109 if (pwd->pw_uid == 0) {
d3d53c7f
RC
110 openlog("su", 0, 0);
111 syslog(LOG_SECURITY, "%s on %s", getlogin(), ttyname(2));
112 closelog();
3a265c7a 113 }
13dd8b1d
SL
114 if (setgid(pwd->pw_gid) < 0) {
115 perror("su: setgid");
116 exit(3);
117 }
4f4c2c68 118 if (initgroups(user, pwd->pw_gid)) {
13dd8b1d
SL
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 }
3a265c7a
BJ
126 if (pwd->pw_shell && *pwd->pw_shell)
127 shell = pwd->pw_shell;
4f4c2c68
SL
128 if (fulllogin) {
129 cleanenv[4] = getenv("TERM");
130 environ = cleanenv;
131 }
c399698a
SL
132 if (strcmp(user, "root"))
133 setenv("USER", pwd->pw_name, userbuf);
4f4c2c68
SL
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);
3a265c7a
BJ
151}
152
4f4c2c68
SL
153setenv(ename, eval, buf)
154 char *ename, *eval, *buf;
3a265c7a
BJ
155{
156 register char *cp, *dp;
157 register char **ep = environ;
3a265c7a 158
4f4c2c68
SL
159 /*
160 * this assumes an environment variable "ename" already exists
161 */
3a265c7a 162 while (dp = *ep++) {
4f4c2c68 163 for (cp = ename; *cp == *dp && *cp; cp++, dp++)
3a265c7a
BJ
164 continue;
165 if (*cp == 0 && (*dp == '=' || *dp == 0)) {
4f4c2c68
SL
166 strcat(buf, eval);
167 *--ep = buf;
3a265c7a
BJ
168 return;
169 }
170 }
171}
172
4f4c2c68
SL
173char *
174getenv(ename)
175 char *ename;
3a265c7a
BJ
176{
177 register char *cp, *dp;
178 register char **ep = environ;
3a265c7a
BJ
179
180 while (dp = *ep++) {
4f4c2c68 181 for (cp = ename; *cp == *dp && *cp; cp++, dp++)
3a265c7a 182 continue;
4f4c2c68
SL
183 if (*cp == 0 && (*dp == '=' || *dp == 0))
184 return (*--ep);
3a265c7a 185 }
4f4c2c68 186 return ((char *)0);
3a265c7a 187}