xref: /csrg-svn/libexec/uucpd/uucpd.c (revision 18625)
1 #ifndef lint
2 static char sccsid[] = "@(#)uucpd.c	5.3 (Berkeley) 04/10/85";
3 #endif
4 
5 /*
6  * 4.2BSD TCP/IP server for uucico
7  * uucico's TCP channel causes this server to be run at the remote end.
8  */
9 
10 #include "uucp.h"
11 #include <signal.h>
12 #include <errno.h>
13 #include <sys/socket.h>
14 #include <sys/ioctl.h>
15 #include <netinet/in.h>
16 #include <netdb.h>
17 #include <sys/wait.h>
18 #include <pwd.h>
19 #include <lastlog.h>
20 
21 char lastlog[] = "/usr/adm/lastlog";
22 struct	sockaddr_in hisctladdr;
23 int hisaddrlen = sizeof hisctladdr;
24 struct	sockaddr_in myctladdr;
25 int mypid;
26 
27 main(argc, argv)
28 int argc;
29 char **argv;
30 {
31 #ifndef BSDINETD
32 	register int s, tcp_socket;
33 	struct servent *sp;
34 #endif !BSDINETD
35 	extern int errno;
36 	int dologout();
37 
38 #ifdef BSDINETD
39 	close(1); close(2);
40 	dup(0); dup(0);
41 	hisaddrlen = sizeof (hisctladdr);
42 	if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
43 		fprintf(stderr, "%s: ", argv[0]);
44 		perror("getpeername");
45 		_exit(1);
46 	}
47 	if (fork() == 0)
48 		doit(&hisctladdr);
49 	dologout();
50 	exit(1);
51 #else !BSDINETD
52 	sp = getservbyname("uucp", "tcp");
53 	if (sp == NULL){
54 		perror("uucpd: getservbyname");
55 		exit(1);
56 	}
57 	if ((s=open("/dev/tty", 2)) >= 0){
58 		ioctl(s, TIOCNOTTY, (char *)0);
59 		close(s);
60 	}
61 
62 	bzero((char *)&myctladdr, sizeof (myctladdr));
63 	tcp_socket = socket(AF_INET, SOCK_STREAM, 0, 0);
64 	if ( tcp_socket<0 ) {
65 		perror("uucpd: socket");
66 		exit(1);
67 	}
68 	myctladdr.sin_port = sp->s_port;
69 	if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr), 0) < 0) {
70 		perror("uucpd: bind");
71 		exit(1);
72 	}
73 	signal(SIGCHLD, dologout);
74 	listen(tcp_socket, 5);	/* 5's as good as any */
75 
76 	for(;;) {
77 		s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
78 		if (s < 0){
79 			if (errno == EINTR)
80 				continue;
81 			perror("uucpd: accept");
82 			exit(1);
83 		}
84 		if (fork()== 0) {
85 			close(0); close(1); close(2);
86 			dup(s); dup(s); dup(s);
87 			close(tcp_socket);close(s);
88 			doit(&hisctladdr);
89 			exit(1);
90 		}
91 		close(s);
92 	}
93 #endif
94 }
95 
96 doit(sinp)
97 struct sockaddr_in *sinp;
98 {
99 	char user[64];
100 	char passwd[64];
101 	char *xpasswd, *crypt();
102 	struct passwd *pw, *getpwnam();
103 
104 	alarm(60);
105 	printf("login: "); fflush(stdout);
106 	if (readline(user, sizeof user) < 0) {
107 		fprintf(stderr, "user read\n");
108 		return;
109 	}
110 	/* truncate username to 8 characters */
111 	user[8] = '\0';
112 	pw = getpwnam(user);
113 	if (pw == NULL) {
114 		fprintf(stderr, "user unknown\n");
115 		return;
116 	}
117 	if (strcmp(pw->pw_shell, UUCICO)) {
118 		fprintf(stderr, "Login incorrect.");
119 		return;
120 	}
121 	if (pw->pw_passwd && *pw->pw_passwd != '\0') {
122 		printf("Password: "); fflush(stdout);
123 		if (readline(passwd, sizeof passwd) < 0) {
124 			fprintf(stderr, "passwd read\n");
125 			return;
126 		}
127 		xpasswd = crypt(passwd, pw->pw_passwd);
128 		if (strcmp(xpasswd, pw->pw_passwd)) {
129 			fprintf(stderr, "Login incorrect.");
130 			return;
131 		}
132 	}
133 	alarm(0);
134 	dologin(pw, sinp);
135 	setegid(pw->pw_gid);
136 	initgroups(pw->pw_name, pw->pw_gid);
137 	chdir(pw->pw_dir);
138 	seteuid(pw->pw_uid);
139 	execl(UUCICO, "uucico", (char *)0);
140 	perror("uucico server: execl");
141 }
142 
143 readline(p, n)
144 register char *p;
145 register int n;
146 {
147 	char c;
148 
149 	while (n-- > 0) {
150 		if (read(0, &c, 1) <= 0)
151 			return(-1);
152 		c &= 0177;
153 		if (c == '\n' || c == '\r') {
154 			*p = '\0';
155 			return(0);
156 		}
157 		*p++ = c;
158 	}
159 	return(-1);
160 }
161 
162 #include <utmp.h>
163 #include <fcntl.h>
164 
165 #define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
166 
167 struct	utmp utmp;
168 
169 dologout()
170 {
171 	union wait status;
172 	int pid, wtmp;
173 
174 #ifdef BSDINETD
175 	while ((pid=wait(&status)) > 0 ) {
176 #else  !BSDINETD
177 	while ((pid=wait3(&status,WNOHANG,0)) > 0 ) {
178 #endif !BSDINETD
179 		wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
180 		if (wtmp >= 0) {
181 			sprintf(utmp.ut_line, "uucp%.4d", pid);
182 			SCPYN(utmp.ut_name, "");
183 			SCPYN(utmp.ut_host, "");
184 			utmp.ut_time = time(0);
185 			(void) write(wtmp, (char *)&utmp, sizeof (utmp));
186 			(void) close(wtmp);
187 		}
188 	}
189 }
190 
191 /*
192  * Record login in wtmp file.
193  */
194 dologin(pw, sin)
195 struct passwd *pw;
196 struct sockaddr_in *sin;
197 {
198 	char line[32];
199 	char remotehost[32];
200 	int wtmp, f;
201 	struct hostent *hp = gethostbyaddr(&sin->sin_addr,
202 		sizeof (struct in_addr), AF_INET);
203 
204 	if (hp) {
205 		strncpy(remotehost, hp->h_name, sizeof (remotehost));
206 		endhostent();
207 	} else
208 		strncpy(remotehost, inet_ntoa(sin->sin_addr),
209 		    sizeof (remotehost));
210 	wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
211 	if (wtmp >= 0) {
212 		/* hack, but must be unique and no tty line */
213 		sprintf(line, "uucp%.4d", getpid());
214 		SCPYN(utmp.ut_line, line);
215 		SCPYN(utmp.ut_name, pw->pw_name);
216 		SCPYN(utmp.ut_host, remotehost);
217 		utmp.ut_time = time(0);
218 		(void) write(wtmp, (char *)&utmp, sizeof (utmp));
219 		(void) close(wtmp);
220 	}
221 	if ((f = open(lastlog, 2)) >= 0) {
222 		struct lastlog ll;
223 
224 		time(&ll.ll_time);
225 		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
226 		strcpy(line, remotehost);
227 		SCPYN(ll.ll_line, line);
228 		SCPYN(ll.ll_host, remotehost);
229 		(void) write(f, (char *) &ll, sizeof ll);
230 		(void) close(f);
231 	}
232 }
233