init USER on "su - root"
[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
886d2233 14static char sccsid[] = "@(#)su.c 5.5 (Berkeley) %G%";
31e00b32 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();
c1589182 40char *getlogin();
3a265c7a
BJ
41
42main(argc,argv)
13dd8b1d 43 int argc;
4f4c2c68 44 char *argv[];
3a265c7a 45{
3a265c7a 46 char *password;
a8a168db
RC
47 char buf[1000];
48 FILE *fp;
c1589182 49 register char *p;
3a265c7a 50
da31c6da
EA
51 openlog("su", LOG_ODELAY, LOG_AUTH);
52
4f4c2c68
SL
53again:
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 }
96f93d9e
RC
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) {
b3d7f31f
RC
81 struct group *gr;
82 int i;
83
b3d7f31f
RC
84 if ((gr = getgrgid(0)) != NULL) {
85 for (i = 0; gr->gr_mem[i] != NULL; i++)
96f93d9e 86 if (strcmp(buf, gr->gr_mem[i]) == 0)
a8a168db 87 goto userok;
96f93d9e
RC
88 fprintf(stderr, "You do not have permission to su %s\n",
89 user);
a8a168db
RC
90 exit(1);
91 }
92 userok:
4f4c2c68 93 setpriority(PRIO_PROCESS, 0, -2);
a8a168db
RC
94 }
95
c1589182 96#define Getlogin() (((p = getlogin()) && *p) ? p : buf)
13dd8b1d 97 if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
3a265c7a
BJ
98 goto ok;
99 password = getpass("Password:");
13dd8b1d 100 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
4f4c2c68 101 fprintf(stderr, "Sorry\n");
13dd8b1d 102 if (pwd->pw_uid == 0) {
da31c6da 103 syslog(LOG_CRIT, "BAD SU %s on %s",
c1589182 104 Getlogin(), ttyname(2));
3a265c7a
BJ
105 }
106 exit(2);
107 }
108ok:
109 endpwent();
13dd8b1d 110 if (pwd->pw_uid == 0) {
c1589182 111 syslog(LOG_NOTICE, "%s on %s", Getlogin(), ttyname(2));
d3d53c7f 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 }
886d2233 132 if (fulllogin || strcmp(user, "root") != 0)
c399698a 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}