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.3 (Berkeley) 09/17/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 openlog("su", LOG_ODELAY, LOG_AUTH); 50 51 again: 52 if (argc > 1 && strcmp(argv[1], "-f") == 0) { 53 fastlogin++; 54 argc--, argv++; 55 goto again; 56 } 57 if (argc > 1 && strcmp(argv[1], "-") == 0) { 58 fulllogin++; 59 argc--, argv++; 60 goto again; 61 } 62 if (argc > 1 && argv[1][0] != '-') { 63 user = argv[1]; 64 argc--, argv++; 65 } 66 if ((pwd = getpwuid(getuid())) == NULL) { 67 fprintf(stderr, "Who are you?\n"); 68 exit(1); 69 } 70 strcpy(buf, pwd->pw_name); 71 if ((pwd = getpwnam(user)) == NULL) { 72 fprintf(stderr, "Unknown login: %s\n", user); 73 exit(1); 74 } 75 /* 76 * Only allow those in group zero to su to root. 77 */ 78 if (pwd->pw_uid == 0) { 79 struct group *gr; 80 int i; 81 82 if ((gr = getgrgid(0)) != NULL) { 83 for (i = 0; gr->gr_mem[i] != NULL; i++) 84 if (strcmp(buf, gr->gr_mem[i]) == 0) 85 goto userok; 86 fprintf(stderr, "You do not have permission to su %s\n", 87 user); 88 exit(1); 89 } 90 userok: 91 setpriority(PRIO_PROCESS, 0, -2); 92 } 93 94 if (pwd->pw_passwd[0] == '\0' || getuid() == 0) 95 goto ok; 96 password = getpass("Password:"); 97 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { 98 fprintf(stderr, "Sorry\n"); 99 if (pwd->pw_uid == 0) { 100 syslog(LOG_CRIT, "BAD SU %s on %s", 101 getlogin(), ttyname(2)); 102 } 103 exit(2); 104 } 105 ok: 106 endpwent(); 107 if (pwd->pw_uid == 0) { 108 syslog(LOG_NOTICE, "%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