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: #if !defined(lint) && defined(DOSCCS) 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: 12: static char sccsid[] = "@(#)su.c 5.4.1 (2.11BSD) 1997/10/2"; 13: #endif 14: 15: #include <stdio.h> 16: #include <pwd.h> 17: #include <grp.h> 18: #include <syslog.h> 19: #include <stdlib.h> 20: #include <unistd.h> 21: #include <sys/types.h> 22: #include <sys/time.h> 23: #include <sys/resource.h> 24: 25: char userbuf[64] = "USER="; 26: char homebuf[128] = "HOME="; 27: char shellbuf[128] = "SHELL="; 28: char pathbuf[128] = "PATH=:/usr/ucb:/bin:/usr/bin"; 29: char *cleanenv[] = { userbuf, homebuf, shellbuf, pathbuf, 0, 0 }; 30: char *user = "root"; 31: char *shell = "/bin/sh"; 32: int fulllogin; 33: int fastlogin; 34: 35: extern char **environ; 36: struct passwd *pwd; 37: 38: main(argc,argv) 39: int argc; 40: char *argv[]; 41: { 42: char *password; 43: char buf[1000]; 44: FILE *fp; 45: register char *p; 46: 47: openlog("su", LOG_ODELAY, LOG_AUTH); 48: 49: again: 50: if (argc > 1 && strcmp(argv[1], "-f") == 0) { 51: fastlogin++; 52: argc--, argv++; 53: goto again; 54: } 55: if (argc > 1 && strcmp(argv[1], "-") == 0) { 56: fulllogin++; 57: argc--, argv++; 58: goto again; 59: } 60: if (argc > 1 && argv[1][0] != '-') { 61: user = argv[1]; 62: argc--, argv++; 63: } 64: if ((pwd = getpwuid(getuid())) == NULL) { 65: fprintf(stderr, "Who are you?\n"); 66: exit(1); 67: } 68: strcpy(buf, pwd->pw_name); 69: if ((pwd = getpwnam(user)) == NULL) { 70: fprintf(stderr, "Unknown login: %s\n", user); 71: exit(1); 72: } 73: /* 74: * Only allow those in group zero to su to root. 75: */ 76: if (pwd->pw_uid == 0) { 77: struct group *gr; 78: int i; 79: 80: if ((gr = getgrgid(0)) != NULL) { 81: for (i = 0; gr->gr_mem[i] != NULL; i++) 82: if (strcmp(buf, gr->gr_mem[i]) == 0) 83: goto userok; 84: fprintf(stderr, "You do not have permission to su %s\n", 85: user); 86: exit(1); 87: } 88: userok: 89: setpriority(PRIO_PROCESS, 0, -2); 90: } 91: 92: #define Getlogin() (((p = getlogin()) && *p) ? p : buf) 93: if (pwd->pw_passwd[0] == '\0' || getuid() == 0) 94: goto ok; 95: password = getpass("Password:"); 96: if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { 97: fprintf(stderr, "Sorry\n"); 98: if (pwd->pw_uid == 0) { 99: syslog(LOG_CRIT, "BAD SU %s on %s", 100: Getlogin(), ttyname(2)); 101: } 102: exit(2); 103: } 104: ok: 105: endpwent(); 106: if (pwd->pw_uid == 0) { 107: syslog(LOG_NOTICE, "%s on %s", Getlogin(), ttyname(2)); 108: closelog(); 109: } 110: if (setgid(pwd->pw_gid) < 0) { 111: perror("su: setgid"); 112: exit(3); 113: } 114: if (initgroups(user, pwd->pw_gid)) { 115: fprintf(stderr, "su: initgroups failed\n"); 116: exit(4); 117: } 118: if (setuid(pwd->pw_uid) < 0) { 119: perror("su: setuid"); 120: exit(5); 121: } 122: if (pwd->pw_shell && *pwd->pw_shell) 123: shell = pwd->pw_shell; 124: if (fulllogin) { 125: cleanenv[4] = getenv("TERM"); 126: environ = cleanenv; 127: } 128: if (strcmp(user, "root")) 129: setenv("USER", pwd->pw_name, userbuf); 130: setenv("SHELL", shell, shellbuf); 131: setenv("HOME", pwd->pw_dir, homebuf); 132: setpriority(PRIO_PROCESS, 0, 0); 133: if (fastlogin) { 134: *argv-- = "-f"; 135: *argv = "su"; 136: } else if (fulllogin) { 137: if (chdir(pwd->pw_dir) < 0) { 138: fprintf(stderr, "No directory\n"); 139: exit(6); 140: } 141: *argv = "-su"; 142: } else 143: *argv = "su"; 144: execv(shell, argv); 145: fprintf(stderr, "No shell\n"); 146: exit(7); 147: } 148: 149: setenv(ename, eval, buf) 150: char *ename, *eval, *buf; 151: { 152: register char *cp, *dp; 153: register char **ep = environ; 154: 155: /* 156: * this assumes an environment variable "ename" already exists 157: */ 158: while (dp = *ep++) { 159: for (cp = ename; *cp == *dp && *cp; cp++, dp++) 160: continue; 161: if (*cp == 0 && (*dp == '=' || *dp == 0)) { 162: strcat(buf, eval); 163: *--ep = buf; 164: return; 165: } 166: } 167: } 168: 169: char * 170: getenv(ename) 171: char *ename; 172: { 173: register char *cp, *dp; 174: register char **ep = environ; 175: 176: while (dp = *ep++) { 177: for (cp = ename; *cp == *dp && *cp; cp++, dp++) 178: continue; 179: if (*cp == 0 && (*dp == '=' || *dp == 0)) 180: return (*--ep); 181: } 182: return ((char *)0); 183: }