(no message)
[unix-history] / usr / src / usr.bin / su / su.c
... / ...
CommitLineData
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
13#ifndef lint
14static char sccsid[] = "@(#)su.c 5.1 (Berkeley) %G%";
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
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;
36struct passwd *pwd;
37char *crypt();
38char *getpass();
39char *getenv();
40
41main(argc,argv)
42 int argc;
43 char *argv[];
44{
45 char *password;
46 char buf[1000];
47 FILE *fp;
48
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 }
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) {
77 struct group *gr;
78 int i;
79
80 if ((gr = getgrgid(0)) != NULL) {
81 for (i = 0; gr->gr_mem[i] != NULL; i++)
82 if (strcmp(buf, gr->gr_mem[i]) == 0)
83 goto userok;
84 fprintf(stderr, "You do not have permission to su %s\n",
85 user);
86 exit(1);
87 }
88 userok:
89 setpriority(PRIO_PROCESS, 0, -2);
90 }
91
92 if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
93 goto ok;
94 password = getpass("Password:");
95 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
96 fprintf(stderr, "Sorry\n");
97 if (pwd->pw_uid == 0) {
98 FILE *console = fopen("/dev/console", "w");
99 if (console != NULL) {
100 fprintf(console, "BADSU: %s %s\r\n",
101 getlogin(), ttyname(2));
102 fclose(console);
103 }
104 }
105 exit(2);
106 }
107ok:
108 endpwent();
109 if (pwd->pw_uid == 0) {
110 openlog("su", 0, 0);
111 syslog(LOG_SECURITY, "%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 (strcmp(user, "root"))
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
153setenv(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
173char *
174getenv(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}