1 #ifndef lint 2 static char *sccsid = "@(#)su.c 4.6 (Berkeley) 07/06/83"; 3 #endif 4 5 #include <stdio.h> 6 #include <pwd.h> 7 #include <sys/types.h> 8 #include <sys/time.h> 9 #include <sys/resource.h> 10 11 char userbuf[16] = "USER="; 12 char homebuf[128] = "HOME="; 13 char shellbuf[128] = "SHELL="; 14 char pathbuf[128] = "PATH=:/usr/ucb:/bin:/usr/bin"; 15 char *cleanenv[] = { userbuf, homebuf, shellbuf, pathbuf, 0, 0 }; 16 char *user = "root"; 17 char *shell = "/bin/sh"; 18 int fulllogin; 19 int fastlogin; 20 21 extern char **environ; 22 struct passwd *pwd,*getpwnam(); 23 char *crypt(); 24 char *getpass(); 25 char *getenv(); 26 27 main(argc,argv) 28 int argc; 29 char *argv[]; 30 { 31 char *password; 32 33 again: 34 if (argc > 1 && strcmp(argv[1], "-f") == 0) { 35 fastlogin++; 36 argc--, argv++; 37 goto again; 38 } 39 if (argc > 1 && strcmp(argv[1], "-") == 0) { 40 fulllogin++; 41 argc--, argv++; 42 goto again; 43 } 44 if (argc > 1 && argv[1][0] != '-') { 45 user = argv[1]; 46 argc--, argv++; 47 } 48 if (strcmp(user, "root") == 0) 49 setpriority(PRIO_PROCESS, 0, -2); 50 if ((pwd = getpwnam(user)) == NULL) { 51 fprintf(stderr, "Unknown login: %s\n", user); 52 exit(1); 53 } 54 if (pwd->pw_passwd[0] == '\0' || getuid() == 0) 55 goto ok; 56 password = getpass("Password:"); 57 if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { 58 fprintf(stderr, "Sorry\n"); 59 if (pwd->pw_uid == 0) { 60 FILE *console = fopen("/dev/console", "w"); 61 if (console != NULL) { 62 fprintf(console, "BADSU: %s %s\r\n", 63 getlogin(), ttyname(2)); 64 fclose(console); 65 } 66 } 67 exit(2); 68 } 69 ok: 70 endpwent(); 71 if (pwd->pw_uid == 0) { 72 FILE *console = fopen("/dev/console", "w"); 73 if (console != NULL) { 74 fprintf(console, "SU: %s %s\r\n", 75 getlogin(), ttyname(2)); 76 fclose(console); 77 } 78 } 79 if (setgid(pwd->pw_gid) < 0) { 80 perror("su: setgid"); 81 exit(3); 82 } 83 if (initgroups(user, pwd->pw_gid)) { 84 fprintf(stderr, "su: initgroups failed\n"); 85 exit(4); 86 } 87 if (setuid(pwd->pw_uid) < 0) { 88 perror("su: setuid"); 89 exit(5); 90 } 91 if (pwd->pw_shell && *pwd->pw_shell) 92 shell = pwd->pw_shell; 93 if (fulllogin) { 94 cleanenv[4] = getenv("TERM"); 95 environ = cleanenv; 96 } 97 if (strcmp(user, "root")) 98 setenv("USER", pwd->pw_name, userbuf); 99 setenv("SHELL", shell, shellbuf); 100 setenv("HOME", pwd->pw_dir, homebuf); 101 setpriority(PRIO_PROCESS, 0, 0); 102 if (fastlogin) { 103 *argv-- = "-f"; 104 *argv = "su"; 105 } else if (fulllogin) { 106 if (chdir(pwd->pw_dir) < 0) { 107 fprintf(stderr, "No directory\n"); 108 exit(6); 109 } 110 *argv = "-su"; 111 } else 112 *argv = "su"; 113 execv(shell, argv); 114 fprintf(stderr, "No shell\n"); 115 exit(7); 116 } 117 118 setenv(ename, eval, buf) 119 char *ename, *eval, *buf; 120 { 121 register char *cp, *dp; 122 register char **ep = environ; 123 124 /* 125 * this assumes an environment variable "ename" already exists 126 */ 127 while (dp = *ep++) { 128 for (cp = ename; *cp == *dp && *cp; cp++, dp++) 129 continue; 130 if (*cp == 0 && (*dp == '=' || *dp == 0)) { 131 strcat(buf, eval); 132 *--ep = buf; 133 return; 134 } 135 } 136 } 137 138 char * 139 getenv(ename) 140 char *ename; 141 { 142 register char *cp, *dp; 143 register char **ep = environ; 144 145 while (dp = *ep++) { 146 for (cp = ename; *cp == *dp && *cp; cp++, dp++) 147 continue; 148 if (*cp == 0 && (*dp == '=' || *dp == 0)) 149 return (*--ep); 150 } 151 return ((char *)0); 152 } 153