xref: /titanic_53/usr/src/cmd/bnu/in.uucpd.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1998-2002 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /* from UCB 5.4 6/23/85 */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  * 4.2BSD, 2.9BSD, or ATTSVR4 TCP/IP server for uucico
33*7c478bd9Sstevel@tonic-gate  * uucico's TCP channel causes this server to be run at the remote end.
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include "uucp.h"
37*7c478bd9Sstevel@tonic-gate #include <netdb.h>
38*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9
39*7c478bd9Sstevel@tonic-gate #include <sys/localopts.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
41*7c478bd9Sstevel@tonic-gate #endif BSD2_9
42*7c478bd9Sstevel@tonic-gate #include <signal.h>
43*7c478bd9Sstevel@tonic-gate #include <errno.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
45*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
47*7c478bd9Sstevel@tonic-gate #ifdef ATTSVTTY
48*7c478bd9Sstevel@tonic-gate #include <sys/termio.h>
49*7c478bd9Sstevel@tonic-gate #else
50*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
51*7c478bd9Sstevel@tonic-gate #endif
52*7c478bd9Sstevel@tonic-gate #include <pwd.h>
53*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
54*7c478bd9Sstevel@tonic-gate #include <shadow.h>
55*7c478bd9Sstevel@tonic-gate #endif
56*7c478bd9Sstevel@tonic-gate #include <lastlog.h>
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate static int uucp_conv();
61*7c478bd9Sstevel@tonic-gate struct pam_conv conv = {uucp_conv, NULL };
62*7c478bd9Sstevel@tonic-gate pam_handle_t    *pamh;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate #if !defined(BSD4_2) && !defined(BSD2_9) && !defined(ATTSVR4)
65*7c478bd9Sstevel@tonic-gate --- You must have either BSD4_2, BSD2_9, or ATTSVR4 defined for this to work
66*7c478bd9Sstevel@tonic-gate #endif !BSD4_2 && !BSD2_9
67*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) && defined(BSD2_9)
68*7c478bd9Sstevel@tonic-gate --- You may not have both BSD4_2 and BSD2_9 defined for this to work
69*7c478bd9Sstevel@tonic-gate #endif	/* check for stupidity */
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate char lastlog[] = "/var/adm/lastlog";
72*7c478bd9Sstevel@tonic-gate struct	passwd nouser = { "", "nope", -1, -1, "", "", "", "", "" };
73*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
74*7c478bd9Sstevel@tonic-gate struct	spwd noupass = { "", "nope" };
75*7c478bd9Sstevel@tonic-gate #endif
76*7c478bd9Sstevel@tonic-gate struct	sockaddr_in hisctladdr;
77*7c478bd9Sstevel@tonic-gate socklen_t hisaddrlen = (socklen_t)sizeof (hisctladdr);
78*7c478bd9Sstevel@tonic-gate struct	sockaddr_in myctladdr;
79*7c478bd9Sstevel@tonic-gate int nolog;		/* don't log in utmp or wtmp */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate char Username[64];
82*7c478bd9Sstevel@tonic-gate char Loginname[64];
83*7c478bd9Sstevel@tonic-gate char *nenv[] = {
84*7c478bd9Sstevel@tonic-gate 	Username,
85*7c478bd9Sstevel@tonic-gate 	Loginname,
86*7c478bd9Sstevel@tonic-gate 	NULL,
87*7c478bd9Sstevel@tonic-gate };
88*7c478bd9Sstevel@tonic-gate extern char **environ;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate main(argc, argv)
91*7c478bd9Sstevel@tonic-gate int argc;
92*7c478bd9Sstevel@tonic-gate char **argv;
93*7c478bd9Sstevel@tonic-gate {
94*7c478bd9Sstevel@tonic-gate #ifndef BSDINETD
95*7c478bd9Sstevel@tonic-gate 	register int s, tcp_socket;
96*7c478bd9Sstevel@tonic-gate 	struct servent *sp;
97*7c478bd9Sstevel@tonic-gate #endif !BSDINETD
98*7c478bd9Sstevel@tonic-gate 	extern int errno;
99*7c478bd9Sstevel@tonic-gate 	int dologout();
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	if (argc > 1 && strcmp(argv[1], "-n") == 0)
102*7c478bd9Sstevel@tonic-gate 		nolog = 1;
103*7c478bd9Sstevel@tonic-gate 	environ = nenv;
104*7c478bd9Sstevel@tonic-gate #ifdef BSDINETD
105*7c478bd9Sstevel@tonic-gate 	close(1); close(2);
106*7c478bd9Sstevel@tonic-gate 	dup(0); dup(0);
107*7c478bd9Sstevel@tonic-gate 	hisaddrlen = (socklen_t)sizeof (hisctladdr);
108*7c478bd9Sstevel@tonic-gate 	if (getpeername(0, (struct sockaddr *)&hisctladdr, &hisaddrlen) < 0) {
109*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: ", argv[0]);
110*7c478bd9Sstevel@tonic-gate 		perror("getpeername");
111*7c478bd9Sstevel@tonic-gate 		_exit(1);
112*7c478bd9Sstevel@tonic-gate 	}
113*7c478bd9Sstevel@tonic-gate 	if (fork() == 0)
114*7c478bd9Sstevel@tonic-gate 		doit(&hisctladdr);
115*7c478bd9Sstevel@tonic-gate 	dologout();
116*7c478bd9Sstevel@tonic-gate 	exit(1);
117*7c478bd9Sstevel@tonic-gate #else !BSDINETD
118*7c478bd9Sstevel@tonic-gate 	sp = getservbyname("uucp", "tcp");
119*7c478bd9Sstevel@tonic-gate 	if (sp == NULL) {
120*7c478bd9Sstevel@tonic-gate 		perror("uucpd: getservbyname");
121*7c478bd9Sstevel@tonic-gate 		exit(1);
122*7c478bd9Sstevel@tonic-gate 	}
123*7c478bd9Sstevel@tonic-gate 	if (fork())
124*7c478bd9Sstevel@tonic-gate 		exit(0);
125*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
126*7c478bd9Sstevel@tonic-gate 	setsid();
127*7c478bd9Sstevel@tonic-gate #else
128*7c478bd9Sstevel@tonic-gate 	if ((s = open("/dev/tty", 2)) >= 0) {
129*7c478bd9Sstevel@tonic-gate 		ioctl(s, TIOCNOTTY, (char *)0);
130*7c478bd9Sstevel@tonic-gate 		close(s);
131*7c478bd9Sstevel@tonic-gate 	}
132*7c478bd9Sstevel@tonic-gate #endif
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
135*7c478bd9Sstevel@tonic-gate 	memset((void *)&myctladdr, 0, sizeof (myctladdr));
136*7c478bd9Sstevel@tonic-gate #else
137*7c478bd9Sstevel@tonic-gate 	bzero((char *)&myctladdr, sizeof (myctladdr));
138*7c478bd9Sstevel@tonic-gate #endif
139*7c478bd9Sstevel@tonic-gate 	myctladdr.sin_family = AF_INET;
140*7c478bd9Sstevel@tonic-gate 	myctladdr.sin_port = sp->s_port;
141*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4)
142*7c478bd9Sstevel@tonic-gate 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
143*7c478bd9Sstevel@tonic-gate 	if (tcp_socket < 0) {
144*7c478bd9Sstevel@tonic-gate 		perror("uucpd: socket");
145*7c478bd9Sstevel@tonic-gate 		exit(1);
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
148*7c478bd9Sstevel@tonic-gate 		perror("uucpd: bind");
149*7c478bd9Sstevel@tonic-gate 		exit(1);
150*7c478bd9Sstevel@tonic-gate 	}
151*7c478bd9Sstevel@tonic-gate 	listen(tcp_socket, 3);	/* at most 3 simultaneuos uucp connections */
152*7c478bd9Sstevel@tonic-gate 	signal(SIGCHLD, dologout);
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	for (;;) {
155*7c478bd9Sstevel@tonic-gate 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
156*7c478bd9Sstevel@tonic-gate 		if (s < 0) {
157*7c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
158*7c478bd9Sstevel@tonic-gate 				continue;
159*7c478bd9Sstevel@tonic-gate 			perror("uucpd: accept");
160*7c478bd9Sstevel@tonic-gate 			exit(1);
161*7c478bd9Sstevel@tonic-gate 		}
162*7c478bd9Sstevel@tonic-gate 		if (fork() == 0) {
163*7c478bd9Sstevel@tonic-gate 			close(0); close(1); close(2);
164*7c478bd9Sstevel@tonic-gate 			dup(s); dup(s); dup(s);
165*7c478bd9Sstevel@tonic-gate 			close(tcp_socket); close(s);
166*7c478bd9Sstevel@tonic-gate 			doit(&hisctladdr);
167*7c478bd9Sstevel@tonic-gate 			exit(1);
168*7c478bd9Sstevel@tonic-gate 		}
169*7c478bd9Sstevel@tonic-gate 		close(s);
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate #endif BSD4_2
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9
174*7c478bd9Sstevel@tonic-gate 	for (;;) {
175*7c478bd9Sstevel@tonic-gate 		signal(SIGCHLD, dologout);
176*7c478bd9Sstevel@tonic-gate 		s = socket(SOCK_STREAM, 0,  &myctladdr,
177*7c478bd9Sstevel@tonic-gate 			SO_ACCEPTCONN|SO_KEEPALIVE);
178*7c478bd9Sstevel@tonic-gate 		if (s < 0) {
179*7c478bd9Sstevel@tonic-gate 			perror("uucpd: socket");
180*7c478bd9Sstevel@tonic-gate 			exit(1);
181*7c478bd9Sstevel@tonic-gate 		}
182*7c478bd9Sstevel@tonic-gate 		if (accept(s, &hisctladdr) < 0) {
183*7c478bd9Sstevel@tonic-gate 			if (errno == EINTR) {
184*7c478bd9Sstevel@tonic-gate 				close(s);
185*7c478bd9Sstevel@tonic-gate 				continue;
186*7c478bd9Sstevel@tonic-gate 			}
187*7c478bd9Sstevel@tonic-gate 			perror("uucpd: accept");
188*7c478bd9Sstevel@tonic-gate 			exit(1);
189*7c478bd9Sstevel@tonic-gate 		}
190*7c478bd9Sstevel@tonic-gate 		if (fork() == 0) {
191*7c478bd9Sstevel@tonic-gate 			close(0); close(1); close(2);
192*7c478bd9Sstevel@tonic-gate 			dup(s); dup(s); dup(s);
193*7c478bd9Sstevel@tonic-gate 			close(s);
194*7c478bd9Sstevel@tonic-gate 			doit(&hisctladdr);
195*7c478bd9Sstevel@tonic-gate 			exit(1);
196*7c478bd9Sstevel@tonic-gate 		}
197*7c478bd9Sstevel@tonic-gate 	}
198*7c478bd9Sstevel@tonic-gate #endif BSD2_9
199*7c478bd9Sstevel@tonic-gate #endif	!BSDINETD
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
202*7c478bd9Sstevel@tonic-gate }
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate doit(sinp)
205*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sinp;
206*7c478bd9Sstevel@tonic-gate {
207*7c478bd9Sstevel@tonic-gate 	char user[64], passwd[64];
208*7c478bd9Sstevel@tonic-gate 	struct passwd *pw, *getpwnam();
209*7c478bd9Sstevel@tonic-gate 	int error;
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	alarm(60);
212*7c478bd9Sstevel@tonic-gate 	printf("login: "); fflush(stdout);
213*7c478bd9Sstevel@tonic-gate 	if (readline(user, sizeof (user)) < 0) {
214*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "user read\n");
215*7c478bd9Sstevel@tonic-gate 		return;
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 	/*
219*7c478bd9Sstevel@tonic-gate 	 * Call pam_start to initiate a PAM authentication operation
220*7c478bd9Sstevel@tonic-gate 	 */
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 	if ((pam_start("uucp", user, &conv, &pamh)) != PAM_SUCCESS)
223*7c478bd9Sstevel@tonic-gate 		return;
224*7c478bd9Sstevel@tonic-gate 	if ((pam_set_item(pamh, PAM_TTY, ttyname(0))) != PAM_SUCCESS)
225*7c478bd9Sstevel@tonic-gate 		return;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	if (pam_authenticate(pamh, PAM_SILENT) != PAM_SUCCESS) {
228*7c478bd9Sstevel@tonic-gate 		/* force a delay if passwd bad */
229*7c478bd9Sstevel@tonic-gate 		sleep(4);
230*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
231*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_ABORT);
232*7c478bd9Sstevel@tonic-gate 		return;
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	if ((error = pam_acct_mgmt(pamh, PAM_SILENT)) != PAM_SUCCESS) {
236*7c478bd9Sstevel@tonic-gate 		switch (error) {
237*7c478bd9Sstevel@tonic-gate 		case PAM_NEW_AUTHTOK_REQD:
238*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Password Expired.");
239*7c478bd9Sstevel@tonic-gate 			break;
240*7c478bd9Sstevel@tonic-gate 		case PAM_PERM_DENIED:
241*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Account Expired.");
242*7c478bd9Sstevel@tonic-gate 			break;
243*7c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_EXPIRED:
244*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Password Expired.");
245*7c478bd9Sstevel@tonic-gate 			break;
246*7c478bd9Sstevel@tonic-gate 		default:
247*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Login incorrect.");
248*7c478bd9Sstevel@tonic-gate 			break;
249*7c478bd9Sstevel@tonic-gate 		}
250*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_ABORT);
251*7c478bd9Sstevel@tonic-gate 		return;
252*7c478bd9Sstevel@tonic-gate 	}
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	if ((pw = getpwnam(user)) == NULL || strcmp(pw->pw_shell, UUCICO)) {
255*7c478bd9Sstevel@tonic-gate 		/* force a delay if user bad */
256*7c478bd9Sstevel@tonic-gate 		sleep(4);
257*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
258*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_USER_UNKNOWN);
259*7c478bd9Sstevel@tonic-gate 		return;
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	alarm(0);
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	sprintf(Username, "USER=%s", user);
265*7c478bd9Sstevel@tonic-gate 	sprintf(Loginname, "LOGNAME=%s", user);
266*7c478bd9Sstevel@tonic-gate 	if (!nolog)
267*7c478bd9Sstevel@tonic-gate 		if (dologin(pw, sinp)) {
268*7c478bd9Sstevel@tonic-gate 			pam_end(pamh, PAM_ABORT);
269*7c478bd9Sstevel@tonic-gate 			_exit(1);
270*7c478bd9Sstevel@tonic-gate 		}
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	/* set the real (and effective) GID */
273*7c478bd9Sstevel@tonic-gate 	if (setgid(pw->pw_gid) == -1) {
274*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
275*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_PERM_DENIED);
276*7c478bd9Sstevel@tonic-gate 		return;
277*7c478bd9Sstevel@tonic-gate 	}
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	/*
280*7c478bd9Sstevel@tonic-gate 	 * Initialize the supplementary group access list.
281*7c478bd9Sstevel@tonic-gate 	 */
282*7c478bd9Sstevel@tonic-gate 	if (initgroups(user, pw->pw_gid) == -1) {
283*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
284*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_PERM_DENIED);
285*7c478bd9Sstevel@tonic-gate 		return;
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) {
289*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
290*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_CRED_INSUFFICIENT);
291*7c478bd9Sstevel@tonic-gate 		return;
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	/* set the real (and effective) UID */
295*7c478bd9Sstevel@tonic-gate 	if (setuid(pw->pw_uid) == -1) {
296*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Login incorrect.");
297*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_CRED_ERR);
298*7c478bd9Sstevel@tonic-gate 		return;
299*7c478bd9Sstevel@tonic-gate 	}
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 	chdir(pw->pw_dir);
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	pam_end(pamh, PAM_SUCCESS);
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4)
306*7c478bd9Sstevel@tonic-gate 	execl(UUCICO, "uucico", "-u", user, (char *)0);
307*7c478bd9Sstevel@tonic-gate #endif BSD4_2
308*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9
309*7c478bd9Sstevel@tonic-gate 	sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr));
310*7c478bd9Sstevel@tonic-gate 	execl(UUCICO, "uucico", passwd, (char *)0);
311*7c478bd9Sstevel@tonic-gate #endif BSD2_9
312*7c478bd9Sstevel@tonic-gate 	perror("uucico server: execl");
313*7c478bd9Sstevel@tonic-gate }
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate readline(p, n)
316*7c478bd9Sstevel@tonic-gate register char *p;
317*7c478bd9Sstevel@tonic-gate register int n;
318*7c478bd9Sstevel@tonic-gate {
319*7c478bd9Sstevel@tonic-gate 	char c;
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	while (n-- > 0) {
322*7c478bd9Sstevel@tonic-gate 		if (read(0, &c, 1) <= 0)
323*7c478bd9Sstevel@tonic-gate 			return (-1);
324*7c478bd9Sstevel@tonic-gate 		c &= 0177;
325*7c478bd9Sstevel@tonic-gate 		if (c == '\n' || c == '\r') {
326*7c478bd9Sstevel@tonic-gate 			*p = '\0';
327*7c478bd9Sstevel@tonic-gate 			return (0);
328*7c478bd9Sstevel@tonic-gate 		}
329*7c478bd9Sstevel@tonic-gate 		*p++ = c;
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate 	return (-1);
332*7c478bd9Sstevel@tonic-gate }
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
335*7c478bd9Sstevel@tonic-gate #include <sac.h>	/* for SC_WILDC */
336*7c478bd9Sstevel@tonic-gate #include <utmpx.h>
337*7c478bd9Sstevel@tonic-gate #else !ATTSVR4
338*7c478bd9Sstevel@tonic-gate #include <utmp.h>
339*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4
340*7c478bd9Sstevel@tonic-gate #if defined(BSD4_2) || defined(ATTSVR4)
341*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
342*7c478bd9Sstevel@tonic-gate #endif BSD4_2
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9
345*7c478bd9Sstevel@tonic-gate #define	O_APPEND	0 /* kludge */
346*7c478bd9Sstevel@tonic-gate #define	wait3(a, b, c)	wait2(a, b)
347*7c478bd9Sstevel@tonic-gate #endif BSD2_9
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
352*7c478bd9Sstevel@tonic-gate struct	utmpx utmp;
353*7c478bd9Sstevel@tonic-gate #else !ATTSVR4
354*7c478bd9Sstevel@tonic-gate struct	utmp utmp;
355*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate dologout()
358*7c478bd9Sstevel@tonic-gate {
359*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
360*7c478bd9Sstevel@tonic-gate 	int status;
361*7c478bd9Sstevel@tonic-gate #else !ATTSVR4
362*7c478bd9Sstevel@tonic-gate 	union wait status;
363*7c478bd9Sstevel@tonic-gate #endif !ATSVR4
364*7c478bd9Sstevel@tonic-gate 	int pid, wtmp;
365*7c478bd9Sstevel@tonic-gate 	/* the following 2 variables are needed for utmp mgmt */
366*7c478bd9Sstevel@tonic-gate 	struct utmpx	ut;
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate #ifdef BSDINETD
369*7c478bd9Sstevel@tonic-gate 	while ((pid = wait(&status)) > 0) {
370*7c478bd9Sstevel@tonic-gate #else  !BSDINETD
371*7c478bd9Sstevel@tonic-gate 	while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
372*7c478bd9Sstevel@tonic-gate #endif !BSDINETD
373*7c478bd9Sstevel@tonic-gate 		if (nolog)
374*7c478bd9Sstevel@tonic-gate 			continue;
375*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
376*7c478bd9Sstevel@tonic-gate 		/* clear out any residue from utmpx buffer */
377*7c478bd9Sstevel@tonic-gate 		(void) memset((char *)&ut, 0, sizeof (ut));
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_user, "");
380*7c478bd9Sstevel@tonic-gate 		ut.ut_id[0] = 'u';
381*7c478bd9Sstevel@tonic-gate 		ut.ut_id[1] = 'u';
382*7c478bd9Sstevel@tonic-gate 		ut.ut_id[2] = SC_WILDC;
383*7c478bd9Sstevel@tonic-gate 		ut.ut_id[3] = SC_WILDC;
384*7c478bd9Sstevel@tonic-gate 		sprintf(ut.ut_line, "uucp%.4d", pid);
385*7c478bd9Sstevel@tonic-gate 		ut.ut_pid  = getpid();
386*7c478bd9Sstevel@tonic-gate 		ut.ut_type = DEAD_PROCESS;
387*7c478bd9Sstevel@tonic-gate 		ut.ut_exit.e_termination = status & 0xFF;
388*7c478bd9Sstevel@tonic-gate 		ut.ut_exit.e_exit = WEXITSTATUS(status);
389*7c478bd9Sstevel@tonic-gate 		SCPYN(ut.ut_host, "");
390*7c478bd9Sstevel@tonic-gate 		ut.ut_syslen = 1;
391*7c478bd9Sstevel@tonic-gate 		(void) gettimeofday(&ut.ut_tv, NULL);
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 		/*
394*7c478bd9Sstevel@tonic-gate 		 * XXX: UUCPD does not do any pam session management.
395*7c478bd9Sstevel@tonic-gate 		 *	There is no way for the parent process to close
396*7c478bd9Sstevel@tonic-gate 		 *	the pam session after a child has exited.
397*7c478bd9Sstevel@tonic-gate 		 */
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 		updwtmpx(WTMPX_FILE, &ut);
400*7c478bd9Sstevel@tonic-gate #else !ATTSVR4
401*7c478bd9Sstevel@tonic-gate 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
402*7c478bd9Sstevel@tonic-gate 		if (wtmp >= 0) {
403*7c478bd9Sstevel@tonic-gate 			sprintf(utmp.ut_line, "uucp%.4d", pid);
404*7c478bd9Sstevel@tonic-gate 			SCPYN(utmp.ut_name, "");
405*7c478bd9Sstevel@tonic-gate 			SCPYN(utmp.ut_host, "");
406*7c478bd9Sstevel@tonic-gate 			(void) time(&utmp.ut_time);
407*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9
408*7c478bd9Sstevel@tonic-gate 			(void) lseek(wtmp, 0L, 2);
409*7c478bd9Sstevel@tonic-gate #endif BSD2_9
410*7c478bd9Sstevel@tonic-gate 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
411*7c478bd9Sstevel@tonic-gate 			(void) close(wtmp);
412*7c478bd9Sstevel@tonic-gate 		}
413*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4
414*7c478bd9Sstevel@tonic-gate 	}
415*7c478bd9Sstevel@tonic-gate }
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate /*
418*7c478bd9Sstevel@tonic-gate  * Record login in wtmp file.
419*7c478bd9Sstevel@tonic-gate  */
420*7c478bd9Sstevel@tonic-gate dologin(pw, sin)
421*7c478bd9Sstevel@tonic-gate struct passwd *pw;
422*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin;
423*7c478bd9Sstevel@tonic-gate {
424*7c478bd9Sstevel@tonic-gate 	char line[32];
425*7c478bd9Sstevel@tonic-gate 	char remotehost[32];
426*7c478bd9Sstevel@tonic-gate 	int wtmp;
427*7c478bd9Sstevel@tonic-gate 	struct hostent *hp = gethostbyaddr((const char *)&sin->sin_addr,
428*7c478bd9Sstevel@tonic-gate 		sizeof (struct in_addr), AF_INET);
429*7c478bd9Sstevel@tonic-gate 	struct utmpx	ut;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	if (hp) {
432*7c478bd9Sstevel@tonic-gate 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
433*7c478bd9Sstevel@tonic-gate 		endhostent();
434*7c478bd9Sstevel@tonic-gate 	} else
435*7c478bd9Sstevel@tonic-gate 		strncpy(remotehost, (char *)inet_ntoa(sin->sin_addr),
436*7c478bd9Sstevel@tonic-gate 		    sizeof (remotehost));
437*7c478bd9Sstevel@tonic-gate #ifdef ATTSVR4
438*7c478bd9Sstevel@tonic-gate 	/* clear wtmpx entry */
439*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&ut, 0, sizeof (ut));
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	SCPYN(ut.ut_user, pw->pw_name);
442*7c478bd9Sstevel@tonic-gate 	ut.ut_id[0] = 'u';
443*7c478bd9Sstevel@tonic-gate 	ut.ut_id[1] = 'u';
444*7c478bd9Sstevel@tonic-gate 	ut.ut_id[2] = SC_WILDC;
445*7c478bd9Sstevel@tonic-gate 	ut.ut_id[3] = SC_WILDC;
446*7c478bd9Sstevel@tonic-gate 	/* hack, but must be unique and no tty line */
447*7c478bd9Sstevel@tonic-gate 	sprintf(line, "uucp%.4d", getpid());
448*7c478bd9Sstevel@tonic-gate 	SCPYN(ut.ut_line, line);
449*7c478bd9Sstevel@tonic-gate 	ut.ut_pid = getpid();
450*7c478bd9Sstevel@tonic-gate 	ut.ut_type = USER_PROCESS;
451*7c478bd9Sstevel@tonic-gate 	ut.ut_exit.e_termination = 0;
452*7c478bd9Sstevel@tonic-gate 	ut.ut_exit.e_exit = 0;
453*7c478bd9Sstevel@tonic-gate 	SCPYN(ut.ut_host, remotehost);
454*7c478bd9Sstevel@tonic-gate 	ut.ut_syslen = strlen(remotehost) + 1;
455*7c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&ut.ut_tv, 0);
456*7c478bd9Sstevel@tonic-gate 	updwtmpx(WTMPX_FILE, &ut);
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	/*
459*7c478bd9Sstevel@tonic-gate 	 * XXX:
460*7c478bd9Sstevel@tonic-gate 	 * 	We no longer do session management in uucpd because
461*7c478bd9Sstevel@tonic-gate 	 *	there is no way to do the "pam_close_session()".
462*7c478bd9Sstevel@tonic-gate 	 *
463*7c478bd9Sstevel@tonic-gate 	 *	Processes like "init" can do a pam_close_session()
464*7c478bd9Sstevel@tonic-gate 	 *	because they can use the utmp entry to retrive
465*7c478bd9Sstevel@tonic-gate 	 *	the proper username, ttyname, etc. --
466*7c478bd9Sstevel@tonic-gate 	 *	uucpd only writes to the wtmp file.
467*7c478bd9Sstevel@tonic-gate 	 *
468*7c478bd9Sstevel@tonic-gate 	 *	ftpd (which also only writes to the wtmp file)
469*7c478bd9Sstevel@tonic-gate 	 *	can do a pam_close_session() because it doesn't fork().
470*7c478bd9Sstevel@tonic-gate 	 *
471*7c478bd9Sstevel@tonic-gate 	 *	if (pam_set_item(pamh, PAM_RHOST, remotehost) != PAM_SUCCESS)
472*7c478bd9Sstevel@tonic-gate 	 *		return (1);
473*7c478bd9Sstevel@tonic-gate 	 *	if (pam_set_item(pamh, PAM_TTY, line) != PAM_SUCCESS)
474*7c478bd9Sstevel@tonic-gate 	 *		return (1);
475*7c478bd9Sstevel@tonic-gate 	 *	if (pam_open_session(pamh, 0) != PAM_SUCCESS) {
476*7c478bd9Sstevel@tonic-gate 	 *		return (1);
477*7c478bd9Sstevel@tonic-gate 	 *	}
478*7c478bd9Sstevel@tonic-gate 	 */
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate #else !ATTSVR4
481*7c478bd9Sstevel@tonic-gate 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
482*7c478bd9Sstevel@tonic-gate 	if (wtmp >= 0) {
483*7c478bd9Sstevel@tonic-gate 		/* hack, but must be unique and no tty line */
484*7c478bd9Sstevel@tonic-gate 		sprintf(line, "uucp%.4d", getpid());
485*7c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_line, line);
486*7c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_name, pw->pw_name);
487*7c478bd9Sstevel@tonic-gate 		SCPYN(utmp.ut_host, remotehost);
488*7c478bd9Sstevel@tonic-gate 		time(&utmp.ut_time);
489*7c478bd9Sstevel@tonic-gate #ifdef BSD2_9
490*7c478bd9Sstevel@tonic-gate 		(void) lseek(wtmp, 0L, 2);
491*7c478bd9Sstevel@tonic-gate #endif BSD2_9
492*7c478bd9Sstevel@tonic-gate 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
493*7c478bd9Sstevel@tonic-gate 		(void) close(wtmp);
494*7c478bd9Sstevel@tonic-gate 	}
495*7c478bd9Sstevel@tonic-gate #endif !ATTSVR4
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	return (0);
498*7c478bd9Sstevel@tonic-gate }
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate /*
501*7c478bd9Sstevel@tonic-gate  * uucp_conv	- This is the conv (conversation) function called from
502*7c478bd9Sstevel@tonic-gate  *		a PAM authentication module to print error messages
503*7c478bd9Sstevel@tonic-gate  *		or garner information from the user.
504*7c478bd9Sstevel@tonic-gate  */
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate static int
507*7c478bd9Sstevel@tonic-gate uucp_conv(num_msg, msg, response, appdata_ptr)
508*7c478bd9Sstevel@tonic-gate 	int num_msg;
509*7c478bd9Sstevel@tonic-gate 	struct pam_message **msg;
510*7c478bd9Sstevel@tonic-gate 	struct pam_response **response;
511*7c478bd9Sstevel@tonic-gate 	void *appdata_ptr;
512*7c478bd9Sstevel@tonic-gate {
513*7c478bd9Sstevel@tonic-gate 	struct pam_message	*m;
514*7c478bd9Sstevel@tonic-gate 	struct pam_response	*r;
515*7c478bd9Sstevel@tonic-gate 	char			*temp;
516*7c478bd9Sstevel@tonic-gate 	static char		passwd[64];
517*7c478bd9Sstevel@tonic-gate 	int			k, i;
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	if (num_msg <= 0)
520*7c478bd9Sstevel@tonic-gate 		return (PAM_CONV_ERR);
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 	*response = (struct pam_response *)calloc(num_msg,
523*7c478bd9Sstevel@tonic-gate 			sizeof (struct pam_response));
524*7c478bd9Sstevel@tonic-gate 	if (*response == NULL)
525*7c478bd9Sstevel@tonic-gate 		return (PAM_BUF_ERR);
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	k = num_msg;
528*7c478bd9Sstevel@tonic-gate 	m = *msg;
529*7c478bd9Sstevel@tonic-gate 	r = *response;
530*7c478bd9Sstevel@tonic-gate 	while (k--) {
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 		switch (m->msg_style) {
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_OFF:
535*7c478bd9Sstevel@tonic-gate 			/*
536*7c478bd9Sstevel@tonic-gate 			 * we do this instead of using passed in message
537*7c478bd9Sstevel@tonic-gate 			 * to prevent possible breakage of uucp protocol.
538*7c478bd9Sstevel@tonic-gate 			 */
539*7c478bd9Sstevel@tonic-gate 			printf("Password: "); fflush(stdout);
540*7c478bd9Sstevel@tonic-gate 			if (readline(passwd, sizeof (passwd)) < 0) {
541*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "passwd read\n");
542*7c478bd9Sstevel@tonic-gate 				return (PAM_SUCCESS);
543*7c478bd9Sstevel@tonic-gate 			}
544*7c478bd9Sstevel@tonic-gate 			temp = passwd;
545*7c478bd9Sstevel@tonic-gate 			if (temp != NULL) {
546*7c478bd9Sstevel@tonic-gate 				r->resp = strdup(temp);
547*7c478bd9Sstevel@tonic-gate 				if (r->resp == NULL) {
548*7c478bd9Sstevel@tonic-gate 					/* free responses */
549*7c478bd9Sstevel@tonic-gate 					r = *response;
550*7c478bd9Sstevel@tonic-gate 					for (i = 0; i < num_msg; i++, r++) {
551*7c478bd9Sstevel@tonic-gate 						if (r->resp)
552*7c478bd9Sstevel@tonic-gate 							free(r->resp);
553*7c478bd9Sstevel@tonic-gate 					}
554*7c478bd9Sstevel@tonic-gate 					free(*response);
555*7c478bd9Sstevel@tonic-gate 					*response = NULL;
556*7c478bd9Sstevel@tonic-gate 					return (PAM_BUF_ERR);
557*7c478bd9Sstevel@tonic-gate 				}
558*7c478bd9Sstevel@tonic-gate 			}
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 			m++;
561*7c478bd9Sstevel@tonic-gate 			r++;
562*7c478bd9Sstevel@tonic-gate 			break;
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_ON:
565*7c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
566*7c478bd9Sstevel@tonic-gate 				fputs(m->msg, stdout);
567*7c478bd9Sstevel@tonic-gate 				fflush(stdout);
568*7c478bd9Sstevel@tonic-gate 			}
569*7c478bd9Sstevel@tonic-gate 			r->resp = (char *)malloc(PAM_MAX_RESP_SIZE);
570*7c478bd9Sstevel@tonic-gate 			if (r->resp == NULL) {
571*7c478bd9Sstevel@tonic-gate 				/* free the response */
572*7c478bd9Sstevel@tonic-gate 				r = *response;
573*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < num_msg; i++, r++) {
574*7c478bd9Sstevel@tonic-gate 					if (r->resp)
575*7c478bd9Sstevel@tonic-gate 						free(r->resp);
576*7c478bd9Sstevel@tonic-gate 				}
577*7c478bd9Sstevel@tonic-gate 				free(*response);
578*7c478bd9Sstevel@tonic-gate 				*response = NULL;
579*7c478bd9Sstevel@tonic-gate 				return (PAM_BUF_ERR);
580*7c478bd9Sstevel@tonic-gate 			}
581*7c478bd9Sstevel@tonic-gate 			(void) fgets(r->resp, PAM_MAX_RESP_SIZE, stdin);
582*7c478bd9Sstevel@tonic-gate 			m++;
583*7c478bd9Sstevel@tonic-gate 			r++;
584*7c478bd9Sstevel@tonic-gate 			break;
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate 		case PAM_ERROR_MSG:
587*7c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
588*7c478bd9Sstevel@tonic-gate 				fputs(m->msg, stderr);
589*7c478bd9Sstevel@tonic-gate 				fputs("\n", stderr);
590*7c478bd9Sstevel@tonic-gate 			}
591*7c478bd9Sstevel@tonic-gate 			m++;
592*7c478bd9Sstevel@tonic-gate 			r++;
593*7c478bd9Sstevel@tonic-gate 			break;
594*7c478bd9Sstevel@tonic-gate 		case PAM_TEXT_INFO:
595*7c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
596*7c478bd9Sstevel@tonic-gate 				fputs(m->msg, stdout);
597*7c478bd9Sstevel@tonic-gate 				fputs("\n", stdout);
598*7c478bd9Sstevel@tonic-gate 			}
599*7c478bd9Sstevel@tonic-gate 			m++;
600*7c478bd9Sstevel@tonic-gate 			r++;
601*7c478bd9Sstevel@tonic-gate 			break;
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 		default:
604*7c478bd9Sstevel@tonic-gate 			break;
605*7c478bd9Sstevel@tonic-gate 		}
606*7c478bd9Sstevel@tonic-gate 	}
607*7c478bd9Sstevel@tonic-gate 	return (PAM_SUCCESS);
608*7c478bd9Sstevel@tonic-gate }
609