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.5 (Berkeley) 01/18/87"; 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 char *getlogin(); 41 42 main(argc,argv) 43 int argc; 44 char *argv[]; 45 { 46 char *password; 47 char buf[1000]; 48 FILE *fp; 49 register char *p; 50 51 openlog("su", LOG_ODELAY, LOG_AUTH); 52 53 again: 54 if (argc > 1 && strcmp(argv[1], "-f") == 0) { 55 fastlogin++; 56 argc--, argv++; 57 goto again; 58 } 59 if (argc > 1 && strcmp(argv[1], "-") == 0) { 60 fulllogin++; 61 argc--, argv++; 62 goto again; 63 } 64 if (argc > 1 && argv[1][0] != '-') { 65 user = argv[1]; 66 argc--, argv++; 67 } 68 if ((pwd = getpwuid(getuid())) == NULL) { 69 fprintf(stderr, "Who are you?\n"); 70 exit(1); 71 } 72 strcpy(buf, pwd->pw_name); 73 if ((pwd = getpwnam(user)) == NULL) { 74 fprintf(stderr, "Unknown login: %s\n", user); 75 exit(1); 76 } 77 /* 78 * Only allow those in group zero to su to root. 79 */ 80 if (pwd->pw_uid == 0) { 81 struct group *gr; 82 int i; 83 84 if ((gr = getgrgid(0)) != NULL) { 85 for (i = 0; gr->gr_mem[i] != NULL; i++) 86 if (strcmp(buf, gr->gr_mem[i]) == 0) 87 goto userok; 88 fprintf(stderr, "You do not have permission to su %s\n", 89 user); 90 exit(1); 91 } 92 userok: 93 setpriority(PRIO_PROCESS, 0, -2); 94 } 95 96 #define Getlogin() (((p = getlogin()) && *p) ? p : buf) 97 if (pwd->pw_passwd[0] == '\0' || getuid() == 0) 98 goto ok; 99 password = getpass("Password:"); 100 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { 101 fprintf(stderr, "Sorry\n"); 102 if (pwd->pw_uid == 0) { 103 syslog(LOG_CRIT, "BAD SU %s on %s", 104 Getlogin(), ttyname(2)); 105 } 106 exit(2); 107 } 108 ok: 109 endpwent(); 110 if (pwd->pw_uid == 0) { 111 syslog(LOG_NOTICE, "%s on %s", Getlogin(), ttyname(2)); 112 closelog(); 113 } 114 if (setgid(pwd->pw_gid) < 0) { 115 perror("su: setgid"); 116 exit(3); 117 } 118 if (initgroups(user, pwd->pw_gid)) { 119 fprintf(stderr, "su: initgroups failed\n"); 120 exit(4); 121 } 122 if (setuid(pwd->pw_uid) < 0) { 123 perror("su: setuid"); 124 exit(5); 125 } 126 if (pwd->pw_shell && *pwd->pw_shell) 127 shell = pwd->pw_shell; 128 if (fulllogin) { 129 cleanenv[4] = getenv("TERM"); 130 environ = cleanenv; 131 } 132 if (fulllogin || strcmp(user, "root") != 0) 133 setenv("USER", pwd->pw_name, userbuf); 134 setenv("SHELL", shell, shellbuf); 135 setenv("HOME", pwd->pw_dir, homebuf); 136 setpriority(PRIO_PROCESS, 0, 0); 137 if (fastlogin) { 138 *argv-- = "-f"; 139 *argv = "su"; 140 } else if (fulllogin) { 141 if (chdir(pwd->pw_dir) < 0) { 142 fprintf(stderr, "No directory\n"); 143 exit(6); 144 } 145 *argv = "-su"; 146 } else 147 *argv = "su"; 148 execv(shell, argv); 149 fprintf(stderr, "No shell\n"); 150 exit(7); 151 } 152 153 setenv(ename, eval, buf) 154 char *ename, *eval, *buf; 155 { 156 register char *cp, *dp; 157 register char **ep = environ; 158 159 /* 160 * this assumes an environment variable "ename" already exists 161 */ 162 while (dp = *ep++) { 163 for (cp = ename; *cp == *dp && *cp; cp++, dp++) 164 continue; 165 if (*cp == 0 && (*dp == '=' || *dp == 0)) { 166 strcat(buf, eval); 167 *--ep = buf; 168 return; 169 } 170 } 171 } 172 173 char * 174 getenv(ename) 175 char *ename; 176 { 177 register char *cp, *dp; 178 register char **ep = environ; 179 180 while (dp = *ep++) { 181 for (cp = ename; *cp == *dp && *cp; cp++, dp++) 182 continue; 183 if (*cp == 0 && (*dp == '=' || *dp == 0)) 184 return (*--ep); 185 } 186 return ((char *)0); 187 } 188