Commit | Line | Data |
---|---|---|
d185cb11 | 1 | /* |
dc45ba8c | 2 | * Copyright (c) 1983 Eric P. Allman |
710322bb KB |
3 | * Copyright (c) 1988 Regents of the University of California. |
4 | * All rights reserved. | |
5 | * | |
417f7a11 | 6 | * %sccs.include.redist.c% |
710322bb | 7 | */ |
d185cb11 | 8 | |
d0432129 | 9 | #include <errno.h> |
49c069a9 | 10 | #include <signal.h> |
97543758 | 11 | #include "sendmail.h" |
6b6d57eb | 12 | # include <sys/mx.h> |
ef34cbda | 13 | |
710322bb KB |
14 | #ifndef lint |
15 | #ifdef DAEMON | |
f10d3e38 | 16 | static char sccsid[] = "@(#)daemon.c 6.48 (Berkeley) %G% (with daemon mode)"; |
710322bb | 17 | #else |
f10d3e38 | 18 | static char sccsid[] = "@(#)daemon.c 6.48 (Berkeley) %G% (without daemon mode)"; |
710322bb KB |
19 | #endif |
20 | #endif /* not lint */ | |
21 | ||
22 | #ifdef DAEMON | |
17a67c62 | 23 | |
17a67c62 EA |
24 | # include <netdb.h> |
25 | # include <sys/wait.h> | |
26 | # include <sys/time.h> | |
17a67c62 | 27 | |
ab6ca5e5 EA |
28 | #ifdef NAMED_BIND |
29 | # include <arpa/nameser.h> | |
30 | # include <resolv.h> | |
31 | #endif | |
32 | ||
ef34cbda EA |
33 | /* |
34 | ** DAEMON.C -- routines to use when running as a daemon. | |
2a16bae3 EA |
35 | ** |
36 | ** This entire file is highly dependent on the 4.2 BSD | |
37 | ** interprocess communication primitives. No attempt has | |
38 | ** been made to make this file portable to Version 7, | |
39 | ** Version 6, MPX files, etc. If you should try such a | |
40 | ** thing yourself, I recommend chucking the entire file | |
41 | ** and starting from scratch. Basic semantics are: | |
42 | ** | |
43 | ** getrequests() | |
44 | ** Opens a port and initiates a connection. | |
45 | ** Returns in a child. Must set InChannel and | |
46 | ** OutChannel appropriately. | |
eb8af3ce EA |
47 | ** clrdaemon() |
48 | ** Close any open files associated with getting | |
49 | ** the connection; this is used when running the queue, | |
50 | ** etc., to avoid having extra file descriptors during | |
51 | ** the queue run and to avoid confusing the network | |
52 | ** code (if it cares). | |
8657d05f | 53 | ** makeconnection(host, port, outfile, infile, usesecureport) |
2a16bae3 EA |
54 | ** Make a connection to the named host on the given |
55 | ** port. Set *outfile and *infile to the files | |
56 | ** appropriate for communication. Returns zero on | |
57 | ** success, else an exit status describing the | |
58 | ** error. | |
5a4c03c6 EA |
59 | ** maphostname(map, hbuf, hbufsiz, avp) |
60 | ** Convert the entry in hbuf into a canonical form. | |
ef34cbda | 61 | */ |
6b6d57eb | 62 | |
3341995c EA |
63 | extern char *anynet_ntoa(); |
64 | ||
6b6d57eb | 65 | static FILE *MailPort; /* port that mail comes in on */ |
ef34cbda EA |
66 | \f/* |
67 | ** GETREQUESTS -- open mail IPC port and get requests. | |
68 | ** | |
69 | ** Parameters: | |
70 | ** none. | |
71 | ** | |
72 | ** Returns: | |
73 | ** none. | |
74 | ** | |
75 | ** Side Effects: | |
76 | ** Waits until some interesting activity occurs. When | |
77 | ** it does, a child is created to process it, and the | |
78 | ** parent waits for completion. Return from this | |
40d27fed EA |
79 | ** routine is always in the child. The file pointers |
80 | ** "InChannel" and "OutChannel" should be set to point | |
81 | ** to the communication channel. | |
ef34cbda EA |
82 | */ |
83 | ||
8829f52e EA |
84 | int DaemonSocket = -1; /* fd describing socket */ |
85 | SOCKADDR DaemonAddr; /* socket for incoming */ | |
278c561a | 86 | int ListenQueueSize = 10; /* size of listen queue */ |
14a39063 | 87 | |
7f108496 | 88 | getrequests() |
14a39063 | 89 | { |
7e3417e6 | 90 | int t; |
7f108496 | 91 | register struct servent *sp; |
4ff794a3 | 92 | int on = 1; |
a90a7c55 | 93 | bool refusingconnections = TRUE; |
654398d7 | 94 | FILE *pidf; |
0df908a9 | 95 | extern void reapchild(); |
14a39063 EA |
96 | |
97 | /* | |
98 | ** Set up the address for the mailer. | |
99 | */ | |
100 | ||
8829f52e EA |
101 | if (DaemonAddr.sin.sin_family == 0) |
102 | DaemonAddr.sin.sin_family = AF_INET; | |
103 | if (DaemonAddr.sin.sin_addr.s_addr == 0) | |
104 | DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; | |
105 | if (DaemonAddr.sin.sin_port == 0) | |
7f108496 | 106 | { |
8829f52e EA |
107 | sp = getservbyname("smtp", "tcp"); |
108 | if (sp == NULL) | |
109 | { | |
9964213c | 110 | syserr("554 service \"smtp\" unknown"); |
8829f52e EA |
111 | goto severe; |
112 | } | |
113 | DaemonAddr.sin.sin_port = sp->s_port; | |
7f108496 | 114 | } |
14a39063 EA |
115 | |
116 | /* | |
117 | ** Try to actually open the connection. | |
118 | */ | |
119 | ||
9678c96d | 120 | if (tTd(15, 1)) |
8829f52e | 121 | printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); |
14a39063 | 122 | |
7f108496 | 123 | /* get a socket for the SMTP connection */ |
4a50272d | 124 | DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); |
eb8af3ce | 125 | if (DaemonSocket < 0) |
4b5cf74c | 126 | { |
7f108496 EA |
127 | /* probably another daemon already */ |
128 | syserr("getrequests: can't create socket"); | |
129 | severe: | |
130 | # ifdef LOG | |
131 | if (LogLevel > 0) | |
f3d8f6d6 | 132 | # endif /* LOG */ |
7f108496 EA |
133 | finis(); |
134 | } | |
78c9dc29 | 135 | |
78c9dc29 | 136 | /* turn on network debugging? */ |
d0a69620 | 137 | if (tTd(15, 101)) |
bb812c0b | 138 | (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); |
78c9dc29 | 139 | |
4ff794a3 EA |
140 | (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); |
141 | (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); | |
142 | ||
4a50272d EA |
143 | switch (DaemonAddr.sa.sa_family) |
144 | { | |
145 | # ifdef NETINET | |
146 | case AF_INET: | |
147 | t = sizeof DaemonAddr.sin; | |
148 | break; | |
149 | # endif | |
150 | ||
151 | # ifdef NETISO | |
152 | case AF_ISO: | |
153 | t = sizeof DaemonAddr.siso; | |
154 | break; | |
155 | # endif | |
156 | ||
157 | default: | |
158 | t = sizeof DaemonAddr; | |
159 | break; | |
160 | } | |
161 | ||
162 | if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0) | |
7f108496 EA |
163 | { |
164 | syserr("getrequests: cannot bind"); | |
eb8af3ce | 165 | (void) close(DaemonSocket); |
7f108496 EA |
166 | goto severe; |
167 | } | |
14a39063 | 168 | |
8ff78b51 | 169 | (void) signal(SIGCHLD, reapchild); |
199d34eb | 170 | |
654398d7 EA |
171 | /* write the pid to the log file for posterity */ |
172 | pidf = fopen(PidFile, "w"); | |
173 | if (pidf != NULL) | |
174 | { | |
175 | fprintf(pidf, "%d\n", getpid()); | |
176 | fclose(pidf); | |
177 | } | |
178 | ||
179 | ||
7f108496 | 180 | if (tTd(15, 1)) |
eb8af3ce | 181 | printf("getrequests: %d\n", DaemonSocket); |
2a16bae3 | 182 | |
7f108496 EA |
183 | struct wh wbuf; |
184 | ||
185 | wbuf.index = index; | |
186 | wbuf.count = 0; | |
187 | wbuf.ccount = cnt; | |
188 | wbuf.data = buf; | |
189 | write(MailPort, &wbuf, sizeof wbuf); | |
14a39063 | 190 | } |
1ab402f2 EA |
191 | \f/* |
192 | ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. | |
193 | ** | |
194 | ** Parameters: | |
195 | ** host -- the name of the host. | |
e2d7c32a | 196 | ** port -- the port number to connect to. |
2ae0e0ed EA |
197 | ** mci -- a pointer to the mail connection information |
198 | ** structure to be filled in. | |
8657d05f EA |
199 | ** usesecureport -- if set, use a low numbered (reserved) |
200 | ** port to provide some rudimentary authentication. | |
1ab402f2 EA |
201 | ** |
202 | ** Returns: | |
203 | ** An exit code telling whether the connection could be | |
204 | ** made and if not why not. | |
205 | ** | |
206 | ** Side Effects: | |
207 | ** none. | |
208 | */ | |
209 | ||
3341995c | 210 | SOCKADDR CurHostAddr; /* address of current host */ |
9b95d94a | 211 | |
f2e44ded | 212 | int |
2ae0e0ed | 213 | makeconnection(host, port, mci, usesecureport) |
1ab402f2 | 214 | char *host; |
f7eb07a3 | 215 | u_short port; |
f2e44ded | 216 | register MCI *mci; |
8657d05f | 217 | bool usesecureport; |
1ab402f2 | 218 | { |
9e881165 JB |
219 | register int i, s; |
220 | register struct hostent *hp = (struct hostent *)NULL; | |
3341995c | 221 | SOCKADDR addr; |
fa163d3c | 222 | int sav_errno; |
3341995c | 223 | int addrlen; |
35af2f06 EA |
224 | #ifdef NAMED_BIND |
225 | extern int h_errno; | |
226 | #endif | |
1ab402f2 EA |
227 | |
228 | /* | |
229 | ** Set up the address for the mailer. | |
b3e29341 | 230 | ** Accept "[a.b.c.d]" syntax for host name. |
1ab402f2 EA |
231 | */ |
232 | ||
35af2f06 | 233 | #ifdef NAMED_BIND |
459e21be | 234 | h_errno = 0; |
35af2f06 | 235 | #endif |
459e21be | 236 | errno = 0; |
f66cc88e | 237 | bzero(&CurHostAddr, sizeof CurHostAddr); |
f53bb556 | 238 | CurHostName = host; |
459e21be | 239 | |
b3e29341 EA |
240 | if (host[0] == '[') |
241 | { | |
e56baaff | 242 | long hid; |
f3d8f6d6 | 243 | register char *p = strchr(host, ']'); |
b3e29341 | 244 | |
e56baaff | 245 | if (p != NULL) |
b3e29341 | 246 | { |
e56baaff | 247 | *p = '\0'; |
69d3adf7 | 248 | #ifdef NETINET |
e56baaff | 249 | hid = inet_addr(&host[1]); |
b120ff69 | 250 | if (hid == -1) |
69d3adf7 | 251 | #endif |
b120ff69 EA |
252 | { |
253 | /* try it as a host name (avoid MX lookup) */ | |
254 | hp = gethostbyname(&host[1]); | |
255 | *p = ']'; | |
256 | goto gothostent; | |
257 | } | |
e56baaff | 258 | *p = ']'; |
b3e29341 | 259 | } |
b120ff69 | 260 | if (p == NULL) |
b3e29341 | 261 | { |
b6edea3d | 262 | usrerr("553 Invalid numeric domain spec \"%s\"", host); |
b3e29341 EA |
263 | return (EX_NOHOST); |
264 | } | |
69d3adf7 EA |
265 | #ifdef NETINET |
266 | addr.sin.sin_family = AF_INET; /*XXX*/ | |
3356c77c | 267 | addr.sin.sin_addr.s_addr = hid; |
69d3adf7 | 268 | #endif |
b3e29341 | 269 | } |
7f108496 EA |
270 | else |
271 | { | |
9e881165 | 272 | hp = gethostbyname(host); |
b120ff69 | 273 | gothostent: |
e56baaff | 274 | if (hp == NULL) |
459e21be | 275 | { |
35af2f06 | 276 | #ifdef NAMED_BIND |
459e21be | 277 | if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) |
459e21be | 278 | return (EX_TEMPFAIL); |
8da74c93 | 279 | |
35af2f06 EA |
280 | /* if name server is specified, assume temp fail */ |
281 | if (errno == ECONNREFUSED && UseNameServer) | |
282 | return (EX_TEMPFAIL); | |
283 | #endif | |
7f108496 | 284 | return (EX_NOHOST); |
459e21be | 285 | } |
3356c77c EA |
286 | addr.sa.sa_family = hp->h_addrtype; |
287 | switch (hp->h_addrtype) | |
288 | { | |
289 | #ifdef NETINET | |
290 | case AF_INET: | |
3341995c | 291 | bcopy(hp->h_addr, |
3356c77c | 292 | &addr.sin.sin_addr, |
3341995c | 293 | hp->h_length); |
3356c77c EA |
294 | break; |
295 | #endif | |
296 | ||
297 | default: | |
3341995c | 298 | bcopy(hp->h_addr, |
3356c77c | 299 | addr.sa.sa_data, |
3341995c | 300 | hp->h_length); |
3356c77c EA |
301 | break; |
302 | } | |
9e881165 | 303 | i = 1; |
7f108496 EA |
304 | } |
305 | ||
306 | /* | |
307 | ** Determine the port number. | |
308 | */ | |
309 | ||
372c9e7f | 310 | if (port != 0) |
3341995c | 311 | port = htons(port); |
372c9e7f | 312 | else |
7f108496 EA |
313 | { |
314 | register struct servent *sp = getservbyname("smtp", "tcp"); | |
315 | ||
316 | if (sp == NULL) | |
317 | { | |
9964213c | 318 | syserr("554 makeconnection: service \"smtp\" unknown"); |
aa102c71 | 319 | return (EX_OSERR); |
7f108496 | 320 | } |
3341995c EA |
321 | port = sp->s_port; |
322 | } | |
323 | ||
3356c77c | 324 | switch (addr.sa.sa_family) |
3341995c | 325 | { |
69d3adf7 | 326 | #ifdef NETINET |
3341995c | 327 | case AF_INET: |
3356c77c | 328 | addr.sin.sin_port = port; |
3341995c EA |
329 | addrlen = sizeof (struct sockaddr_in); |
330 | break; | |
69d3adf7 | 331 | #endif |
3341995c EA |
332 | |
333 | #ifdef NETISO | |
334 | case AF_ISO: | |
335 | /* assume two byte transport selector */ | |
336 | bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); | |
337 | addrlen = sizeof (struct sockaddr_iso); | |
338 | break; | |
339 | #endif | |
340 | ||
341 | default: | |
3356c77c | 342 | syserr("Can't connect to address family %d", addr.sa.sa_family); |
3341995c | 343 | return (EX_NOHOST); |
7f108496 | 344 | } |
1ab402f2 EA |
345 | |
346 | /* | |
347 | ** Try to actually open the connection. | |
348 | */ | |
349 | ||
b4f81c5d EA |
350 | #ifdef XLA |
351 | /* if too many connections, don't bother trying */ | |
352 | if (!xla_noqueue_ok(host)) | |
353 | return EX_TEMPFAIL; | |
354 | #endif | |
355 | ||
6feb509e | 356 | for (;;) |
8657d05f | 357 | { |
6feb509e | 358 | if (tTd(16, 1)) |
3341995c EA |
359 | printf("makeconnection (%s [%s])\n", |
360 | host, anynet_ntoa(&addr)); | |
8657d05f | 361 | |
83c07d72 EA |
362 | /* save for logging */ |
363 | CurHostAddr = addr; | |
364 | ||
6feb509e EA |
365 | if (usesecureport) |
366 | { | |
367 | int rport = IPPORT_RESERVED - 1; | |
368 | ||
369 | s = rresvport(&rport); | |
370 | } | |
371 | else | |
372 | { | |
373 | s = socket(AF_INET, SOCK_STREAM, 0); | |
374 | } | |
375 | if (s < 0) | |
376 | { | |
377 | sav_errno = errno; | |
378 | syserr("makeconnection: no socket"); | |
379 | goto failure; | |
380 | } | |
1ab402f2 | 381 | |
6feb509e EA |
382 | if (tTd(16, 1)) |
383 | printf("makeconnection: fd=%d\n", s); | |
78c9dc29 | 384 | |
6feb509e EA |
385 | /* turn on network debugging? */ |
386 | if (tTd(16, 101)) | |
387 | { | |
388 | int on = 1; | |
389 | (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, | |
390 | (char *)&on, sizeof on); | |
391 | } | |
392 | if (CurEnv->e_xfp != NULL) | |
393 | (void) fflush(CurEnv->e_xfp); /* for debugging */ | |
394 | errno = 0; /* for debugging */ | |
3341995c | 395 | if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) |
6feb509e EA |
396 | break; |
397 | ||
398 | /* couldn't connect.... figure out why */ | |
fa163d3c JB |
399 | sav_errno = errno; |
400 | (void) close(s); | |
9e881165 JB |
401 | if (hp && hp->h_addr_list[i]) |
402 | { | |
3341995c EA |
403 | extern char *errstring(); |
404 | ||
6feb509e | 405 | if (tTd(16, 1)) |
3341995c EA |
406 | printf("Connect failed (%s); trying new address....\n", |
407 | errstring(sav_errno)); | |
3356c77c EA |
408 | switch (addr.sa.sa_family) |
409 | { | |
410 | #ifdef NETINET | |
411 | case AF_INET: | |
3341995c | 412 | bcopy(hp->h_addr_list[i++], |
3356c77c | 413 | &addr.sin.sin_addr, |
3341995c | 414 | hp->h_length); |
3356c77c EA |
415 | break; |
416 | #endif | |
417 | ||
418 | default: | |
3341995c | 419 | bcopy(hp->h_addr_list[i++], |
3356c77c | 420 | addr.sa.sa_data, |
8657d05f | 421 | hp->h_length); |
3356c77c EA |
422 | break; |
423 | } | |
6feb509e | 424 | continue; |
9e881165 JB |
425 | } |
426 | ||
1ab402f2 EA |
427 | /* failure, decide if temporary or not */ |
428 | failure: | |
46500bf5 EA |
429 | #ifdef XLA |
430 | xla_host_end(host); | |
431 | #endif | |
1eaa5615 EA |
432 | if (transienterror(sav_errno)) |
433 | return EX_TEMPFAIL; | |
1eaa5615 EA |
434 | else |
435 | { | |
436 | extern char *errstring(); | |
e56baaff | 437 | |
1eaa5615 EA |
438 | message("%s", errstring(sav_errno)); |
439 | return (EX_UNAVAILABLE); | |
1ab402f2 EA |
440 | } |
441 | } | |
442 | ||
443 | /* connection ok, put it into canonical form */ | |
06771186 EA |
444 | mci->mci_out = fdopen(s, "w"); |
445 | mci->mci_in = fdopen(dup(s), "r"); | |
1ab402f2 | 446 | |
1aaa7dec | 447 | return (EX_OK); |
1ab402f2 | 448 | } |
2ec2faaa EA |
449 | \f/* |
450 | ** MYHOSTNAME -- return the name of this host. | |
451 | ** | |
452 | ** Parameters: | |
453 | ** hostbuf -- a place to return the name of this host. | |
05894fc6 | 454 | ** size -- the size of hostbuf. |
2ec2faaa EA |
455 | ** |
456 | ** Returns: | |
457 | ** A list of aliases for this host. | |
458 | ** | |
459 | ** Side Effects: | |
740d17b3 | 460 | ** Sets the MyIpAddrs buffer to a list of my IP addresses. |
2ec2faaa EA |
461 | */ |
462 | ||
740d17b3 EA |
463 | struct in_addr MyIpAddrs[MAXIPADDR + 1]; |
464 | ||
2ec2faaa | 465 | char ** |
05894fc6 | 466 | myhostname(hostbuf, size) |
2ec2faaa | 467 | char hostbuf[]; |
05894fc6 | 468 | int size; |
2ec2faaa | 469 | { |
740d17b3 | 470 | register struct hostent *hp; |
2ec2faaa | 471 | extern struct hostent *gethostbyname(); |
2ec2faaa | 472 | |
17a67c62 EA |
473 | if (gethostname(hostbuf, size) < 0) |
474 | { | |
475 | (void) strcpy(hostbuf, "localhost"); | |
476 | } | |
e56baaff EA |
477 | hp = gethostbyname(hostbuf); |
478 | if (hp != NULL) | |
b9b481e2 | 479 | { |
740d17b3 EA |
480 | (void) strncpy(hostbuf, hp->h_name, size - 1); |
481 | hostbuf[size - 1] = '\0'; | |
482 | ||
483 | if (hp->h_addrtype == AF_INET && hp->h_length == 4) | |
484 | { | |
485 | register int i; | |
486 | ||
487 | for (i = 0; i < MAXIPADDR; i++) | |
488 | { | |
489 | if (hp->h_addr_list[i] == NULL) | |
490 | break; | |
491 | MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; | |
492 | } | |
493 | MyIpAddrs[i].s_addr = 0; | |
494 | } | |
495 | ||
e56baaff | 496 | return (hp->h_aliases); |
b9b481e2 | 497 | } |
2ec2faaa EA |
498 | else |
499 | return (NULL); | |
500 | } | |
bbfde42f | 501 | \f/* |
3f03d7a7 EA |
502 | ** GETAUTHINFO -- get the real host name asociated with a file descriptor |
503 | ** | |
504 | ** Uses RFC1413 protocol to try to get info from the other end. | |
5973222c EA |
505 | ** |
506 | ** Parameters: | |
507 | ** fd -- the descriptor | |
508 | ** | |
509 | ** Returns: | |
3f03d7a7 | 510 | ** The user@host information associated with this descriptor. |
5973222c EA |
511 | ** |
512 | ** Side Effects: | |
3f03d7a7 | 513 | ** Sets RealHostName to the name of the host at the other end. |
5973222c EA |
514 | */ |
515 | ||
3f03d7a7 EA |
516 | #ifdef IDENTPROTO |
517 | ||
518 | static jmp_buf CtxAuthTimeout; | |
519 | ||
520 | static | |
521 | authtimeout() | |
522 | { | |
523 | longjmp(CtxAuthTimeout, 1); | |
524 | } | |
525 | ||
526 | #endif | |
527 | ||
5973222c | 528 | char * |
3f03d7a7 | 529 | getauthinfo(fd) |
5973222c EA |
530 | int fd; |
531 | { | |
3f03d7a7 EA |
532 | SOCKADDR fa; |
533 | int falen; | |
72bc63d1 | 534 | register char *p; |
3f03d7a7 EA |
535 | #ifdef IDENTPROTO |
536 | SOCKADDR la; | |
537 | int lalen; | |
538 | register struct servent *sp; | |
539 | int s; | |
540 | int i; | |
3f03d7a7 EA |
541 | EVENT *ev; |
542 | #endif | |
543 | static char hbuf[MAXNAME * 2 + 2]; | |
544 | extern char *hostnamebyanyaddr(); | |
545 | extern char RealUserName[]; /* main.c */ | |
546 | ||
547 | falen = sizeof fa; | |
548 | if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) | |
549 | { | |
550 | RealHostName = "localhost"; | |
551 | (void) sprintf(hbuf, "%s@localhost", RealUserName); | |
a9bac7a9 | 552 | if (tTd(9, 1)) |
3f03d7a7 EA |
553 | printf("getauthinfo: %s\n", hbuf); |
554 | return hbuf; | |
555 | } | |
556 | ||
557 | RealHostName = newstr(hostnamebyanyaddr(&fa)); | |
558 | RealHostAddr = fa; | |
559 | ||
560 | #ifdef IDENTPROTO | |
561 | lalen = sizeof la; | |
562 | if (fa.sa.sa_family != AF_INET || | |
563 | getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || | |
564 | la.sa.sa_family != AF_INET) | |
565 | { | |
566 | /* no ident info */ | |
567 | goto noident; | |
568 | } | |
569 | ||
570 | /* create ident query */ | |
571 | (void) sprintf(hbuf, "%d,%d\r\n", fa.sin.sin_port, la.sin.sin_port); | |
572 | ||
573 | /* create local address */ | |
574 | bzero(&la, sizeof la); | |
575 | ||
576 | /* create foreign address */ | |
577 | sp = getservbyname("auth", "tcp"); | |
578 | if (sp != NULL) | |
579 | fa.sin.sin_port = sp->s_port; | |
5973222c | 580 | else |
696f60e3 | 581 | fa.sin.sin_port = htons(113); |
3f03d7a7 EA |
582 | |
583 | s = -1; | |
584 | if (setjmp(CtxAuthTimeout) != 0) | |
585 | { | |
586 | if (s >= 0) | |
587 | (void) close(s); | |
588 | goto noident; | |
589 | } | |
590 | ||
591 | /* put a timeout around the whole thing */ | |
592 | ev = setevent((time_t) 30, authtimeout, 0); | |
593 | ||
594 | /* connect to foreign IDENT server */ | |
595 | s = socket(AF_INET, SOCK_STREAM, 0); | |
596 | if (s < 0) | |
597 | { | |
598 | clrevent(ev); | |
599 | goto noident; | |
600 | } | |
601 | if (connect(s, &fa.sa, sizeof fa.sin) < 0) | |
602 | { | |
603 | closeident: | |
604 | (void) close(s); | |
605 | clrevent(ev); | |
606 | goto noident; | |
607 | } | |
608 | ||
a9bac7a9 | 609 | if (tTd(9, 10)) |
3f03d7a7 EA |
610 | printf("getauthinfo: sent %s", hbuf); |
611 | ||
612 | /* send query */ | |
613 | if (write(s, hbuf, strlen(hbuf)) < 0) | |
614 | goto closeident; | |
615 | ||
616 | /* get result */ | |
617 | i = read(s, hbuf, sizeof hbuf); | |
618 | (void) close(s); | |
619 | clrevent(ev); | |
620 | if (i <= 0) | |
621 | goto noident; | |
622 | if (hbuf[--i] == '\n' && hbuf[--i] == '\r') | |
623 | i--; | |
624 | hbuf[++i] = '\0'; | |
625 | ||
a9bac7a9 | 626 | if (tTd(9, 3)) |
3f03d7a7 EA |
627 | printf("getauthinfo: got %s\n", hbuf); |
628 | ||
629 | /* parse result */ | |
630 | p = strchr(hbuf, ':'); | |
631 | if (p == NULL) | |
632 | { | |
633 | /* malformed response */ | |
634 | goto noident; | |
635 | } | |
636 | while (isascii(*++p) && isspace(*p)) | |
637 | continue; | |
638 | if (strncasecmp(p, "userid", 6) != 0) | |
639 | { | |
640 | /* presumably an error string */ | |
641 | goto noident; | |
642 | } | |
643 | p += 6; | |
644 | while (isascii(*p) && isspace(*p)) | |
645 | p++; | |
646 | if (*p++ != ':') | |
647 | { | |
648 | /* either useridxx or malformed response */ | |
649 | goto noident; | |
650 | } | |
651 | ||
652 | /* p now points to the OSTYPE field */ | |
653 | p = strchr(p, ':'); | |
654 | if (p == NULL) | |
655 | { | |
656 | /* malformed response */ | |
657 | goto noident; | |
658 | } | |
a9bac7a9 EA |
659 | |
660 | /* 1413 says don't do this -- but it's broken otherwise */ | |
661 | while (isascii(*++p) && isspace(*p)) | |
662 | continue; | |
3f03d7a7 EA |
663 | |
664 | /* p now points to the authenticated name */ | |
665 | (void) sprintf(hbuf, "%s@%s", p, RealHostName); | |
a9bac7a9 EA |
666 | goto finish; |
667 | ||
668 | #endif /* IDENTPROTO */ | |
669 | ||
670 | noident: | |
671 | (void) strcpy(hbuf, RealHostName); | |
672 | ||
673 | finish: | |
3f03d7a7 EA |
674 | if (RealHostName[0] != '[') |
675 | { | |
676 | p = &hbuf[strlen(hbuf)]; | |
677 | (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); | |
678 | } | |
a9bac7a9 | 679 | if (tTd(9, 1)) |
3f03d7a7 | 680 | printf("getauthinfo: %s\n", hbuf); |
5973222c EA |
681 | return hbuf; |
682 | } | |
683 | \f/* | |
42fa5d67 EA |
684 | ** MAPHOSTNAME -- turn a hostname into canonical form |
685 | ** | |
686 | ** Parameters: | |
5a4c03c6 | 687 | ** map -- a pointer to this map (unused). |
42fa5d67 EA |
688 | ** hbuf -- a buffer containing a hostname. |
689 | ** hbsize -- the size of hbuf. | |
0cf5a7ba EA |
690 | ** avp -- unused -- for compatibility with other mapping |
691 | ** functions. | |
d1db7a89 EA |
692 | ** statp -- an exit status (out parameter) -- set to |
693 | ** EX_TEMPFAIL if the name server is unavailable. | |
42fa5d67 EA |
694 | ** |
695 | ** Returns: | |
696 | ** The mapping, if found. | |
697 | ** NULL if no mapping found. | |
698 | ** | |
699 | ** Side Effects: | |
700 | ** Looks up the host specified in hbuf. If it is not | |
701 | ** the canonical name for that host, return the canonical | |
702 | ** name. | |
703 | */ | |
bbfde42f | 704 | |
42fa5d67 | 705 | char * |
d1db7a89 | 706 | maphostname(map, hbuf, hbsize, avp, statp) |
5a4c03c6 | 707 | MAP *map; |
217a0102 EA |
708 | char *hbuf; |
709 | int hbsize; | |
42fa5d67 | 710 | char **avp; |
d1db7a89 | 711 | int *statp; |
217a0102 EA |
712 | { |
713 | register struct hostent *hp; | |
d0432129 | 714 | u_long in_addr; |
5a4c03c6 | 715 | char *cp; |
740d17b3 | 716 | int i; |
b97dd58b EA |
717 | register STAB *s; |
718 | extern struct hostent *gethostbyaddr(); | |
719 | extern int h_errno; | |
217a0102 | 720 | |
32fd13db | 721 | /* allow room for null */ |
5a4c03c6 | 722 | hbsize--; |
42fa5d67 | 723 | |
33e4da31 | 724 | /* |
b97dd58b EA |
725 | ** See if we have already looked up this name. If so, just |
726 | ** return it. | |
727 | */ | |
728 | ||
729 | s = stab(hbuf, ST_NAMECANON, ST_ENTER); | |
730 | if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) | |
731 | { | |
d3b6a883 EA |
732 | if (tTd(9, 1)) |
733 | printf("maphostname(%s, %d) => CACHE %s\n", | |
734 | hbuf, hbsize, s->s_namecanon.nc_cname); | |
b97dd58b EA |
735 | errno = s->s_namecanon.nc_errno; |
736 | h_errno = s->s_namecanon.nc_herrno; | |
737 | *statp = s->s_namecanon.nc_stat; | |
738 | return s->s_namecanon.nc_cname; | |
739 | } | |
740 | ||
741 | /* | |
742 | ** If first character is a bracket, then it is an address | |
743 | ** lookup. Address is copied into a temporary buffer to | |
744 | ** strip the brackets and to preserve hbuf if address is | |
745 | ** unknown. | |
746 | */ | |
42fa5d67 | 747 | |
bbfde42f | 748 | if (*hbuf != '[') |
42fa5d67 | 749 | { |
0cf5a7ba EA |
750 | extern bool getcanonname(); |
751 | ||
a97feb13 EA |
752 | if (tTd(9, 1)) |
753 | printf("maphostname(%s, %d) => ", hbuf, hbsize); | |
b97dd58b | 754 | s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ |
b32ed404 | 755 | if (getcanonname(hbuf, hbsize)) |
1d136a1f EA |
756 | { |
757 | if (tTd(9, 1)) | |
758 | printf("%s\n", hbuf); | |
b97dd58b | 759 | s->s_namecanon.nc_cname = newstr(hbuf); |
42fa5d67 | 760 | return hbuf; |
1d136a1f | 761 | } |
42fa5d67 | 762 | else |
1d136a1f | 763 | { |
d1db7a89 | 764 | register struct hostent *hp; |
d1db7a89 | 765 | |
1d136a1f | 766 | if (tTd(9, 1)) |
d1db7a89 | 767 | printf("FAIL (%d)\n", h_errno); |
b97dd58b EA |
768 | s->s_namecanon.nc_errno = errno; |
769 | s->s_namecanon.nc_herrno = h_errno; | |
d1db7a89 EA |
770 | switch (h_errno) |
771 | { | |
772 | case TRY_AGAIN: | |
c281eee3 | 773 | if (UseNameServer) |
7ffb494c EA |
774 | { |
775 | char *msg = "Recipient domain nameserver timed out"; | |
776 | ||
777 | message(msg); | |
778 | if (CurEnv->e_message == NULL) | |
f10d3e38 | 779 | CurEnv->e_message = newstr(msg); |
7ffb494c | 780 | } |
d1db7a89 EA |
781 | *statp = EX_TEMPFAIL; |
782 | break; | |
783 | ||
784 | case HOST_NOT_FOUND: | |
785 | *statp = EX_NOHOST; | |
786 | break; | |
787 | ||
788 | case NO_RECOVERY: | |
789 | *statp = EX_SOFTWARE; | |
790 | break; | |
791 | ||
792 | default: | |
793 | *statp = EX_UNAVAILABLE; | |
794 | break; | |
795 | } | |
b97dd58b | 796 | s->s_namecanon.nc_stat = *statp; |
d1db7a89 EA |
797 | if (*statp != EX_TEMPFAIL || UseNameServer) |
798 | return NULL; | |
799 | ||
800 | /* | |
801 | ** Try to look it up in /etc/hosts | |
802 | */ | |
803 | ||
804 | hp = gethostbyname(hbuf); | |
805 | if (hp == NULL) | |
806 | { | |
807 | /* no dice there either */ | |
b97dd58b | 808 | s->s_namecanon.nc_stat = *statp = EX_NOHOST; |
d1db7a89 EA |
809 | return NULL; |
810 | } | |
811 | ||
b97dd58b EA |
812 | s->s_namecanon.nc_stat = *statp = EX_OK; |
813 | s->s_namecanon.nc_cname = newstr(hp->h_name); | |
d1db7a89 | 814 | return hp->h_name; |
1d136a1f | 815 | } |
42fa5d67 | 816 | } |
5a4c03c6 | 817 | if ((cp = strchr(hbuf, ']')) == NULL) |
42fa5d67 | 818 | return (NULL); |
bd974b31 | 819 | *cp = '\0'; |
5a4c03c6 | 820 | in_addr = inet_addr(&hbuf[1]); |
740d17b3 EA |
821 | |
822 | /* check to see if this is one of our addresses */ | |
823 | for (i = 0; MyIpAddrs[i].s_addr != 0; i++) | |
824 | { | |
825 | if (MyIpAddrs[i].s_addr == in_addr) | |
826 | { | |
827 | strncpy(hbuf, MyHostName, hbsize); | |
828 | hbuf[hbsize] = '\0'; | |
829 | return hbuf; | |
830 | } | |
831 | } | |
832 | ||
833 | /* nope -- ask the name server */ | |
d0432129 | 834 | hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); |
b97dd58b EA |
835 | s->s_namecanon.nc_errno = errno; |
836 | s->s_namecanon.nc_herrno = h_errno; | |
837 | s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ | |
d0432129 | 838 | if (hp == NULL) |
b97dd58b EA |
839 | { |
840 | s->s_namecanon.nc_stat = *statp = EX_NOHOST; | |
42fa5d67 | 841 | return (NULL); |
b97dd58b | 842 | } |
42fa5d67 | 843 | |
740d17b3 | 844 | /* found a match -- copy out */ |
b97dd58b | 845 | s->s_namecanon.nc_cname = newstr(hp->h_name); |
5a4c03c6 EA |
846 | if (strlen(hp->h_name) > hbsize) |
847 | hp->h_name[hbsize] = '\0'; | |
42fa5d67 | 848 | (void) strcpy(hbuf, hp->h_name); |
b97dd58b | 849 | s->s_namecanon.nc_stat = *statp = EX_OK; |
42fa5d67 | 850 | return hbuf; |
217a0102 | 851 | } |
3341995c EA |
852 | \f/* |
853 | ** ANYNET_NTOA -- convert a network address to printable form. | |
854 | ** | |
855 | ** Parameters: | |
856 | ** sap -- a pointer to a sockaddr structure. | |
857 | ** | |
858 | ** Returns: | |
859 | ** A printable version of that sockaddr. | |
860 | */ | |
861 | ||
862 | char * | |
863 | anynet_ntoa(sap) | |
864 | register SOCKADDR *sap; | |
865 | { | |
866 | register char *bp; | |
867 | register char *ap; | |
868 | int l; | |
869 | static char buf[80]; | |
870 | ||
a97feb13 EA |
871 | /* check for null/zero family */ |
872 | if (sap == NULL) | |
873 | return "NULLADDR"; | |
874 | if (sap->sa.sa_family == 0) | |
875 | return "0"; | |
876 | ||
3356c77c EA |
877 | #ifdef NETINET |
878 | if (sap->sa.sa_family == AF_INET) | |
3341995c EA |
879 | { |
880 | extern char *inet_ntoa(); | |
881 | ||
882 | return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); | |
883 | } | |
3356c77c | 884 | #endif |
3341995c EA |
885 | |
886 | /* unknown family -- just dump bytes */ | |
3356c77c | 887 | (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); |
3341995c | 888 | bp = &buf[strlen(buf)]; |
3356c77c EA |
889 | ap = sap->sa.sa_data; |
890 | for (l = sizeof sap->sa.sa_data; --l >= 0; ) | |
3341995c EA |
891 | { |
892 | (void) sprintf(bp, "%02x:", *ap++ & 0377); | |
893 | bp += 3; | |
894 | } | |
895 | *--bp = '\0'; | |
896 | return buf; | |
897 | } | |
3f03d7a7 EA |
898 | \f/* |
899 | ** HOSTNAMEBYANYADDR -- return name of host based on address | |
900 | ** | |
901 | ** Parameters: | |
902 | ** sap -- SOCKADDR pointer | |
903 | ** | |
904 | ** Returns: | |
905 | ** text representation of host name. | |
906 | ** | |
907 | ** Side Effects: | |
908 | ** none. | |
909 | */ | |
910 | ||
911 | char * | |
912 | hostnamebyanyaddr(sap) | |
913 | register SOCKADDR *sap; | |
914 | { | |
915 | register struct hostent *hp; | |
916 | ||
ab6ca5e5 EA |
917 | #ifdef NAMED_BIND |
918 | int saveretry; | |
919 | ||
920 | /* shorten name server timeout to avoid higher level timeouts */ | |
921 | saveretry = _res.retry; | |
922 | _res.retry = 3; | |
923 | #endif /* NAMED_BIND */ | |
924 | ||
3f03d7a7 EA |
925 | switch (sap->sa.sa_family) |
926 | { | |
927 | #ifdef NETINET | |
928 | case AF_INET: | |
929 | hp = gethostbyaddr((char *) &sap->sin.sin_addr, | |
930 | sizeof sap->sin.sin_addr, | |
931 | AF_INET); | |
932 | break; | |
933 | #endif | |
934 | ||
935 | #ifdef NETISO | |
936 | case AF_ISO: | |
937 | hp = gethostbyaddr((char *) &sap->siso.siso_addr, | |
938 | sizeof sap->siso.siso_addr, | |
939 | AF_ISO); | |
940 | break; | |
941 | #endif | |
942 | ||
943 | default: | |
944 | hp = gethostbyaddr(sap->sa.sa_data, | |
945 | sizeof sap->sa.sa_data, | |
946 | sap->sa.sa_family); | |
947 | break; | |
948 | } | |
949 | ||
ab6ca5e5 EA |
950 | #ifdef NAMED_BIND |
951 | _res.retry = saveretry; | |
952 | #endif /* NAMED_BIND */ | |
953 | ||
3f03d7a7 EA |
954 | if (hp != NULL) |
955 | return hp->h_name; | |
956 | else | |
957 | { | |
958 | /* produce a dotted quad */ | |
959 | static char buf[512]; | |
960 | ||
961 | (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); | |
962 | return buf; | |
963 | } | |
964 | } | |
d0432129 | 965 | |
f3d8f6d6 | 966 | # else /* DAEMON */ |
217a0102 | 967 | /* code for systems without sophisticated networking */ |
2ec2faaa EA |
968 | |
969 | /* | |
970 | ** MYHOSTNAME -- stub version for case of no daemon code. | |
69f904e0 EA |
971 | ** |
972 | ** Can't convert to upper case here because might be a UUCP name. | |
05894fc6 EA |
973 | ** |
974 | ** Mark, you can change this to be anything you want...... | |
2ec2faaa EA |
975 | */ |
976 | ||
977 | char ** | |
05894fc6 | 978 | myhostname(hostbuf, size) |
2ec2faaa | 979 | char hostbuf[]; |
05894fc6 | 980 | int size; |
2ec2faaa EA |
981 | { |
982 | register FILE *f; | |
983 | ||
984 | hostbuf[0] = '\0'; | |
985 | f = fopen("/usr/include/whoami", "r"); | |
986 | if (f != NULL) | |
987 | { | |
05894fc6 | 988 | (void) fgets(hostbuf, size, f); |
2ec2faaa EA |
989 | fixcrlf(hostbuf, TRUE); |
990 | (void) fclose(f); | |
991 | } | |
992 | return (NULL); | |
993 | } | |
217a0102 | 994 | \f/* |
3f03d7a7 | 995 | ** GETAUTHINFO -- get the real host name asociated with a file descriptor |
5973222c EA |
996 | ** |
997 | ** Parameters: | |
998 | ** fd -- the descriptor | |
999 | ** | |
1000 | ** Returns: | |
1001 | ** The host name associated with this descriptor, if it can | |
1002 | ** be determined. | |
1003 | ** NULL otherwise. | |
1004 | ** | |
1005 | ** Side Effects: | |
1006 | ** none | |
1007 | */ | |
1008 | ||
1009 | char * | |
3f03d7a7 | 1010 | getauthinfo(fd) |
5973222c EA |
1011 | int fd; |
1012 | { | |
1013 | return NULL; | |
1014 | } | |
1015 | \f/* | |
217a0102 EA |
1016 | ** MAPHOSTNAME -- turn a hostname into canonical form |
1017 | ** | |
1018 | ** Parameters: | |
5a4c03c6 | 1019 | ** map -- a pointer to the database map. |
217a0102 | 1020 | ** hbuf -- a buffer containing a hostname. |
d1db7a89 | 1021 | ** hbsize -- size of hbuf. |
42fa5d67 | 1022 | ** avp -- a pointer to a (cf file defined) argument vector. |
d1db7a89 | 1023 | ** statp -- an exit status (out parameter). |
217a0102 EA |
1024 | ** |
1025 | ** Returns: | |
42fa5d67 | 1026 | ** mapped host name |
bbfde42f | 1027 | ** FALSE otherwise. |
217a0102 EA |
1028 | ** |
1029 | ** Side Effects: | |
1030 | ** Looks up the host specified in hbuf. If it is not | |
1031 | ** the canonical name for that host, replace it with | |
1032 | ** the canonical name. If the name is unknown, or it | |
1033 | ** is already the canonical name, leave it unchanged. | |
1034 | */ | |
1035 | ||
1036 | /*ARGSUSED*/ | |
42fa5d67 | 1037 | char * |
d1db7a89 | 1038 | maphostname(map, hbuf, hbsize, avp, statp) |
5a4c03c6 | 1039 | MAP *map; |
217a0102 EA |
1040 | char *hbuf; |
1041 | int hbsize; | |
42fa5d67 | 1042 | char **avp; |
d1db7a89 | 1043 | char *statp; |
217a0102 | 1044 | { |
d1db7a89 EA |
1045 | register struct hostent *hp; |
1046 | ||
1047 | hp = gethostbyname(hbuf); | |
1048 | if (hp != NULL) | |
1049 | return hp->h_name; | |
1050 | *statp = EX_NOHOST; | |
42fa5d67 | 1051 | return NULL; |
217a0102 EA |
1052 | } |
1053 | ||
f3d8f6d6 | 1054 | #endif /* DAEMON */ |