facilities in syslog
[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.3 (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
49 openlog("su", LOG_ODELAY, LOG_AUTH);
50
51again:
52 if (argc > 1 && strcmp(argv[1], "-f") == 0) {
53 fastlogin++;
54 argc--, argv++;
55 goto again;
56 }
57 if (argc > 1 && strcmp(argv[1], "-") == 0) {
58 fulllogin++;
59 argc--, argv++;
60 goto again;
61 }
62 if (argc > 1 && argv[1][0] != '-') {
63 user = argv[1];
64 argc--, argv++;
65 }
66 if ((pwd = getpwuid(getuid())) == NULL) {
67 fprintf(stderr, "Who are you?\n");
68 exit(1);
69 }
70 strcpy(buf, pwd->pw_name);
71 if ((pwd = getpwnam(user)) == NULL) {
72 fprintf(stderr, "Unknown login: %s\n", user);
73 exit(1);
74 }
75 /*
76 * Only allow those in group zero to su to root.
77 */
78 if (pwd->pw_uid == 0) {
79 struct group *gr;
80 int i;
81
82 if ((gr = getgrgid(0)) != NULL) {
83 for (i = 0; gr->gr_mem[i] != NULL; i++)
84 if (strcmp(buf, gr->gr_mem[i]) == 0)
85 goto userok;
86 fprintf(stderr, "You do not have permission to su %s\n",
87 user);
88 exit(1);
89 }
90 userok:
91 setpriority(PRIO_PROCESS, 0, -2);
92 }
93
94 if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
95 goto ok;
96 password = getpass("Password:");
97 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
98 fprintf(stderr, "Sorry\n");
99 if (pwd->pw_uid == 0) {
100 syslog(LOG_CRIT, "BAD SU %s on %s",
101 getlogin(), ttyname(2));
102 }
103 exit(2);
104 }
105ok:
106 endpwent();
107 if (pwd->pw_uid == 0) {
108 syslog(LOG_NOTICE, "%s on %s", getlogin(), ttyname(2));
109 closelog();
110 }
111 if (setgid(pwd->pw_gid) < 0) {
112 perror("su: setgid");
113 exit(3);
114 }
115 if (initgroups(user, pwd->pw_gid)) {
116 fprintf(stderr, "su: initgroups failed\n");
117 exit(4);
118 }
119 if (setuid(pwd->pw_uid) < 0) {
120 perror("su: setuid");
121 exit(5);
122 }
123 if (pwd->pw_shell && *pwd->pw_shell)
124 shell = pwd->pw_shell;
125 if (fulllogin) {
126 cleanenv[4] = getenv("TERM");
127 environ = cleanenv;
128 }
129 if (strcmp(user, "root"))
130 setenv("USER", pwd->pw_name, userbuf);
131 setenv("SHELL", shell, shellbuf);
132 setenv("HOME", pwd->pw_dir, homebuf);
133 setpriority(PRIO_PROCESS, 0, 0);
134 if (fastlogin) {
135 *argv-- = "-f";
136 *argv = "su";
137 } else if (fulllogin) {
138 if (chdir(pwd->pw_dir) < 0) {
139 fprintf(stderr, "No directory\n");
140 exit(6);
141 }
142 *argv = "-su";
143 } else
144 *argv = "su";
145 execv(shell, argv);
146 fprintf(stderr, "No shell\n");
147 exit(7);
148}
149
150setenv(ename, eval, buf)
151 char *ename, *eval, *buf;
152{
153 register char *cp, *dp;
154 register char **ep = environ;
155
156 /*
157 * this assumes an environment variable "ename" already exists
158 */
159 while (dp = *ep++) {
160 for (cp = ename; *cp == *dp && *cp; cp++, dp++)
161 continue;
162 if (*cp == 0 && (*dp == '=' || *dp == 0)) {
163 strcat(buf, eval);
164 *--ep = buf;
165 return;
166 }
167 }
168}
169
170char *
171getenv(ename)
172 char *ename;
173{
174 register char *cp, *dp;
175 register char **ep = environ;
176
177 while (dp = *ep++) {
178 for (cp = ename; *cp == *dp && *cp; cp++, dp++)
179 continue;
180 if (*cp == 0 && (*dp == '=' || *dp == 0))
181 return (*--ep);
182 }
183 return ((char *)0);
184}