deprecate LOG_NOWAIT
[unix-history] / usr / src / usr.bin / su / su.c
CommitLineData
31e00b32 1/*
7d5e1706
KB
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31e00b32
DF
16 */
17
18#ifndef lint
19char copyright[] =
7d5e1706 20"@(#) Copyright (c) 1988 The Regents of the University of California.\n\
31e00b32 21 All rights reserved.\n";
7d5e1706 22#endif /* not lint */
31e00b32 23
13dd8b1d 24#ifndef lint
3a7a366d 25static char sccsid[] = "@(#)su.c 5.12 (Berkeley) %G%";
7d5e1706 26#endif /* not lint */
13dd8b1d 27
a8d8c335 28#include <sys/param.h>
4f4c2c68
SL
29#include <sys/time.h>
30#include <sys/resource.h>
7d5e1706
KB
31#include <syslog.h>
32#include <stdio.h>
33#include <pwd.h>
34#include <grp.h>
3a7a366d 35#include "pathnames.h"
3a265c7a 36
7d5e1706 37main(argc, argv)
13dd8b1d 38 int argc;
7d5e1706 39 char **argv;
3a265c7a 40{
7d5e1706
KB
41 extern char **environ;
42 extern int errno, optind;
7d5e1706
KB
43 register struct passwd *pwd;
44 register char *p, **g;
45 struct group *gr;
a8d8c335 46 uid_t ruid, getuid();
6964f298 47 int asme, ch, fulllogin, fastlogin, prio;
a8d8c335 48 enum { UNSET, YES, NO } iscsh = UNSET;
6964f298 49 char *user, *shell, *username, *cleanenv[2], *nargv[4], **np;
a8d8c335
KB
50 char namebuf[50], shellbuf[MAXPATHLEN];
51 char *crypt(), *getpass(), *getenv(), *getlogin(), *rindex(), *strcpy();
3a265c7a 52
6964f298
KB
53 np = &nargv[3];
54 *np-- = NULL;
55 asme = fulllogin = fastlogin = 0;
56 while ((ch = getopt(argc, argv, "-flm")) != EOF)
7d5e1706 57 switch((char)ch) {
a8d8c335
KB
58 case 'f':
59 fastlogin = 1;
60 break;
7d5e1706
KB
61 case '-':
62 case 'l':
63 fulllogin = 1;
64 break;
6964f298
KB
65 case 'm':
66 asme = 1;
67 break;
7d5e1706
KB
68 case '?':
69 default:
3130bef4 70 fprintf(stderr, "usage: su [-flm] [login]\n");
7d5e1706
KB
71 exit(1);
72 }
73 argv += optind;
da31c6da 74
6964f298
KB
75 errno = 0;
76 prio = getpriority(PRIO_PROCESS, 0);
77 if (errno)
78 prio = 0;
79 (void)setpriority(PRIO_PROCESS, 0, -2);
80
81 /* get current login name and shell */
a8d8c335 82 if ((pwd = getpwuid(ruid = getuid())) == NULL) {
7d5e1706 83 fprintf(stderr, "su: who are you?\n");
96f93d9e
RC
84 exit(1);
85 }
a8d8c335 86 username = strcpy(namebuf, pwd->pw_name);
6964f298 87 if (asme)
a8d8c335
KB
88 if (pwd->pw_shell && *pwd->pw_shell)
89 shell = strcpy(shellbuf, pwd->pw_shell);
90 else {
3a7a366d 91 shell = _PATH_BSHELL;
a8d8c335
KB
92 iscsh = NO;
93 }
7d5e1706 94
6964f298
KB
95 /* get target login information */
96 user = *argv ? *argv : "root";
96f93d9e 97 if ((pwd = getpwnam(user)) == NULL) {
7d5e1706 98 fprintf(stderr, "su: unknown login %s\n", user);
96f93d9e
RC
99 exit(1);
100 }
7d5e1706
KB
101
102 /* only allow those in group zero to su to root. */
a8d8c335 103 if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0)))
7d5e1706
KB
104 for (g = gr->gr_mem;; ++g) {
105 if (!*g) {
106 fprintf(stderr, "su: you are not in the correct group to su %s.\n", user);
107 exit(1);
108 }
109 if (!strcmp(username, *g))
110 break;
a8a168db 111 }
a8a168db 112
6964f298
KB
113 /* if target requires a password, verify it */
114 if (ruid && *pwd->pw_passwd) {
7d5e1706
KB
115 p = getpass("Password:");
116 if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
117 fprintf(stderr, "Sorry\n");
118 if (pwd->pw_uid == 0)
6964f298 119 syslog(LOG_CRIT|LOG_AUTH, "su: BAD SU %s on %s", username, ttyname(2));
7d5e1706 120 exit(1);
3a265c7a 121 }
3a265c7a 122 }
a8d8c335 123
6fad2abb
KB
124 if (asme) {
125 /* if asme and non-standard target shell, must be root */
126 if (!chshell(pwd->pw_shell) && ruid) {
127 fprintf(stderr, "su: Permission denied.\n");
128 exit(1);
a8d8c335 129 }
6fad2abb
KB
130 }
131 else if (pwd->pw_shell && *pwd->pw_shell) {
132 shell = pwd->pw_shell;
133 iscsh = UNSET;
134 } else {
3a7a366d 135 shell = _PATH_BSHELL;
6fad2abb
KB
136 iscsh = NO;
137 }
a8d8c335 138
6964f298 139 /* if we're forking a csh, we want to slightly muck the args */
a8d8c335
KB
140 if (iscsh == UNSET) {
141 if (p = rindex(shell, '/'))
142 ++p;
143 else
144 p = shell;
145 iscsh = strcmp(p, "csh") ? NO : YES;
146 }
147
6964f298 148 /* set permissions */
13dd8b1d
SL
149 if (setgid(pwd->pw_gid) < 0) {
150 perror("su: setgid");
7d5e1706 151 exit(1);
13dd8b1d 152 }
4f4c2c68 153 if (initgroups(user, pwd->pw_gid)) {
13dd8b1d 154 fprintf(stderr, "su: initgroups failed\n");
7d5e1706 155 exit(1);
13dd8b1d
SL
156 }
157 if (setuid(pwd->pw_uid) < 0) {
158 perror("su: setuid");
7d5e1706 159 exit(1);
13dd8b1d 160 }
6964f298
KB
161
162 if (!asme) {
163 if (fulllogin) {
164 p = getenv("TERM");
3a7a366d 165 cleanenv[0] = _PATH_SEARCHPATH;
6964f298
KB
166 cleanenv[1] = NULL;
167 environ = cleanenv;
168 (void)setenv("TERM", p, 1);
169 if (chdir(pwd->pw_dir) < 0) {
170 fprintf(stderr, "su: no directory\n");
171 exit(1);
172 }
173 }
174 if (fulllogin || pwd->pw_uid)
175 (void)setenv("USER", pwd->pw_name, 1);
a8d8c335
KB
176 (void)setenv("HOME", pwd->pw_dir, 1);
177 (void)setenv("SHELL", shell, 1);
3a265c7a 178 }
3a265c7a 179
6964f298
KB
180 if (iscsh == YES) {
181 if (fastlogin)
182 *np-- = "-f";
183 if (asme)
184 *np-- = "-m";
185 }
a8d8c335
KB
186
187 /* csh strips the first character... */
6964f298 188 *np = fulllogin ? "-su" : iscsh == YES ? "_su" : "su";
7d5e1706
KB
189
190 if (pwd->pw_uid == 0)
a8d8c335
KB
191 syslog(LOG_NOTICE|LOG_AUTH, "su: %s on %s",
192 username, ttyname(2));
7d5e1706
KB
193
194 (void)setpriority(PRIO_PROCESS, 0, prio);
195
6964f298 196 execv(shell, np);
a8d8c335 197 fprintf(stderr, "su: no shell.\n");
7d5e1706 198 exit(1);
3a265c7a 199}
7b34c4f8
KB
200
201chshell(sh)
202 char *sh;
203{
204 char *cp, *getusershell();
205
206 while ((cp = getusershell()) != NULL)
207 if (!strcmp(cp, sh))
208 return(1);
209 return(0);
210}