Fix bug when moving tableau pile to empty slot (don't allow it).
[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
da31c6da 14static char sccsid[] = "@(#)su.c 5.3 (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();
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
da31c6da
EA
49 openlog("su", LOG_ODELAY, LOG_AUTH);
50
4f4c2c68
SL
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 }
96f93d9e
RC
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) {
b3d7f31f
RC
79 struct group *gr;
80 int i;
81
b3d7f31f
RC
82 if ((gr = getgrgid(0)) != NULL) {
83 for (i = 0; gr->gr_mem[i] != NULL; i++)
96f93d9e 84 if (strcmp(buf, gr->gr_mem[i]) == 0)
a8a168db 85 goto userok;
96f93d9e
RC
86 fprintf(stderr, "You do not have permission to su %s\n",
87 user);
a8a168db
RC
88 exit(1);
89 }
90 userok:
4f4c2c68 91 setpriority(PRIO_PROCESS, 0, -2);
a8a168db
RC
92 }
93
13dd8b1d 94 if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
3a265c7a
BJ
95 goto ok;
96 password = getpass("Password:");
13dd8b1d 97 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
4f4c2c68 98 fprintf(stderr, "Sorry\n");
13dd8b1d 99 if (pwd->pw_uid == 0) {
da31c6da 100 syslog(LOG_CRIT, "BAD SU %s on %s",
13dd8b1d 101 getlogin(), ttyname(2));
3a265c7a
BJ
102 }
103 exit(2);
104 }
105ok:
106 endpwent();
13dd8b1d 107 if (pwd->pw_uid == 0) {
da31c6da 108 syslog(LOG_NOTICE, "%s on %s", getlogin(), ttyname(2));
d3d53c7f 109 closelog();
3a265c7a 110 }
13dd8b1d
SL
111 if (setgid(pwd->pw_gid) < 0) {
112 perror("su: setgid");
113 exit(3);
114 }
4f4c2c68 115 if (initgroups(user, pwd->pw_gid)) {
13dd8b1d
SL
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 }
3a265c7a
BJ
123 if (pwd->pw_shell && *pwd->pw_shell)
124 shell = pwd->pw_shell;
4f4c2c68
SL
125 if (fulllogin) {
126 cleanenv[4] = getenv("TERM");
127 environ = cleanenv;
128 }
c399698a
SL
129 if (strcmp(user, "root"))
130 setenv("USER", pwd->pw_name, userbuf);
4f4c2c68
SL
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);
3a265c7a
BJ
148}
149
4f4c2c68
SL
150setenv(ename, eval, buf)
151 char *ename, *eval, *buf;
3a265c7a
BJ
152{
153 register char *cp, *dp;
154 register char **ep = environ;
3a265c7a 155
4f4c2c68
SL
156 /*
157 * this assumes an environment variable "ename" already exists
158 */
3a265c7a 159 while (dp = *ep++) {
4f4c2c68 160 for (cp = ename; *cp == *dp && *cp; cp++, dp++)
3a265c7a
BJ
161 continue;
162 if (*cp == 0 && (*dp == '=' || *dp == 0)) {
4f4c2c68
SL
163 strcat(buf, eval);
164 *--ep = buf;
3a265c7a
BJ
165 return;
166 }
167 }
168}
169
4f4c2c68
SL
170char *
171getenv(ename)
172 char *ename;
3a265c7a
BJ
173{
174 register char *cp, *dp;
175 register char **ep = environ;
3a265c7a
BJ
176
177 while (dp = *ep++) {
4f4c2c68 178 for (cp = ename; *cp == *dp && *cp; cp++, dp++)
3a265c7a 179 continue;
4f4c2c68
SL
180 if (*cp == 0 && (*dp == '=' || *dp == 0))
181 return (*--ep);
3a265c7a 182 }
4f4c2c68 183 return ((char *)0);
3a265c7a 184}