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