xref: /titanic_51/usr/src/cmd/bnu/in.uucpd.c (revision 2de0a7d66c00b4cb047dc93352fe8b77707d2838)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5f48205beScasper  * Common Development and Distribution License (the "License").
6f48205beScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22f48205beScasper  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
26*2de0a7d6SDan McDonald #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*2de0a7d6SDan McDonald 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * 4.2BSD, 2.9BSD, or ATTSVR4 TCP/IP server for uucico
307c478bd9Sstevel@tonic-gate  * uucico's TCP channel causes this server to be run at the remote end.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include "uucp.h"
347c478bd9Sstevel@tonic-gate #include <netdb.h>
357c478bd9Sstevel@tonic-gate #ifdef BSD2_9
367c478bd9Sstevel@tonic-gate #include <sys/localopts.h>
377c478bd9Sstevel@tonic-gate #include <sys/file.h>
38462be471Sceastha #endif	/* BSD2_9 */
397c478bd9Sstevel@tonic-gate #include <signal.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <sys/socket.h>
427c478bd9Sstevel@tonic-gate #include <netinet/in.h>
437c478bd9Sstevel@tonic-gate #include <sys/wait.h>
447c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
457c478bd9Sstevel@tonic-gate #include <sys/termio.h>
467c478bd9Sstevel@tonic-gate #else
477c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
487c478bd9Sstevel@tonic-gate #endif
497c478bd9Sstevel@tonic-gate #include <pwd.h>
507c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
517c478bd9Sstevel@tonic-gate #include <shadow.h>
527c478bd9Sstevel@tonic-gate #endif
53*2de0a7d6SDan McDonald #include <lastlog.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate static int uucp_conv();
587c478bd9Sstevel@tonic-gate struct pam_conv conv = {uucp_conv, NULL };
597c478bd9Sstevel@tonic-gate pam_handle_t    *pamh;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #if !defined(BSD4_2) && !defined(BSD2_9) && !defined(ATTSVR4)
627c478bd9Sstevel@tonic-gate --- You must have either BSD4_2, BSD2_9, or ATTSVR4 defined for this to work
63462be471Sceastha #endif	/* !BSD4_2 && !BSD2_9 */
647c478bd9Sstevel@tonic-gate #if defined(BSD4_2) && defined(BSD2_9)
657c478bd9Sstevel@tonic-gate --- You may not have both BSD4_2 and BSD2_9 defined for this to work
667c478bd9Sstevel@tonic-gate #endif	/* check for stupidity */
677c478bd9Sstevel@tonic-gate 
68*2de0a7d6SDan McDonald char lastlog[] = "/var/adm/lastlog";
69f48205beScasper struct	passwd nouser = {
70f48205beScasper 	"", "nope", (uid_t)-1, (gid_t)-1, "", "", "", "", "" };
717c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
727c478bd9Sstevel@tonic-gate struct	spwd noupass = { "", "nope" };
737c478bd9Sstevel@tonic-gate #endif
747c478bd9Sstevel@tonic-gate struct	sockaddr_in hisctladdr;
757c478bd9Sstevel@tonic-gate socklen_t hisaddrlen = (socklen_t)sizeof (hisctladdr);
767c478bd9Sstevel@tonic-gate struct	sockaddr_in myctladdr;
777c478bd9Sstevel@tonic-gate int nolog;		/* don't log in utmp or wtmp */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate char Username[64];
807c478bd9Sstevel@tonic-gate char Loginname[64];
817c478bd9Sstevel@tonic-gate char *nenv[] = {
827c478bd9Sstevel@tonic-gate 	Username,
837c478bd9Sstevel@tonic-gate 	Loginname,
847c478bd9Sstevel@tonic-gate 	NULL,
857c478bd9Sstevel@tonic-gate };
867c478bd9Sstevel@tonic-gate extern char **environ;
877c478bd9Sstevel@tonic-gate 
88462be471Sceastha static void doit(struct sockaddr_in *);
89462be471Sceastha static void dologout(void);
90462be471Sceastha 
91462be471Sceastha int
927c478bd9Sstevel@tonic-gate main(argc, argv)
937c478bd9Sstevel@tonic-gate int argc;
947c478bd9Sstevel@tonic-gate char **argv;
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate #ifndef BSDINETD
97462be471Sceastha 	int s, tcp_socket;
987c478bd9Sstevel@tonic-gate 	struct servent *sp;
99462be471Sceastha #endif	/* !BSDINETD */
1007c478bd9Sstevel@tonic-gate 	extern int errno;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	if (argc > 1 && strcmp(argv[1], "-n") == 0)
1037c478bd9Sstevel@tonic-gate 		nolog = 1;
1047c478bd9Sstevel@tonic-gate 	environ = nenv;
1057c478bd9Sstevel@tonic-gate #ifdef BSDINETD
1067c478bd9Sstevel@tonic-gate 	close(1); close(2);
1077c478bd9Sstevel@tonic-gate 	dup(0); dup(0);
1087c478bd9Sstevel@tonic-gate 	hisaddrlen = (socklen_t)sizeof (hisctladdr);
1097c478bd9Sstevel@tonic-gate 	if (getpeername(0, (struct sockaddr *)&hisctladdr, &hisaddrlen) < 0) {
1107c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: ", argv[0]);
1117c478bd9Sstevel@tonic-gate 		perror("getpeername");
1127c478bd9Sstevel@tonic-gate 		_exit(1);
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 	if (fork() == 0)
1157c478bd9Sstevel@tonic-gate 		doit(&hisctladdr);
1167c478bd9Sstevel@tonic-gate 	dologout();
1177c478bd9Sstevel@tonic-gate 	exit(1);
118462be471Sceastha #else	/* !BSDINETD */
1197c478bd9Sstevel@tonic-gate 	sp = getservbyname("uucp", "tcp");
1207c478bd9Sstevel@tonic-gate 	if (sp == NULL) {
1217c478bd9Sstevel@tonic-gate 		perror("uucpd: getservbyname");
1227c478bd9Sstevel@tonic-gate 		exit(1);
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 	if (fork())
1257c478bd9Sstevel@tonic-gate 		exit(0);
1267c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
1277c478bd9Sstevel@tonic-gate 	setsid();
1287c478bd9Sstevel@tonic-gate #else
1297c478bd9Sstevel@tonic-gate 	if ((s = open("/dev/tty", 2)) >= 0) {
1307c478bd9Sstevel@tonic-gate 		ioctl(s, TIOCNOTTY, (char *)0);
1317c478bd9Sstevel@tonic-gate 		close(s);
1327c478bd9Sstevel@tonic-gate 	}
1337c478bd9Sstevel@tonic-gate #endif
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
1367c478bd9Sstevel@tonic-gate 	memset((void *)&myctladdr, 0, sizeof (myctladdr));
1377c478bd9Sstevel@tonic-gate #else
1387c478bd9Sstevel@tonic-gate 	bzero((char *)&myctladdr, sizeof (myctladdr));
1397c478bd9Sstevel@tonic-gate #endif
1407c478bd9Sstevel@tonic-gate 	myctladdr.sin_family = AF_INET;
1417c478bd9Sstevel@tonic-gate 	myctladdr.sin_port = sp->s_port;
1427c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4)
1437c478bd9Sstevel@tonic-gate 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
1447c478bd9Sstevel@tonic-gate 	if (tcp_socket < 0) {
1457c478bd9Sstevel@tonic-gate 		perror("uucpd: socket");
1467c478bd9Sstevel@tonic-gate 		exit(1);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
1497c478bd9Sstevel@tonic-gate 		perror("uucpd: bind");
1507c478bd9Sstevel@tonic-gate 		exit(1);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
1537c478bd9Sstevel@tonic-gate 	signal(SIGCHLD, dologout);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	for (;;) {
1567c478bd9Sstevel@tonic-gate 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
1577c478bd9Sstevel@tonic-gate 		if (s < 0) {
1587c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
1597c478bd9Sstevel@tonic-gate 				continue;
1607c478bd9Sstevel@tonic-gate 			perror("uucpd: accept");
1617c478bd9Sstevel@tonic-gate 			exit(1);
1627c478bd9Sstevel@tonic-gate 		}
1637c478bd9Sstevel@tonic-gate 		if (fork() == 0) {
1647c478bd9Sstevel@tonic-gate 			close(0); close(1); close(2);
1657c478bd9Sstevel@tonic-gate 			dup(s); dup(s); dup(s);
1667c478bd9Sstevel@tonic-gate 			close(tcp_socket); close(s);
1677c478bd9Sstevel@tonic-gate 			doit(&hisctladdr);
1687c478bd9Sstevel@tonic-gate 			exit(1);
1697c478bd9Sstevel@tonic-gate 		}
1707c478bd9Sstevel@tonic-gate 		close(s);
1717c478bd9Sstevel@tonic-gate 	}
172462be471Sceastha #endif	/* BSD4_2 */
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate #ifdef BSD2_9
1757c478bd9Sstevel@tonic-gate 	for (;;) {
1767c478bd9Sstevel@tonic-gate 		signal(SIGCHLD, dologout);
1777c478bd9Sstevel@tonic-gate 		s = socket(SOCK_STREAM, 0,  &myctladdr,
1787c478bd9Sstevel@tonic-gate 			SO_ACCEPTCONN|SO_KEEPALIVE);
1797c478bd9Sstevel@tonic-gate 		if (s < 0) {
1807c478bd9Sstevel@tonic-gate 			perror("uucpd: socket");
1817c478bd9Sstevel@tonic-gate 			exit(1);
1827c478bd9Sstevel@tonic-gate 		}
1837c478bd9Sstevel@tonic-gate 		if (accept(s, &hisctladdr) < 0) {
1847c478bd9Sstevel@tonic-gate 			if (errno == EINTR) {
1857c478bd9Sstevel@tonic-gate 				close(s);
1867c478bd9Sstevel@tonic-gate 				continue;
1877c478bd9Sstevel@tonic-gate 			}
1887c478bd9Sstevel@tonic-gate 			perror("uucpd: accept");
1897c478bd9Sstevel@tonic-gate 			exit(1);
1907c478bd9Sstevel@tonic-gate 		}
1917c478bd9Sstevel@tonic-gate 		if (fork() == 0) {
1927c478bd9Sstevel@tonic-gate 			close(0); close(1); close(2);
1937c478bd9Sstevel@tonic-gate 			dup(s); dup(s); dup(s);
1947c478bd9Sstevel@tonic-gate 			close(s);
1957c478bd9Sstevel@tonic-gate 			doit(&hisctladdr);
1967c478bd9Sstevel@tonic-gate 			exit(1);
1977c478bd9Sstevel@tonic-gate 		}
1987c478bd9Sstevel@tonic-gate 	}
199462be471Sceastha #endif	/* BSD2_9 */
200462be471Sceastha #endif	/* !BSDINETD */
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate 
205462be471Sceastha static void
2067c478bd9Sstevel@tonic-gate doit(sinp)
2077c478bd9Sstevel@tonic-gate struct sockaddr_in *sinp;
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 	char user[64], passwd[64];
2107c478bd9Sstevel@tonic-gate 	struct passwd *pw, *getpwnam();
2117c478bd9Sstevel@tonic-gate 	int error;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	alarm(60);
2147c478bd9Sstevel@tonic-gate 	printf("login: "); fflush(stdout);
2157c478bd9Sstevel@tonic-gate 	if (readline(user, sizeof (user)) < 0) {
2167c478bd9Sstevel@tonic-gate 		fprintf(stderr, "user read\n");
2177c478bd9Sstevel@tonic-gate 		return;
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/*
2217c478bd9Sstevel@tonic-gate 	 * Call pam_start to initiate a PAM authentication operation
2227c478bd9Sstevel@tonic-gate 	 */
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if ((pam_start("uucp", user, &conv, &pamh)) != PAM_SUCCESS)
2257c478bd9Sstevel@tonic-gate 		return;
2267c478bd9Sstevel@tonic-gate 	if ((pam_set_item(pamh, PAM_TTY, ttyname(0))) != PAM_SUCCESS)
2277c478bd9Sstevel@tonic-gate 		return;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	if (pam_authenticate(pamh, PAM_SILENT) != PAM_SUCCESS) {
2307c478bd9Sstevel@tonic-gate 		/* force a delay if passwd bad */
2317c478bd9Sstevel@tonic-gate 		sleep(4);
2327c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
2337c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_ABORT);
2347c478bd9Sstevel@tonic-gate 		return;
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	if ((error = pam_acct_mgmt(pamh, PAM_SILENT)) != PAM_SUCCESS) {
2387c478bd9Sstevel@tonic-gate 		switch (error) {
2397c478bd9Sstevel@tonic-gate 		case PAM_NEW_AUTHTOK_REQD:
2407c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Password Expired.");
2417c478bd9Sstevel@tonic-gate 			break;
2427c478bd9Sstevel@tonic-gate 		case PAM_PERM_DENIED:
2437c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Account Expired.");
2447c478bd9Sstevel@tonic-gate 			break;
2457c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_EXPIRED:
2467c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Password Expired.");
2477c478bd9Sstevel@tonic-gate 			break;
2487c478bd9Sstevel@tonic-gate 		default:
2497c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Login incorrect.");
2507c478bd9Sstevel@tonic-gate 			break;
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_ABORT);
2537c478bd9Sstevel@tonic-gate 		return;
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	if ((pw = getpwnam(user)) == NULL || strcmp(pw->pw_shell, UUCICO)) {
2577c478bd9Sstevel@tonic-gate 		/* force a delay if user bad */
2587c478bd9Sstevel@tonic-gate 		sleep(4);
2597c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
2607c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_USER_UNKNOWN);
2617c478bd9Sstevel@tonic-gate 		return;
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	alarm(0);
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	sprintf(Username, "USER=%s", user);
2677c478bd9Sstevel@tonic-gate 	sprintf(Loginname, "LOGNAME=%s", user);
2687c478bd9Sstevel@tonic-gate 	if (!nolog)
2697c478bd9Sstevel@tonic-gate 		if (dologin(pw, sinp)) {
2707c478bd9Sstevel@tonic-gate 			pam_end(pamh, PAM_ABORT);
2717c478bd9Sstevel@tonic-gate 			_exit(1);
2727c478bd9Sstevel@tonic-gate 		}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	/* set the real (and effective) GID */
2757c478bd9Sstevel@tonic-gate 	if (setgid(pw->pw_gid) == -1) {
2767c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
2777c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_PERM_DENIED);
2787c478bd9Sstevel@tonic-gate 		return;
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	/*
2827c478bd9Sstevel@tonic-gate 	 * Initialize the supplementary group access list.
2837c478bd9Sstevel@tonic-gate 	 */
2847c478bd9Sstevel@tonic-gate 	if (initgroups(user, pw->pw_gid) == -1) {
2857c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
2867c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_PERM_DENIED);
2877c478bd9Sstevel@tonic-gate 		return;
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) {
2917c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
2927c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_CRED_INSUFFICIENT);
2937c478bd9Sstevel@tonic-gate 		return;
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	/* set the real (and effective) UID */
2977c478bd9Sstevel@tonic-gate 	if (setuid(pw->pw_uid) == -1) {
2987c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
2997c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_CRED_ERR);
3007c478bd9Sstevel@tonic-gate 		return;
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	chdir(pw->pw_dir);
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	pam_end(pamh, PAM_SUCCESS);
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4)
3087c478bd9Sstevel@tonic-gate 	execl(UUCICO, "uucico", "-u", user, (char *)0);
309462be471Sceastha #endif	/* BSD4_2 */
3107c478bd9Sstevel@tonic-gate #ifdef BSD2_9
3117c478bd9Sstevel@tonic-gate 	sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr));
3127c478bd9Sstevel@tonic-gate 	execl(UUCICO, "uucico", passwd, (char *)0);
313462be471Sceastha #endif	/* BSD2_9 */
3147c478bd9Sstevel@tonic-gate 	perror("uucico server: execl");
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
317462be471Sceastha int
3187c478bd9Sstevel@tonic-gate readline(p, n)
319462be471Sceastha char *p;
320462be471Sceastha int n;
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate 	char c;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	while (n-- > 0) {
3257c478bd9Sstevel@tonic-gate 		if (read(0, &c, 1) <= 0)
3267c478bd9Sstevel@tonic-gate 			return (-1);
3277c478bd9Sstevel@tonic-gate 		c &= 0177;
3287c478bd9Sstevel@tonic-gate 		if (c == '\n' || c == '\r') {
3297c478bd9Sstevel@tonic-gate 			*p = '\0';
3307c478bd9Sstevel@tonic-gate 			return (0);
3317c478bd9Sstevel@tonic-gate 		}
3327c478bd9Sstevel@tonic-gate 		*p++ = c;
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 	return (-1);
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
3387c478bd9Sstevel@tonic-gate #include <sac.h>	/* for SC_WILDC */
3397c478bd9Sstevel@tonic-gate #include <utmpx.h>
340462be471Sceastha #else	/* !ATTSVR4 */
3417c478bd9Sstevel@tonic-gate #include <utmp.h>
342462be471Sceastha #endif	/* !ATTSVR4 */
3437c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4)
3447c478bd9Sstevel@tonic-gate #include <fcntl.h>
345462be471Sceastha #endif	/* BSD4_2 */
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate #ifdef BSD2_9
3487c478bd9Sstevel@tonic-gate #define	O_APPEND	0 /* kludge */
3497c478bd9Sstevel@tonic-gate #define	wait3(a, b, c)	wait2(a, b)
350462be471Sceastha #endif	/* BSD2_9 */
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
3557c478bd9Sstevel@tonic-gate struct	utmpx utmp;
356462be471Sceastha #else	/* !ATTSVR4 */
3577c478bd9Sstevel@tonic-gate struct	utmp utmp;
358462be471Sceastha #endif	/* !ATTSVR4 */
3597c478bd9Sstevel@tonic-gate 
360462be471Sceastha static void
361462be471Sceastha dologout(void)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
3647c478bd9Sstevel@tonic-gate 	int status;
365462be471Sceastha #else	/* !ATTSVR4 */
3667c478bd9Sstevel@tonic-gate 	union wait status;
367462be471Sceastha #endif	/* !ATSVR4 */
3687c478bd9Sstevel@tonic-gate 	int pid, wtmp;
3697c478bd9Sstevel@tonic-gate 	/* the following 2 variables are needed for utmp mgmt */
3707c478bd9Sstevel@tonic-gate 	struct utmpx	ut;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate #ifdef BSDINETD
3737c478bd9Sstevel@tonic-gate 	while ((pid = wait(&status)) > 0) {
374462be471Sceastha #else	/* !BSDINETD */
3757c478bd9Sstevel@tonic-gate 	while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
376462be471Sceastha #endif	/* !BSDINETD */
3777c478bd9Sstevel@tonic-gate 		if (nolog)
3787c478bd9Sstevel@tonic-gate 			continue;
3797c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
3807c478bd9Sstevel@tonic-gate 		/* clear out any residue from utmpx buffer */
3817c478bd9Sstevel@tonic-gate 		(void) memset((char *)&ut, 0, sizeof (ut));
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_user, "");
3847c478bd9Sstevel@tonic-gate 		ut.ut_id[0] = 'u';
3857c478bd9Sstevel@tonic-gate 		ut.ut_id[1] = 'u';
3867c478bd9Sstevel@tonic-gate 		ut.ut_id[2] = SC_WILDC;
3877c478bd9Sstevel@tonic-gate 		ut.ut_id[3] = SC_WILDC;
3887c478bd9Sstevel@tonic-gate 		sprintf(ut.ut_line, "uucp%.4d", pid);
3897c478bd9Sstevel@tonic-gate 		ut.ut_pid  = getpid();
3907c478bd9Sstevel@tonic-gate 		ut.ut_type = DEAD_PROCESS;
3917c478bd9Sstevel@tonic-gate 		ut.ut_exit.e_termination = status & 0xFF;
3927c478bd9Sstevel@tonic-gate 		ut.ut_exit.e_exit = WEXITSTATUS(status);
3937c478bd9Sstevel@tonic-gate 		SCPYN(ut.ut_host, "");
3947c478bd9Sstevel@tonic-gate 		ut.ut_syslen = 1;
3957c478bd9Sstevel@tonic-gate 		(void) gettimeofday(&ut.ut_tv, NULL);
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 		/*
3987c478bd9Sstevel@tonic-gate 		 * XXX: UUCPD does not do any pam session management.
3997c478bd9Sstevel@tonic-gate 		 *	There is no way for the parent process to close
4007c478bd9Sstevel@tonic-gate 		 *	the pam session after a child has exited.
4017c478bd9Sstevel@tonic-gate 		 */
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 		updwtmpx(WTMPX_FILE, &ut);
404462be471Sceastha #else	/* !ATTSVR4 */
4057c478bd9Sstevel@tonic-gate 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
4067c478bd9Sstevel@tonic-gate 		if (wtmp >= 0) {
4077c478bd9Sstevel@tonic-gate 			sprintf(utmp.ut_line, "uucp%.4d", pid);
4087c478bd9Sstevel@tonic-gate 			SCPYN(utmp.ut_name, "");
4097c478bd9Sstevel@tonic-gate 			SCPYN(utmp.ut_host, "");
4107c478bd9Sstevel@tonic-gate 			(void) time(&utmp.ut_time);
4117c478bd9Sstevel@tonic-gate #ifdef BSD2_9
4127c478bd9Sstevel@tonic-gate 			(void) lseek(wtmp, 0L, 2);
413462be471Sceastha #endif	/* BSD2_9 */
4147c478bd9Sstevel@tonic-gate 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
4157c478bd9Sstevel@tonic-gate 			(void) close(wtmp);
4167c478bd9Sstevel@tonic-gate 		}
417462be471Sceastha #endif	/* !ATTSVR4 */
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate  * Record login in wtmp file.
4237c478bd9Sstevel@tonic-gate  */
424462be471Sceastha int
4257c478bd9Sstevel@tonic-gate dologin(pw, sin)
4267c478bd9Sstevel@tonic-gate struct passwd *pw;
4277c478bd9Sstevel@tonic-gate struct sockaddr_in *sin;
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	char line[32];
4307c478bd9Sstevel@tonic-gate 	char remotehost[32];
4317c478bd9Sstevel@tonic-gate 	int wtmp;
4327c478bd9Sstevel@tonic-gate 	struct hostent *hp = gethostbyaddr((const char *)&sin->sin_addr,
4337c478bd9Sstevel@tonic-gate 		sizeof (struct in_addr), AF_INET);
4347c478bd9Sstevel@tonic-gate 	struct utmpx	ut;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	if (hp) {
4377c478bd9Sstevel@tonic-gate 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
4387c478bd9Sstevel@tonic-gate 		endhostent();
4397c478bd9Sstevel@tonic-gate 	} else
4407c478bd9Sstevel@tonic-gate 		strncpy(remotehost, (char *)inet_ntoa(sin->sin_addr),
4417c478bd9Sstevel@tonic-gate 		    sizeof (remotehost));
4427c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
4437c478bd9Sstevel@tonic-gate 	/* clear wtmpx entry */
4447c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ut, 0, sizeof (ut));
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	SCPYN(ut.ut_user, pw->pw_name);
4477c478bd9Sstevel@tonic-gate 	ut.ut_id[0] = 'u';
4487c478bd9Sstevel@tonic-gate 	ut.ut_id[1] = 'u';
4497c478bd9Sstevel@tonic-gate 	ut.ut_id[2] = SC_WILDC;
4507c478bd9Sstevel@tonic-gate 	ut.ut_id[3] = SC_WILDC;
4517c478bd9Sstevel@tonic-gate 	/* hack, but must be unique and no tty line */
4527c478bd9Sstevel@tonic-gate 	sprintf(line, "uucp%.4d", getpid());
4537c478bd9Sstevel@tonic-gate 	SCPYN(ut.ut_line, line);
4547c478bd9Sstevel@tonic-gate 	ut.ut_pid = getpid();
4557c478bd9Sstevel@tonic-gate 	ut.ut_type = USER_PROCESS;
4567c478bd9Sstevel@tonic-gate 	ut.ut_exit.e_termination = 0;
4577c478bd9Sstevel@tonic-gate 	ut.ut_exit.e_exit = 0;
4587c478bd9Sstevel@tonic-gate 	SCPYN(ut.ut_host, remotehost);
4597c478bd9Sstevel@tonic-gate 	ut.ut_syslen = strlen(remotehost) + 1;
4607c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&ut.ut_tv, 0);
4617c478bd9Sstevel@tonic-gate 	updwtmpx(WTMPX_FILE, &ut);
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	/*
4647c478bd9Sstevel@tonic-gate 	 * XXX:
4657c478bd9Sstevel@tonic-gate 	 * 	We no longer do session management in uucpd because
4667c478bd9Sstevel@tonic-gate 	 *	there is no way to do the "pam_close_session()".
4677c478bd9Sstevel@tonic-gate 	 *
4687c478bd9Sstevel@tonic-gate 	 *	Processes like "init" can do a pam_close_session()
469da6c28aaSamw 	 *	because they can use the utmp entry to retrieve
4707c478bd9Sstevel@tonic-gate 	 *	the proper username, ttyname, etc. --
4717c478bd9Sstevel@tonic-gate 	 *	uucpd only writes to the wtmp file.
4727c478bd9Sstevel@tonic-gate 	 *
4737c478bd9Sstevel@tonic-gate 	 *	ftpd (which also only writes to the wtmp file)
4747c478bd9Sstevel@tonic-gate 	 *	can do a pam_close_session() because it doesn't fork().
4757c478bd9Sstevel@tonic-gate 	 *
4767c478bd9Sstevel@tonic-gate 	 *	if (pam_set_item(pamh, PAM_RHOST, remotehost) != PAM_SUCCESS)
4777c478bd9Sstevel@tonic-gate 	 *		return (1);
4787c478bd9Sstevel@tonic-gate 	 *	if (pam_set_item(pamh, PAM_TTY, line) != PAM_SUCCESS)
4797c478bd9Sstevel@tonic-gate 	 *		return (1);
4807c478bd9Sstevel@tonic-gate 	 *	if (pam_open_session(pamh, 0) != PAM_SUCCESS) {
4817c478bd9Sstevel@tonic-gate 	 *		return (1);
4827c478bd9Sstevel@tonic-gate 	 *	}
4837c478bd9Sstevel@tonic-gate 	 */
4847c478bd9Sstevel@tonic-gate 
485462be471Sceastha #else	/* !ATTSVR4 */
4867c478bd9Sstevel@tonic-gate 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
4877c478bd9Sstevel@tonic-gate 	if (wtmp >= 0) {
4887c478bd9Sstevel@tonic-gate 		/* hack, but must be unique and no tty line */
4897c478bd9Sstevel@tonic-gate 		sprintf(line, "uucp%.4d", getpid());
4907c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_line, line);
4917c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_name, pw->pw_name);
4927c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_host, remotehost);
4937c478bd9Sstevel@tonic-gate 		time(&utmp.ut_time);
4947c478bd9Sstevel@tonic-gate #ifdef BSD2_9
4957c478bd9Sstevel@tonic-gate 		(void) lseek(wtmp, 0L, 2);
496462be471Sceastha #endif	/* BSD2_9 */
4977c478bd9Sstevel@tonic-gate 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
4987c478bd9Sstevel@tonic-gate 		(void) close(wtmp);
4997c478bd9Sstevel@tonic-gate 	}
500462be471Sceastha #endif	/* !ATTSVR4 */
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	return (0);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate /*
5067c478bd9Sstevel@tonic-gate  * uucp_conv	- This is the conv (conversation) function called from
5077c478bd9Sstevel@tonic-gate  *		a PAM authentication module to print error messages
5087c478bd9Sstevel@tonic-gate  *		or garner information from the user.
5097c478bd9Sstevel@tonic-gate  */
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate static int
5127c478bd9Sstevel@tonic-gate uucp_conv(num_msg, msg, response, appdata_ptr)
5137c478bd9Sstevel@tonic-gate 	int num_msg;
5147c478bd9Sstevel@tonic-gate 	struct pam_message **msg;
5157c478bd9Sstevel@tonic-gate 	struct pam_response **response;
5167c478bd9Sstevel@tonic-gate 	void *appdata_ptr;
5177c478bd9Sstevel@tonic-gate {
5187c478bd9Sstevel@tonic-gate 	struct pam_message	*m;
5197c478bd9Sstevel@tonic-gate 	struct pam_response	*r;
5207c478bd9Sstevel@tonic-gate 	char			*temp;
5217c478bd9Sstevel@tonic-gate 	static char		passwd[64];
5227c478bd9Sstevel@tonic-gate 	int			k, i;
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	if (num_msg <= 0)
5257c478bd9Sstevel@tonic-gate 		return (PAM_CONV_ERR);
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	*response = (struct pam_response *)calloc(num_msg,
5287c478bd9Sstevel@tonic-gate 			sizeof (struct pam_response));
5297c478bd9Sstevel@tonic-gate 	if (*response == NULL)
5307c478bd9Sstevel@tonic-gate 		return (PAM_BUF_ERR);
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	k = num_msg;
5337c478bd9Sstevel@tonic-gate 	m = *msg;
5347c478bd9Sstevel@tonic-gate 	r = *response;
5357c478bd9Sstevel@tonic-gate 	while (k--) {
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 		switch (m->msg_style) {
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_OFF:
5407c478bd9Sstevel@tonic-gate 			/*
5417c478bd9Sstevel@tonic-gate 			 * we do this instead of using passed in message
5427c478bd9Sstevel@tonic-gate 			 * to prevent possible breakage of uucp protocol.
5437c478bd9Sstevel@tonic-gate 			 */
5447c478bd9Sstevel@tonic-gate 			printf("Password: "); fflush(stdout);
5457c478bd9Sstevel@tonic-gate 			if (readline(passwd, sizeof (passwd)) < 0) {
5467c478bd9Sstevel@tonic-gate 				fprintf(stderr, "passwd read\n");
5477c478bd9Sstevel@tonic-gate 				return (PAM_SUCCESS);
5487c478bd9Sstevel@tonic-gate 			}
5497c478bd9Sstevel@tonic-gate 			temp = passwd;
5507c478bd9Sstevel@tonic-gate 			if (temp != NULL) {
5517c478bd9Sstevel@tonic-gate 				r->resp = strdup(temp);
5527c478bd9Sstevel@tonic-gate 				if (r->resp == NULL) {
5537c478bd9Sstevel@tonic-gate 					/* free responses */
5547c478bd9Sstevel@tonic-gate 					r = *response;
5557c478bd9Sstevel@tonic-gate 					for (i = 0; i < num_msg; i++, r++) {
5567c478bd9Sstevel@tonic-gate 						if (r->resp)
5577c478bd9Sstevel@tonic-gate 							free(r->resp);
5587c478bd9Sstevel@tonic-gate 					}
5597c478bd9Sstevel@tonic-gate 					free(*response);
5607c478bd9Sstevel@tonic-gate 					*response = NULL;
5617c478bd9Sstevel@tonic-gate 					return (PAM_BUF_ERR);
5627c478bd9Sstevel@tonic-gate 				}
5637c478bd9Sstevel@tonic-gate 			}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 			m++;
5667c478bd9Sstevel@tonic-gate 			r++;
5677c478bd9Sstevel@tonic-gate 			break;
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_ON:
5707c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
5717c478bd9Sstevel@tonic-gate 				fputs(m->msg, stdout);
5727c478bd9Sstevel@tonic-gate 				fflush(stdout);
5737c478bd9Sstevel@tonic-gate 			}
5747c478bd9Sstevel@tonic-gate 			r->resp = (char *)malloc(PAM_MAX_RESP_SIZE);
5757c478bd9Sstevel@tonic-gate 			if (r->resp == NULL) {
5767c478bd9Sstevel@tonic-gate 				/* free the response */
5777c478bd9Sstevel@tonic-gate 				r = *response;
5787c478bd9Sstevel@tonic-gate 				for (i = 0; i < num_msg; i++, r++) {
5797c478bd9Sstevel@tonic-gate 					if (r->resp)
5807c478bd9Sstevel@tonic-gate 						free(r->resp);
5817c478bd9Sstevel@tonic-gate 				}
5827c478bd9Sstevel@tonic-gate 				free(*response);
5837c478bd9Sstevel@tonic-gate 				*response = NULL;
5847c478bd9Sstevel@tonic-gate 				return (PAM_BUF_ERR);
5857c478bd9Sstevel@tonic-gate 			}
5867c478bd9Sstevel@tonic-gate 			(void) fgets(r->resp, PAM_MAX_RESP_SIZE, stdin);
5877c478bd9Sstevel@tonic-gate 			m++;
5887c478bd9Sstevel@tonic-gate 			r++;
5897c478bd9Sstevel@tonic-gate 			break;
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 		case PAM_ERROR_MSG:
5927c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
5937c478bd9Sstevel@tonic-gate 				fputs(m->msg, stderr);
5947c478bd9Sstevel@tonic-gate 				fputs("\n", stderr);
5957c478bd9Sstevel@tonic-gate 			}
5967c478bd9Sstevel@tonic-gate 			m++;
5977c478bd9Sstevel@tonic-gate 			r++;
5987c478bd9Sstevel@tonic-gate 			break;
5997c478bd9Sstevel@tonic-gate 		case PAM_TEXT_INFO:
6007c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
6017c478bd9Sstevel@tonic-gate 				fputs(m->msg, stdout);
6027c478bd9Sstevel@tonic-gate 				fputs("\n", stdout);
6037c478bd9Sstevel@tonic-gate 			}
6047c478bd9Sstevel@tonic-gate 			m++;
6057c478bd9Sstevel@tonic-gate 			r++;
6067c478bd9Sstevel@tonic-gate 			break;
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 		default:
6097c478bd9Sstevel@tonic-gate 			break;
6107c478bd9Sstevel@tonic-gate 		}
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 	return (PAM_SUCCESS);
6137c478bd9Sstevel@tonic-gate }
614