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