date and time created 88/09/26 15:06:04 by bostic
[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
a8d8c335 25static char sccsid[] = "@(#)su.c 5.7 (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>
3a265c7a 35
7d5e1706 36main(argc, argv)
13dd8b1d 37 int argc;
7d5e1706 38 char **argv;
3a265c7a 39{
7d5e1706
KB
40 extern char **environ;
41 extern int errno, optind;
7d5e1706
KB
42 register struct passwd *pwd;
43 register char *p, **g;
44 struct group *gr;
a8d8c335 45 uid_t ruid, getuid();
7d5e1706 46 int ch, fulllogin, fastlogin, prio;
a8d8c335
KB
47 enum { UNSET, YES, NO } iscsh = UNSET;
48 char *user, *shell, *username, *cleanenv[2];
49 char namebuf[50], shellbuf[MAXPATHLEN];
50 char *crypt(), *getpass(), *getenv(), *getlogin(), *rindex(), *strcpy();
3a265c7a 51
7d5e1706 52 fulllogin = fastlogin = 0;
7d5e1706
KB
53 while ((ch = getopt(argc, argv, "-fl")) != EOF)
54 switch((char)ch) {
a8d8c335
KB
55 case 'f':
56 fastlogin = 1;
57 break;
7d5e1706
KB
58 case '-':
59 case 'l':
60 fulllogin = 1;
61 break;
7d5e1706
KB
62 case '?':
63 default:
64 fprintf(stderr, "usage: su [-fl] [login]\n");
65 exit(1);
66 }
67 argv += optind;
da31c6da 68
a8d8c335 69 if ((pwd = getpwuid(ruid = getuid())) == NULL) {
7d5e1706 70 fprintf(stderr, "su: who are you?\n");
96f93d9e
RC
71 exit(1);
72 }
a8d8c335
KB
73 username = strcpy(namebuf, pwd->pw_name);
74 if (!fulllogin)
75 if (pwd->pw_shell && *pwd->pw_shell)
76 shell = strcpy(shellbuf, pwd->pw_shell);
77 else {
78 shell = "/bin/sh";
79 iscsh = NO;
80 }
7d5e1706 81
a8d8c335 82 user = *argv ? *argv++ : "root";
96f93d9e 83 if ((pwd = getpwnam(user)) == NULL) {
7d5e1706 84 fprintf(stderr, "su: unknown login %s\n", user);
96f93d9e
RC
85 exit(1);
86 }
7d5e1706
KB
87
88 /* only allow those in group zero to su to root. */
a8d8c335 89 if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0)))
7d5e1706
KB
90 for (g = gr->gr_mem;; ++g) {
91 if (!*g) {
92 fprintf(stderr, "su: you are not in the correct group to su %s.\n", user);
93 exit(1);
94 }
95 if (!strcmp(username, *g))
96 break;
a8a168db 97 }
a8a168db 98
7d5e1706
KB
99 errno = 0;
100 prio = getpriority(PRIO_PROCESS, 0);
101 if (errno)
102 prio = 0;
103 (void)setpriority(PRIO_PROCESS, 0, -2);
104
105 if ((p = getlogin()) && *p)
106 username = p;
107
a8d8c335 108 if (*pwd->pw_passwd && ruid) {
7d5e1706
KB
109 p = getpass("Password:");
110 if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) {
111 fprintf(stderr, "Sorry\n");
112 if (pwd->pw_uid == 0)
a8d8c335
KB
113 syslog(LOG_CRIT|LOG_AUTH, "su: BAD SU %s on %s",
114 username, ttyname(2));
7d5e1706 115 exit(1);
3a265c7a 116 }
3a265c7a 117 }
a8d8c335
KB
118
119 /* if target user has no password, or fulllogin, use their shell */
120 if (!*pwd->pw_passwd || fulllogin)
121 if (pwd->pw_shell && *pwd->pw_shell) {
122 shell = pwd->pw_shell;
123 iscsh = UNSET;
124 } else {
125 shell = "/bin/sh";
126 iscsh = NO;
127 }
128
129 if (iscsh == UNSET) {
130 if (p = rindex(shell, '/'))
131 ++p;
132 else
133 p = shell;
134 iscsh = strcmp(p, "csh") ? NO : YES;
135 }
136
13dd8b1d
SL
137 if (setgid(pwd->pw_gid) < 0) {
138 perror("su: setgid");
7d5e1706 139 exit(1);
13dd8b1d 140 }
4f4c2c68 141 if (initgroups(user, pwd->pw_gid)) {
13dd8b1d 142 fprintf(stderr, "su: initgroups failed\n");
7d5e1706 143 exit(1);
13dd8b1d
SL
144 }
145 if (setuid(pwd->pw_uid) < 0) {
146 perror("su: setuid");
7d5e1706 147 exit(1);
13dd8b1d 148 }
4f4c2c68 149 if (fulllogin) {
7d5e1706
KB
150 p = getenv("TERM");
151 cleanenv[0] = "PATH=:/usr/ucb:/bin:/usr/bin";
152 cleanenv[1] = NULL;
4f4c2c68 153 environ = cleanenv;
a8d8c335
KB
154 (void)setenv("HOME", pwd->pw_dir, 1);
155 (void)setenv("SHELL", shell, 1);
7d5e1706 156 (void)setenv("TERM", p, 1);
a8d8c335 157 (void)setenv("USER", pwd->pw_name, 1);
4f4c2c68 158 if (chdir(pwd->pw_dir) < 0) {
7d5e1706
KB
159 fprintf(stderr, "su: no directory\n");
160 exit(1);
3a265c7a
BJ
161 }
162 }
3a265c7a 163
a8d8c335
KB
164 if (fastlogin && iscsh == YES)
165 *--argv = "-f";
166
167 /* csh strips the first character... */
168 *--argv = fulllogin ? "-su" : iscsh == YES ? "_su" : "su";
7d5e1706
KB
169
170 if (pwd->pw_uid == 0)
a8d8c335
KB
171 syslog(LOG_NOTICE|LOG_AUTH, "su: %s on %s",
172 username, ttyname(2));
7d5e1706
KB
173
174 (void)setpriority(PRIO_PROCESS, 0, prio);
175
176 execv(shell, argv);
a8d8c335 177 fprintf(stderr, "su: no shell.\n");
7d5e1706 178 exit(1);
3a265c7a 179}