119908Sdist /* 235489Sbostic * Copyright (c) 1988 The Regents of the University of California. 335489Sbostic * All rights reserved. 435489Sbostic * 535489Sbostic * Redistribution and use in source and binary forms are permitted 635489Sbostic * provided that the above copyright notice and this paragraph are 735489Sbostic * duplicated in all such forms and that any documentation, 835489Sbostic * advertising materials, and other materials related to such 935489Sbostic * distribution and use acknowledge that the software was developed 1035489Sbostic * by the University of California, Berkeley. The name of the 1135489Sbostic * University may not be used to endorse or promote products derived 1235489Sbostic * from this software without specific prior written permission. 1335489Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435489Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535489Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1619908Sdist */ 1719908Sdist 1810045Ssam #ifndef lint 1919908Sdist char copyright[] = 2035489Sbostic "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ 2119908Sdist All rights reserved.\n"; 2235489Sbostic #endif /* not lint */ 2310045Ssam 2419908Sdist #ifndef lint 25*35716Sbostic static char sccsid[] = "@(#)su.c 5.7 (Berkeley) 09/26/88"; 2635489Sbostic #endif /* not lint */ 2719908Sdist 28*35716Sbostic #include <sys/param.h> 2935489Sbostic #include <sys/time.h> 3035489Sbostic #include <sys/resource.h> 3135489Sbostic #include <syslog.h> 321109Sbill #include <stdio.h> 331109Sbill #include <pwd.h> 3415914Sralph #include <grp.h> 351109Sbill 3635489Sbostic main(argc, argv) 3710045Ssam int argc; 3835489Sbostic char **argv; 391109Sbill { 4035489Sbostic extern char **environ; 4135489Sbostic extern int errno, optind; 4235489Sbostic register struct passwd *pwd; 4335489Sbostic register char *p, **g; 4435489Sbostic struct group *gr; 45*35716Sbostic uid_t ruid, getuid(); 4635489Sbostic int ch, fulllogin, fastlogin, prio; 47*35716Sbostic enum { UNSET, YES, NO } iscsh = UNSET; 48*35716Sbostic char *user, *shell, *username, *cleanenv[2]; 49*35716Sbostic char namebuf[50], shellbuf[MAXPATHLEN]; 50*35716Sbostic char *crypt(), *getpass(), *getenv(), *getlogin(), *rindex(), *strcpy(); 511109Sbill 5235489Sbostic fulllogin = fastlogin = 0; 5335489Sbostic while ((ch = getopt(argc, argv, "-fl")) != EOF) 5435489Sbostic switch((char)ch) { 55*35716Sbostic case 'f': 56*35716Sbostic fastlogin = 1; 57*35716Sbostic break; 5835489Sbostic case '-': 5935489Sbostic case 'l': 6035489Sbostic fulllogin = 1; 6135489Sbostic break; 6235489Sbostic case '?': 6335489Sbostic default: 6435489Sbostic fprintf(stderr, "usage: su [-fl] [login]\n"); 6535489Sbostic exit(1); 6635489Sbostic } 6735489Sbostic argv += optind; 6835489Sbostic 69*35716Sbostic if ((pwd = getpwuid(ruid = getuid())) == NULL) { 7035489Sbostic fprintf(stderr, "su: who are you?\n"); 7116216Sralph exit(1); 7216216Sralph } 73*35716Sbostic username = strcpy(namebuf, pwd->pw_name); 74*35716Sbostic if (!fulllogin) 75*35716Sbostic if (pwd->pw_shell && *pwd->pw_shell) 76*35716Sbostic shell = strcpy(shellbuf, pwd->pw_shell); 77*35716Sbostic else { 78*35716Sbostic shell = "/bin/sh"; 79*35716Sbostic iscsh = NO; 80*35716Sbostic } 8135489Sbostic 82*35716Sbostic user = *argv ? *argv++ : "root"; 8316216Sralph if ((pwd = getpwnam(user)) == NULL) { 8435489Sbostic fprintf(stderr, "su: unknown login %s\n", user); 8516216Sralph exit(1); 8616216Sralph } 8715914Sralph 8835489Sbostic /* only allow those in group zero to su to root. */ 89*35716Sbostic if (pwd->pw_uid == 0 && (gr = getgrgid((gid_t)0))) 9035489Sbostic for (g = gr->gr_mem;; ++g) { 9135489Sbostic if (!*g) { 9235489Sbostic fprintf(stderr, "su: you are not in the correct group to su %s.\n", user); 9335489Sbostic exit(1); 9435489Sbostic } 9535489Sbostic if (!strcmp(username, *g)) 9635489Sbostic break; 9715897Sralph } 9815897Sralph 9935489Sbostic errno = 0; 10035489Sbostic prio = getpriority(PRIO_PROCESS, 0); 10135489Sbostic if (errno) 10235489Sbostic prio = 0; 10335489Sbostic (void)setpriority(PRIO_PROCESS, 0, -2); 10435489Sbostic 10535489Sbostic if ((p = getlogin()) && *p) 10635489Sbostic username = p; 10735489Sbostic 108*35716Sbostic if (*pwd->pw_passwd && ruid) { 10935489Sbostic p = getpass("Password:"); 11035489Sbostic if (strcmp(pwd->pw_passwd, crypt(p, pwd->pw_passwd))) { 11135489Sbostic fprintf(stderr, "Sorry\n"); 11235489Sbostic if (pwd->pw_uid == 0) 113*35716Sbostic syslog(LOG_CRIT|LOG_AUTH, "su: BAD SU %s on %s", 114*35716Sbostic username, ttyname(2)); 11535489Sbostic exit(1); 1161109Sbill } 1171109Sbill } 118*35716Sbostic 119*35716Sbostic /* if target user has no password, or fulllogin, use their shell */ 120*35716Sbostic if (!*pwd->pw_passwd || fulllogin) 121*35716Sbostic if (pwd->pw_shell && *pwd->pw_shell) { 122*35716Sbostic shell = pwd->pw_shell; 123*35716Sbostic iscsh = UNSET; 124*35716Sbostic } else { 125*35716Sbostic shell = "/bin/sh"; 126*35716Sbostic iscsh = NO; 127*35716Sbostic } 128*35716Sbostic 129*35716Sbostic if (iscsh == UNSET) { 130*35716Sbostic if (p = rindex(shell, '/')) 131*35716Sbostic ++p; 132*35716Sbostic else 133*35716Sbostic p = shell; 134*35716Sbostic iscsh = strcmp(p, "csh") ? NO : YES; 135*35716Sbostic } 136*35716Sbostic 13710045Ssam if (setgid(pwd->pw_gid) < 0) { 13810045Ssam perror("su: setgid"); 13935489Sbostic exit(1); 14010045Ssam } 14112696Ssam if (initgroups(user, pwd->pw_gid)) { 14210045Ssam fprintf(stderr, "su: initgroups failed\n"); 14335489Sbostic exit(1); 14410045Ssam } 14510045Ssam if (setuid(pwd->pw_uid) < 0) { 14610045Ssam perror("su: setuid"); 14735489Sbostic exit(1); 14810045Ssam } 14912696Ssam if (fulllogin) { 15035489Sbostic p = getenv("TERM"); 15135489Sbostic cleanenv[0] = "PATH=:/usr/ucb:/bin:/usr/bin"; 15235489Sbostic cleanenv[1] = NULL; 15312696Ssam environ = cleanenv; 154*35716Sbostic (void)setenv("HOME", pwd->pw_dir, 1); 155*35716Sbostic (void)setenv("SHELL", shell, 1); 15635489Sbostic (void)setenv("TERM", p, 1); 157*35716Sbostic (void)setenv("USER", pwd->pw_name, 1); 15812696Ssam if (chdir(pwd->pw_dir) < 0) { 15935489Sbostic fprintf(stderr, "su: no directory\n"); 16035489Sbostic exit(1); 16112696Ssam } 16235489Sbostic } 1631109Sbill 164*35716Sbostic if (fastlogin && iscsh == YES) 165*35716Sbostic *--argv = "-f"; 1661109Sbill 167*35716Sbostic /* csh strips the first character... */ 168*35716Sbostic *--argv = fulllogin ? "-su" : iscsh == YES ? "_su" : "su"; 169*35716Sbostic 17035489Sbostic if (pwd->pw_uid == 0) 171*35716Sbostic syslog(LOG_NOTICE|LOG_AUTH, "su: %s on %s", 172*35716Sbostic username, ttyname(2)); 1731109Sbill 17435489Sbostic (void)setpriority(PRIO_PROCESS, 0, prio); 1751109Sbill 17635489Sbostic execv(shell, argv); 177*35716Sbostic fprintf(stderr, "su: no shell.\n"); 17835489Sbostic exit(1); 1791109Sbill } 180