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 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)su.c 5.2 (Berkeley) 06/07/85"; 15 #endif not lint 16 17 #include <stdio.h> 18 #include <pwd.h> 19 #include <grp.h> 20 #include <syslog.h> 21 #include <sys/types.h> 22 #include <sys/time.h> 23 #include <sys/resource.h> 24 25 char userbuf[16] = "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 char *crypt(); 38 char *getpass(); 39 char *getenv(); 40 41 main(argc,argv) 42 int argc; 43 char *argv[]; 44 { 45 char *password; 46 char buf[1000]; 47 FILE *fp; 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 if (pwd->pw_passwd[0] == '\0' || getuid() == 0) 93 goto ok; 94 password = getpass("Password:"); 95 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { 96 fprintf(stderr, "Sorry\n"); 97 if (pwd->pw_uid == 0) { 98 openlog("su", 0, 0); 99 syslog(LOG_SECURITY, "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 openlog("su", 0, 0); 108 syslog(LOG_SECURITY, "%s on %s", getlogin(), ttyname(2)); 109 closelog(); 110 } 111 if (setgid(pwd->pw_gid) < 0) { 112 perror("su: setgid"); 113 exit(3); 114 } 115 if (initgroups(user, pwd->pw_gid)) { 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 } 123 if (pwd->pw_shell && *pwd->pw_shell) 124 shell = pwd->pw_shell; 125 if (fulllogin) { 126 cleanenv[4] = getenv("TERM"); 127 environ = cleanenv; 128 } 129 if (strcmp(user, "root")) 130 setenv("USER", pwd->pw_name, userbuf); 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); 148 } 149 150 setenv(ename, eval, buf) 151 char *ename, *eval, *buf; 152 { 153 register char *cp, *dp; 154 register char **ep = environ; 155 156 /* 157 * this assumes an environment variable "ename" already exists 158 */ 159 while (dp = *ep++) { 160 for (cp = ename; *cp == *dp && *cp; cp++, dp++) 161 continue; 162 if (*cp == 0 && (*dp == '=' || *dp == 0)) { 163 strcat(buf, eval); 164 *--ep = buf; 165 return; 166 } 167 } 168 } 169 170 char * 171 getenv(ename) 172 char *ename; 173 { 174 register char *cp, *dp; 175 register char **ep = environ; 176 177 while (dp = *ep++) { 178 for (cp = ename; *cp == *dp && *cp; cp++, dp++) 179 continue; 180 if (*cp == 0 && (*dp == '=' || *dp == 0)) 181 return (*--ep); 182 } 183 return ((char *)0); 184 } 185