xref: /csrg-svn/usr.bin/su/su.c (revision 10045)
1*10045Ssam #ifndef lint
2*10045Ssam static char *sccsid = "@(#)su.c	4.4 (Berkeley) 4.4";
3*10045Ssam #endif
4*10045Ssam 
51109Sbill #include <stdio.h>
61109Sbill #include <pwd.h>
71109Sbill 
81109Sbill struct	passwd *pwd,*getpwnam();
91109Sbill char	*crypt();
101109Sbill char	*getpass();
111109Sbill 
121109Sbill main(argc,argv)
13*10045Ssam 	int argc;
14*10045Ssam 	char **argv;
151109Sbill {
16*10045Ssam 	char *nptr = "root";
171109Sbill 	char *password;
181109Sbill 	char *shell = "/bin/sh";
191109Sbill 
20*10045Ssam 	if (argc > 1)
211109Sbill 		nptr = argv[1];
22*10045Ssam 	if ((pwd = getpwnam(nptr)) == NULL) {
231109Sbill 		printf("Unknown id: %s\n",nptr);
241109Sbill 		exit(1);
251109Sbill 	}
26*10045Ssam 	if (pwd->pw_passwd[0] == '\0' || getuid() == 0)
271109Sbill 		goto ok;
281109Sbill 	password = getpass("Password:");
29*10045Ssam 	if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
301109Sbill 		printf("Sorry\n");
31*10045Ssam 		if (pwd->pw_uid == 0) {
321109Sbill 			FILE *console = fopen("/dev/console", "w");
331109Sbill 			if (console != NULL) {
34*10045Ssam 				fprintf(console, "BADSU: %s %s\r\n",
35*10045Ssam 					getlogin(), ttyname(2));
361109Sbill 				fclose(console);
371109Sbill 			}
381109Sbill 		}
391109Sbill 		exit(2);
401109Sbill 	}
411109Sbill ok:
421109Sbill 	endpwent();
43*10045Ssam 	if (pwd->pw_uid == 0) {
441109Sbill 		FILE *console = fopen("/dev/console", "w");
451109Sbill 		if (console != NULL) {
46*10045Ssam 			fprintf(console, "SU: %s %s\r\n",
47*10045Ssam 				getlogin(), ttyname(2));
481109Sbill 			fclose(console);
491109Sbill 		}
501109Sbill 	}
51*10045Ssam 	if (setgid(pwd->pw_gid) < 0) {
52*10045Ssam 		perror("su: setgid");
53*10045Ssam 		exit(3);
54*10045Ssam 	}
55*10045Ssam 	if (initgroups(nptr, pwd->pw_gid)) {
56*10045Ssam 		fprintf(stderr, "su: initgroups failed\n");
57*10045Ssam 		exit(4);
58*10045Ssam 	}
59*10045Ssam 	if (setuid(pwd->pw_uid) < 0) {
60*10045Ssam 		perror("su: setuid");
61*10045Ssam 		exit(5);
62*10045Ssam 	}
631109Sbill 	if (pwd->pw_shell && *pwd->pw_shell)
641109Sbill 		shell = pwd->pw_shell;
651109Sbill 	homeis(pwd->pw_dir);
661109Sbill 	shellis(shell);
671109Sbill 	execl(shell, "su", 0);
681109Sbill 	printf("No shell\n");
691109Sbill 	exit(3);
701109Sbill }
711109Sbill 
721109Sbill char	**environ;
731109Sbill 
741109Sbill homeis(hp)
751109Sbill 	char *hp;
761109Sbill {
771109Sbill 	register char *cp, *dp;
781109Sbill 	register char **ep = environ;
791109Sbill 	static char homebuf[128];
801109Sbill 
811109Sbill 	while (dp = *ep++) {
821109Sbill 		for (cp = "HOME"; *cp == *dp && *cp; cp++, dp++)
831109Sbill 			continue;
841109Sbill 		if (*cp == 0 && (*dp == '=' || *dp == 0)) {
851109Sbill 			strcpy(homebuf, "HOME=");
861109Sbill 			strcat(homebuf, hp);
871109Sbill 			*--ep = homebuf;
881109Sbill 			return;
891109Sbill 		}
901109Sbill 	}
911109Sbill }
921109Sbill 
931109Sbill shellis(sp)
941109Sbill 	char *sp;
951109Sbill {
961109Sbill 	register char *cp, *dp;
971109Sbill 	register char **ep = environ;
981109Sbill 	static char shellbuf[128];
991109Sbill 
1001109Sbill 	while (dp = *ep++) {
1011109Sbill 		for (cp = "SHELL"; *cp == *dp && *cp; cp++, dp++)
1021109Sbill 			continue;
1031109Sbill 		if (*cp == 0 && (*dp == '=' || *dp == 0)) {
1041109Sbill 			strcpy(shellbuf, "SHELL=");
1051109Sbill 			strcat(shellbuf, sp);
1061109Sbill 			*--ep = shellbuf;
1071109Sbill 			return;
1081109Sbill 		}
1091109Sbill 	}
1101109Sbill }
111