1 /* 2 * Copyright (c) 1983, 1995 Eric P. Allman 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #include <errno.h> 10 #include "sendmail.h" 11 12 #ifndef lint 13 #ifdef DAEMON 14 static char sccsid[] = "@(#)daemon.c 8.90 (Berkeley) 05/19/95 (with daemon mode)"; 15 #else 16 static char sccsid[] = "@(#)daemon.c 8.90 (Berkeley) 05/19/95 (without daemon mode)"; 17 #endif 18 #endif /* not lint */ 19 20 #ifdef DAEMON 21 22 # include <arpa/inet.h> 23 24 #if NAMED_BIND 25 # include <resolv.h> 26 #endif 27 28 /* 29 ** DAEMON.C -- routines to use when running as a daemon. 30 ** 31 ** This entire file is highly dependent on the 4.2 BSD 32 ** interprocess communication primitives. No attempt has 33 ** been made to make this file portable to Version 7, 34 ** Version 6, MPX files, etc. If you should try such a 35 ** thing yourself, I recommend chucking the entire file 36 ** and starting from scratch. Basic semantics are: 37 ** 38 ** getrequests() 39 ** Opens a port and initiates a connection. 40 ** Returns in a child. Must set InChannel and 41 ** OutChannel appropriately. 42 ** clrdaemon() 43 ** Close any open files associated with getting 44 ** the connection; this is used when running the queue, 45 ** etc., to avoid having extra file descriptors during 46 ** the queue run and to avoid confusing the network 47 ** code (if it cares). 48 ** makeconnection(host, port, outfile, infile, usesecureport) 49 ** Make a connection to the named host on the given 50 ** port. Set *outfile and *infile to the files 51 ** appropriate for communication. Returns zero on 52 ** success, else an exit status describing the 53 ** error. 54 ** host_map_lookup(map, hbuf, avp, pstat) 55 ** Convert the entry in hbuf into a canonical form. 56 */ 57 /* 58 ** GETREQUESTS -- open mail IPC port and get requests. 59 ** 60 ** Parameters: 61 ** none. 62 ** 63 ** Returns: 64 ** none. 65 ** 66 ** Side Effects: 67 ** Waits until some interesting activity occurs. When 68 ** it does, a child is created to process it, and the 69 ** parent waits for completion. Return from this 70 ** routine is always in the child. The file pointers 71 ** "InChannel" and "OutChannel" should be set to point 72 ** to the communication channel. 73 */ 74 75 int DaemonSocket = -1; /* fd describing socket */ 76 SOCKADDR DaemonAddr; /* socket for incoming */ 77 int ListenQueueSize = 10; /* size of listen queue */ 78 int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 79 int TcpSndBufferSize = 0; /* size of TCP send buffer */ 80 81 void 82 getrequests() 83 { 84 int t; 85 bool refusingconnections = TRUE; 86 FILE *pidf; 87 int socksize; 88 #ifdef XDEBUG 89 bool j_has_dot; 90 #endif 91 extern void reapchild(); 92 93 /* 94 ** Set up the address for the mailer. 95 */ 96 97 if (DaemonAddr.sin.sin_family == 0) 98 DaemonAddr.sin.sin_family = AF_INET; 99 if (DaemonAddr.sin.sin_addr.s_addr == 0) 100 DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 101 if (DaemonAddr.sin.sin_port == 0) 102 { 103 register struct servent *sp; 104 105 sp = getservbyname("smtp", "tcp"); 106 if (sp == NULL) 107 { 108 syserr("554 service \"smtp\" unknown"); 109 DaemonAddr.sin.sin_port = htons(25); 110 } 111 else 112 DaemonAddr.sin.sin_port = sp->s_port; 113 } 114 115 /* 116 ** Try to actually open the connection. 117 */ 118 119 if (tTd(15, 1)) 120 printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 121 122 /* get a socket for the SMTP connection */ 123 socksize = opendaemonsocket(TRUE); 124 125 (void) setsignal(SIGCHLD, reapchild); 126 127 /* write the pid to the log file for posterity */ 128 pidf = fopen(PidFile, "w"); 129 if (pidf != NULL) 130 { 131 extern char *CommandLineArgs; 132 133 /* write the process id on line 1 */ 134 fprintf(pidf, "%d\n", getpid()); 135 136 /* line 2 contains all command line flags */ 137 fprintf(pidf, "%s\n", CommandLineArgs); 138 139 /* flush and close */ 140 fclose(pidf); 141 } 142 143 #ifdef XDEBUG 144 { 145 char jbuf[MAXHOSTNAMELEN]; 146 147 expand("\201j", jbuf, sizeof jbuf, CurEnv); 148 j_has_dot = strchr(jbuf, '.') != NULL; 149 } 150 #endif 151 152 if (tTd(15, 1)) 153 printf("getrequests: %d\n", DaemonSocket); 154 155 for (;;) 156 { 157 register int pid; 158 auto int lotherend; 159 extern bool refuseconnections(); 160 extern int getla(); 161 162 /* see if we are rejecting connections */ 163 CurrentLA = getla(); 164 if (refuseconnections()) 165 { 166 if (DaemonSocket >= 0) 167 { 168 /* close socket so peer will fail quickly */ 169 (void) close(DaemonSocket); 170 DaemonSocket = -1; 171 } 172 refusingconnections = TRUE; 173 setproctitle("rejecting connections: load average: %d", 174 CurrentLA); 175 sleep(15); 176 continue; 177 } 178 179 /* arrange to (re)open the socket if necessary */ 180 if (refusingconnections) 181 { 182 (void) opendaemonsocket(FALSE); 183 setproctitle("accepting connections"); 184 refusingconnections = FALSE; 185 } 186 187 #ifdef XDEBUG 188 /* check for disaster */ 189 { 190 char jbuf[MAXHOSTNAMELEN]; 191 192 expand("\201j", jbuf, sizeof jbuf, CurEnv); 193 if (!wordinclass(jbuf, 'w')) 194 { 195 dumpstate("daemon lost $j"); 196 syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); 197 abort(); 198 } 199 else if (j_has_dot && strchr(jbuf, '.') == NULL) 200 { 201 dumpstate("daemon $j lost dot"); 202 syslog(LOG_ALERT, "daemon process $j lost dot; see syslog"); 203 abort(); 204 } 205 } 206 #endif 207 208 /* wait for a connection */ 209 do 210 { 211 errno = 0; 212 lotherend = socksize; 213 t = accept(DaemonSocket, 214 (struct sockaddr *)&RealHostAddr, &lotherend); 215 } while (t < 0 && errno == EINTR); 216 if (t < 0) 217 { 218 syserr("getrequests: accept"); 219 220 /* arrange to re-open the socket next time around */ 221 (void) close(DaemonSocket); 222 DaemonSocket = -1; 223 sleep(5); 224 continue; 225 } 226 227 /* 228 ** Create a subprocess to process the mail. 229 */ 230 231 if (tTd(15, 2)) 232 printf("getrequests: forking (fd = %d)\n", t); 233 234 pid = fork(); 235 if (pid < 0) 236 { 237 syserr("daemon: cannot fork"); 238 sleep(10); 239 (void) close(t); 240 continue; 241 } 242 243 if (pid == 0) 244 { 245 char *p; 246 extern char *hostnamebyanyaddr(); 247 extern void intsig(); 248 249 /* 250 ** CHILD -- return to caller. 251 ** Collect verified idea of sending host. 252 ** Verify calling user id if possible here. 253 */ 254 255 (void) setsignal(SIGCHLD, SIG_DFL); 256 (void) setsignal(SIGHUP, intsig); 257 (void) close(DaemonSocket); 258 DisConnected = FALSE; 259 260 setproctitle("startup with %s", 261 anynet_ntoa(&RealHostAddr)); 262 263 /* determine host name */ 264 p = hostnamebyanyaddr(&RealHostAddr); 265 if (strlen(p) > MAXNAME) 266 p[MAXNAME] = '\0'; 267 RealHostName = newstr(p); 268 setproctitle("startup with %s", p); 269 270 #ifdef LOG 271 if (LogLevel > 11) 272 { 273 /* log connection information */ 274 syslog(LOG_INFO, "connect from %s (%s)", 275 RealHostName, anynet_ntoa(&RealHostAddr)); 276 } 277 #endif 278 279 if ((InChannel = fdopen(t, "r")) == NULL || 280 (t = dup(t)) < 0 || 281 (OutChannel = fdopen(t, "w")) == NULL) 282 { 283 syserr("cannot open SMTP server channel, fd=%d", t); 284 exit(0); 285 } 286 287 /* should we check for illegal connection here? XXX */ 288 #ifdef XLA 289 if (!xla_host_ok(RealHostName)) 290 { 291 message("421 Too many SMTP sessions for this host"); 292 exit(0); 293 } 294 #endif 295 296 if (tTd(15, 2)) 297 printf("getreq: returning\n"); 298 return; 299 } 300 301 /* close the port so that others will hang (for a while) */ 302 (void) close(t); 303 } 304 /*NOTREACHED*/ 305 } 306 /* 307 ** OPENDAEMONSOCKET -- open the SMTP socket 308 ** 309 ** Deals with setting all appropriate options. DaemonAddr must 310 ** be set up in advance. 311 ** 312 ** Parameters: 313 ** firsttime -- set if this is the initial open. 314 ** 315 ** Returns: 316 ** Size in bytes of the daemon socket addr. 317 ** 318 ** Side Effects: 319 ** Leaves DaemonSocket set to the open socket. 320 ** Exits if the socket cannot be created. 321 */ 322 323 #define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 324 325 int 326 opendaemonsocket(firsttime) 327 bool firsttime; 328 { 329 int on = 1; 330 int socksize = 0; 331 int ntries = 0; 332 int saveerrno; 333 334 if (tTd(15, 2)) 335 printf("opendaemonsocket()\n"); 336 337 do 338 { 339 if (ntries > 0) 340 sleep(5); 341 if (firsttime || DaemonSocket < 0) 342 { 343 DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 344 if (DaemonSocket < 0) 345 { 346 /* probably another daemon already */ 347 saveerrno = errno; 348 syserr("opendaemonsocket: can't create server SMTP socket"); 349 severe: 350 # ifdef LOG 351 if (LogLevel > 0) 352 syslog(LOG_ALERT, "problem creating SMTP socket"); 353 # endif /* LOG */ 354 DaemonSocket = -1; 355 continue; 356 } 357 358 /* turn on network debugging? */ 359 if (tTd(15, 101)) 360 (void) setsockopt(DaemonSocket, SOL_SOCKET, 361 SO_DEBUG, (char *)&on, 362 sizeof on); 363 364 (void) setsockopt(DaemonSocket, SOL_SOCKET, 365 SO_REUSEADDR, (char *)&on, sizeof on); 366 (void) setsockopt(DaemonSocket, SOL_SOCKET, 367 SO_KEEPALIVE, (char *)&on, sizeof on); 368 369 #ifdef SO_RCVBUF 370 if (TcpRcvBufferSize > 0) 371 { 372 if (setsockopt(DaemonSocket, SOL_SOCKET, 373 SO_RCVBUF, 374 (char *) &TcpRcvBufferSize, 375 sizeof(TcpRcvBufferSize)) < 0) 376 syserr("getrequests: setsockopt(SO_RCVBUF)"); 377 } 378 #endif 379 380 switch (DaemonAddr.sa.sa_family) 381 { 382 # ifdef NETINET 383 case AF_INET: 384 socksize = sizeof DaemonAddr.sin; 385 break; 386 # endif 387 388 # ifdef NETISO 389 case AF_ISO: 390 socksize = sizeof DaemonAddr.siso; 391 break; 392 # endif 393 394 default: 395 socksize = sizeof DaemonAddr; 396 break; 397 } 398 399 if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 400 { 401 saveerrno = errno; 402 syserr("getrequests: cannot bind"); 403 (void) close(DaemonSocket); 404 goto severe; 405 } 406 } 407 if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0) 408 { 409 saveerrno = errno; 410 syserr("getrequests: cannot listen"); 411 (void) close(DaemonSocket); 412 goto severe; 413 } 414 return socksize; 415 } while (ntries++ < MAXOPENTRIES && transienterror(saveerrno)); 416 syserr("!opendaemonsocket: server SMTP socket wedged: exiting"); 417 finis(); 418 } 419 /* 420 ** CLRDAEMON -- reset the daemon connection 421 ** 422 ** Parameters: 423 ** none. 424 ** 425 ** Returns: 426 ** none. 427 ** 428 ** Side Effects: 429 ** releases any resources used by the passive daemon. 430 */ 431 432 void 433 clrdaemon() 434 { 435 if (DaemonSocket >= 0) 436 (void) close(DaemonSocket); 437 DaemonSocket = -1; 438 } 439 /* 440 ** SETDAEMONOPTIONS -- set options for running the daemon 441 ** 442 ** Parameters: 443 ** p -- the options line. 444 ** 445 ** Returns: 446 ** none. 447 */ 448 449 void 450 setdaemonoptions(p) 451 register char *p; 452 { 453 if (DaemonAddr.sa.sa_family == AF_UNSPEC) 454 DaemonAddr.sa.sa_family = AF_INET; 455 456 while (p != NULL) 457 { 458 register char *f; 459 register char *v; 460 461 while (isascii(*p) && isspace(*p)) 462 p++; 463 if (*p == '\0') 464 break; 465 f = p; 466 p = strchr(p, ','); 467 if (p != NULL) 468 *p++ = '\0'; 469 v = strchr(f, '='); 470 if (v == NULL) 471 continue; 472 while (isascii(*++v) && isspace(*v)) 473 continue; 474 if (isascii(*f) && isupper(*f)) 475 *f = tolower(*f); 476 477 switch (*f) 478 { 479 case 'F': /* address family */ 480 if (isascii(*v) && isdigit(*v)) 481 DaemonAddr.sa.sa_family = atoi(v); 482 #ifdef NETINET 483 else if (strcasecmp(v, "inet") == 0) 484 DaemonAddr.sa.sa_family = AF_INET; 485 #endif 486 #ifdef NETISO 487 else if (strcasecmp(v, "iso") == 0) 488 DaemonAddr.sa.sa_family = AF_ISO; 489 #endif 490 #ifdef NETNS 491 else if (strcasecmp(v, "ns") == 0) 492 DaemonAddr.sa.sa_family = AF_NS; 493 #endif 494 #ifdef NETX25 495 else if (strcasecmp(v, "x.25") == 0) 496 DaemonAddr.sa.sa_family = AF_CCITT; 497 #endif 498 else 499 syserr("554 Unknown address family %s in Family=option", v); 500 break; 501 502 case 'A': /* address */ 503 switch (DaemonAddr.sa.sa_family) 504 { 505 #ifdef NETINET 506 case AF_INET: 507 if (isascii(*v) && isdigit(*v)) 508 DaemonAddr.sin.sin_addr.s_addr = htonl(inet_network(v)); 509 else 510 { 511 register struct netent *np; 512 513 np = getnetbyname(v); 514 if (np == NULL) 515 syserr("554 network \"%s\" unknown", v); 516 else 517 DaemonAddr.sin.sin_addr.s_addr = np->n_net; 518 } 519 break; 520 #endif 521 522 default: 523 syserr("554 Address= option unsupported for family %d", 524 DaemonAddr.sa.sa_family); 525 break; 526 } 527 break; 528 529 case 'P': /* port */ 530 switch (DaemonAddr.sa.sa_family) 531 { 532 short port; 533 534 #ifdef NETINET 535 case AF_INET: 536 if (isascii(*v) && isdigit(*v)) 537 DaemonAddr.sin.sin_port = htons(atoi(v)); 538 else 539 { 540 register struct servent *sp; 541 542 sp = getservbyname(v, "tcp"); 543 if (sp == NULL) 544 syserr("554 service \"%s\" unknown", v); 545 else 546 DaemonAddr.sin.sin_port = sp->s_port; 547 } 548 break; 549 #endif 550 551 #ifdef NETISO 552 case AF_ISO: 553 /* assume two byte transport selector */ 554 if (isascii(*v) && isdigit(*v)) 555 port = htons(atoi(v)); 556 else 557 { 558 register struct servent *sp; 559 560 sp = getservbyname(v, "tcp"); 561 if (sp == NULL) 562 syserr("554 service \"%s\" unknown", v); 563 else 564 port = sp->s_port; 565 } 566 bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 567 break; 568 #endif 569 570 default: 571 syserr("554 Port= option unsupported for family %d", 572 DaemonAddr.sa.sa_family); 573 break; 574 } 575 break; 576 577 case 'L': /* listen queue size */ 578 ListenQueueSize = atoi(v); 579 break; 580 581 case 'S': /* send buffer size */ 582 TcpSndBufferSize = atoi(v); 583 break; 584 585 case 'R': /* receive buffer size */ 586 TcpRcvBufferSize = atoi(v); 587 break; 588 589 default: 590 syserr("554 DaemonPortOptions parameter \"%s\" unknown", f); 591 } 592 } 593 } 594 /* 595 ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 596 ** 597 ** Parameters: 598 ** host -- the name of the host. 599 ** port -- the port number to connect to. 600 ** mci -- a pointer to the mail connection information 601 ** structure to be filled in. 602 ** usesecureport -- if set, use a low numbered (reserved) 603 ** port to provide some rudimentary authentication. 604 ** 605 ** Returns: 606 ** An exit code telling whether the connection could be 607 ** made and if not why not. 608 ** 609 ** Side Effects: 610 ** none. 611 */ 612 613 SOCKADDR CurHostAddr; /* address of current host */ 614 615 int 616 makeconnection(host, port, mci, usesecureport) 617 char *host; 618 u_short port; 619 register MCI *mci; 620 bool usesecureport; 621 { 622 register int i = 0; 623 register int s; 624 register struct hostent *hp = (struct hostent *)NULL; 625 SOCKADDR addr; 626 int sav_errno; 627 int addrlen; 628 bool firstconnect; 629 #if NAMED_BIND 630 extern int h_errno; 631 #endif 632 633 /* 634 ** Set up the address for the mailer. 635 ** Accept "[a.b.c.d]" syntax for host name. 636 */ 637 638 #if NAMED_BIND 639 h_errno = 0; 640 #endif 641 errno = 0; 642 bzero(&CurHostAddr, sizeof CurHostAddr); 643 SmtpPhase = mci->mci_phase = "initial connection"; 644 CurHostName = host; 645 646 if (host[0] == '[') 647 { 648 long hid; 649 register char *p = strchr(host, ']'); 650 651 if (p != NULL) 652 { 653 *p = '\0'; 654 #ifdef NETINET 655 hid = inet_addr(&host[1]); 656 if (hid == -1) 657 #endif 658 { 659 /* try it as a host name (avoid MX lookup) */ 660 hp = sm_gethostbyname(&host[1]); 661 if (hp == NULL && p[-1] == '.') 662 { 663 #if NAMED_BIND 664 int oldopts = _res.options; 665 666 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 667 #endif 668 p[-1] = '\0'; 669 hp = sm_gethostbyname(&host[1]); 670 p[-1] = '.'; 671 #if NAMED_BIND 672 _res.options = oldopts; 673 #endif 674 } 675 *p = ']'; 676 goto gothostent; 677 } 678 *p = ']'; 679 } 680 if (p == NULL) 681 { 682 usrerr("553 Invalid numeric domain spec \"%s\"", host); 683 mci->mci_status = "5.1.2"; 684 return (EX_NOHOST); 685 } 686 #ifdef NETINET 687 addr.sin.sin_family = AF_INET; /*XXX*/ 688 addr.sin.sin_addr.s_addr = hid; 689 #endif 690 } 691 else 692 { 693 register char *p = &host[strlen(host) - 1]; 694 695 hp = sm_gethostbyname(host); 696 if (hp == NULL && *p == '.') 697 { 698 #if NAMED_BIND 699 int oldopts = _res.options; 700 701 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 702 #endif 703 *p = '\0'; 704 hp = sm_gethostbyname(host); 705 *p = '.'; 706 #if NAMED_BIND 707 _res.options = oldopts; 708 #endif 709 } 710 gothostent: 711 if (hp == NULL) 712 { 713 #if NAMED_BIND 714 /* check for name server timeouts */ 715 if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || 716 (errno == ECONNREFUSED && UseNameServer)) 717 { 718 mci->mci_status = "4.4.3"; 719 return (EX_TEMPFAIL); 720 } 721 #endif 722 return (EX_NOHOST); 723 } 724 addr.sa.sa_family = hp->h_addrtype; 725 switch (hp->h_addrtype) 726 { 727 #ifdef NETINET 728 case AF_INET: 729 bcopy(hp->h_addr, 730 &addr.sin.sin_addr, 731 INADDRSZ); 732 break; 733 #endif 734 735 default: 736 bcopy(hp->h_addr, 737 addr.sa.sa_data, 738 hp->h_length); 739 break; 740 } 741 i = 1; 742 } 743 744 /* 745 ** Determine the port number. 746 */ 747 748 if (port != 0) 749 port = htons(port); 750 else 751 { 752 register struct servent *sp = getservbyname("smtp", "tcp"); 753 754 if (sp == NULL) 755 { 756 #ifdef LOG 757 if (LogLevel > 2) 758 syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown"); 759 #endif 760 port = htons(25); 761 } 762 else 763 port = sp->s_port; 764 } 765 766 switch (addr.sa.sa_family) 767 { 768 #ifdef NETINET 769 case AF_INET: 770 addr.sin.sin_port = port; 771 addrlen = sizeof (struct sockaddr_in); 772 break; 773 #endif 774 775 #ifdef NETISO 776 case AF_ISO: 777 /* assume two byte transport selector */ 778 bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 779 addrlen = sizeof (struct sockaddr_iso); 780 break; 781 #endif 782 783 default: 784 syserr("Can't connect to address family %d", addr.sa.sa_family); 785 return (EX_NOHOST); 786 } 787 788 /* 789 ** Try to actually open the connection. 790 */ 791 792 #ifdef XLA 793 /* if too many connections, don't bother trying */ 794 if (!xla_noqueue_ok(host)) 795 return EX_TEMPFAIL; 796 #endif 797 798 firstconnect = TRUE; 799 for (;;) 800 { 801 if (tTd(16, 1)) 802 printf("makeconnection (%s [%s])\n", 803 host, anynet_ntoa(&addr)); 804 805 /* save for logging */ 806 CurHostAddr = addr; 807 808 if (usesecureport) 809 { 810 int rport = IPPORT_RESERVED - 1; 811 812 s = rresvport(&rport); 813 } 814 else 815 { 816 s = socket(AF_INET, SOCK_STREAM, 0); 817 } 818 if (s < 0) 819 { 820 sav_errno = errno; 821 syserr("makeconnection: no socket"); 822 goto failure; 823 } 824 825 #ifdef SO_SNDBUF 826 if (TcpSndBufferSize > 0) 827 { 828 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 829 (char *) &TcpSndBufferSize, 830 sizeof(TcpSndBufferSize)) < 0) 831 syserr("makeconnection: setsockopt(SO_SNDBUF)"); 832 } 833 #endif 834 835 if (tTd(16, 1)) 836 printf("makeconnection: fd=%d\n", s); 837 838 /* turn on network debugging? */ 839 if (tTd(16, 101)) 840 { 841 int on = 1; 842 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 843 (char *)&on, sizeof on); 844 } 845 if (CurEnv->e_xfp != NULL) 846 (void) fflush(CurEnv->e_xfp); /* for debugging */ 847 errno = 0; /* for debugging */ 848 if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 849 break; 850 851 /* if running demand-dialed connection, try again */ 852 if (DialDelay > 0 && firstconnect) 853 { 854 if (tTd(16, 1)) 855 printf("Connect failed (%s); trying again...\n", 856 errstring(sav_errno)); 857 firstconnect = FALSE; 858 sleep(DialDelay); 859 continue; 860 } 861 862 /* couldn't connect.... figure out why */ 863 sav_errno = errno; 864 (void) close(s); 865 if (hp != NULL && hp->h_addr_list[i]) 866 { 867 if (tTd(16, 1)) 868 printf("Connect failed (%s); trying new address....\n", 869 errstring(sav_errno)); 870 switch (addr.sa.sa_family) 871 { 872 #ifdef NETINET 873 case AF_INET: 874 bcopy(hp->h_addr_list[i++], 875 &addr.sin.sin_addr, 876 INADDRSZ); 877 break; 878 #endif 879 880 default: 881 bcopy(hp->h_addr_list[i++], 882 addr.sa.sa_data, 883 hp->h_length); 884 break; 885 } 886 continue; 887 } 888 889 /* failure, decide if temporary or not */ 890 failure: 891 #ifdef XLA 892 xla_host_end(host); 893 #endif 894 if (transienterror(sav_errno)) 895 return EX_TEMPFAIL; 896 else 897 { 898 message("%s", errstring(sav_errno)); 899 return (EX_UNAVAILABLE); 900 } 901 } 902 903 /* connection ok, put it into canonical form */ 904 if ((mci->mci_out = fdopen(s, "w")) == NULL || 905 (s = dup(s)) < 0 || 906 (mci->mci_in = fdopen(s, "r")) == NULL) 907 { 908 syserr("cannot open SMTP client channel, fd=%d", s); 909 return EX_TEMPFAIL; 910 } 911 912 return (EX_OK); 913 } 914 /* 915 ** MYHOSTNAME -- return the name of this host. 916 ** 917 ** Parameters: 918 ** hostbuf -- a place to return the name of this host. 919 ** size -- the size of hostbuf. 920 ** 921 ** Returns: 922 ** A list of aliases for this host. 923 ** 924 ** Side Effects: 925 ** Adds numeric codes to $=w. 926 */ 927 928 struct hostent * 929 myhostname(hostbuf, size) 930 char hostbuf[]; 931 int size; 932 { 933 register struct hostent *hp; 934 extern bool getcanonname(); 935 extern int h_errno; 936 937 if (gethostname(hostbuf, size) < 0) 938 { 939 (void) strcpy(hostbuf, "localhost"); 940 } 941 hp = sm_gethostbyname(hostbuf); 942 if (hp == NULL) 943 return NULL; 944 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 945 { 946 (void) strncpy(hostbuf, hp->h_name, size - 1); 947 hostbuf[size - 1] = '\0'; 948 } 949 950 #if NAMED_BIND 951 /* 952 ** If still no dot, try DNS directly (i.e., avoid NIS problems). 953 ** This ought to be driven from the configuration file, but 954 ** we are called before the configuration is read. We could 955 ** check for an /etc/resolv.conf file, but that isn't required. 956 ** All in all, a bit of a mess. 957 */ 958 959 if (strchr(hostbuf, '.') == NULL && 960 !getcanonname(hostbuf, size, TRUE) && 961 h_errno == TRY_AGAIN) 962 { 963 /* try twice in case name server not yet started up */ 964 message("My unqualifed host name (%s) unknown to DNS; sleeping for retry", 965 hostbuf); 966 sleep(60); 967 if (!getcanonname(hostbuf, size, TRUE)) 968 errno = h_errno + E_DNSBASE; 969 } 970 #endif 971 return (hp); 972 } 973 /* 974 ** GETAUTHINFO -- get the real host name asociated with a file descriptor 975 ** 976 ** Uses RFC1413 protocol to try to get info from the other end. 977 ** 978 ** Parameters: 979 ** fd -- the descriptor 980 ** 981 ** Returns: 982 ** The user@host information associated with this descriptor. 983 */ 984 985 static jmp_buf CtxAuthTimeout; 986 987 static void 988 authtimeout() 989 { 990 longjmp(CtxAuthTimeout, 1); 991 } 992 993 char * 994 getauthinfo(fd) 995 int fd; 996 { 997 int falen; 998 register char *p; 999 SOCKADDR la; 1000 int lalen; 1001 register struct servent *sp; 1002 int s; 1003 int i; 1004 EVENT *ev; 1005 int nleft; 1006 char ibuf[MAXNAME + 1]; 1007 static char hbuf[MAXNAME * 2 + 2]; 1008 extern char *hostnamebyanyaddr(); 1009 extern char RealUserName[]; /* main.c */ 1010 1011 falen = sizeof RealHostAddr; 1012 if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 || 1013 falen <= 0 || RealHostAddr.sa.sa_family == 0) 1014 { 1015 (void) sprintf(hbuf, "%s@localhost", RealUserName); 1016 if (tTd(9, 1)) 1017 printf("getauthinfo: %s\n", hbuf); 1018 return hbuf; 1019 } 1020 1021 if (RealHostName == NULL) 1022 { 1023 /* translate that to a host name */ 1024 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 1025 } 1026 1027 if (TimeOuts.to_ident == 0) 1028 goto noident; 1029 1030 lalen = sizeof la; 1031 if (RealHostAddr.sa.sa_family != AF_INET || 1032 getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 1033 la.sa.sa_family != AF_INET) 1034 { 1035 /* no ident info */ 1036 goto noident; 1037 } 1038 1039 /* create ident query */ 1040 (void) sprintf(ibuf, "%d,%d\r\n", 1041 ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 1042 1043 /* create local address */ 1044 la.sin.sin_port = 0; 1045 1046 /* create foreign address */ 1047 sp = getservbyname("auth", "tcp"); 1048 if (sp != NULL) 1049 RealHostAddr.sin.sin_port = sp->s_port; 1050 else 1051 RealHostAddr.sin.sin_port = htons(113); 1052 1053 s = -1; 1054 if (setjmp(CtxAuthTimeout) != 0) 1055 { 1056 if (s >= 0) 1057 (void) close(s); 1058 goto noident; 1059 } 1060 1061 /* put a timeout around the whole thing */ 1062 ev = setevent(TimeOuts.to_ident, authtimeout, 0); 1063 1064 /* connect to foreign IDENT server using same address as SMTP socket */ 1065 s = socket(AF_INET, SOCK_STREAM, 0); 1066 if (s < 0) 1067 { 1068 clrevent(ev); 1069 goto noident; 1070 } 1071 if (bind(s, &la.sa, sizeof la.sin) < 0 || 1072 connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 1073 { 1074 goto closeident; 1075 } 1076 1077 if (tTd(9, 10)) 1078 printf("getauthinfo: sent %s", ibuf); 1079 1080 /* send query */ 1081 if (write(s, ibuf, strlen(ibuf)) < 0) 1082 goto closeident; 1083 1084 /* get result */ 1085 p = &ibuf[0]; 1086 nleft = sizeof ibuf - 1; 1087 while ((i = read(s, p, nleft)) > 0) 1088 { 1089 p += i; 1090 nleft -= i; 1091 } 1092 (void) close(s); 1093 clrevent(ev); 1094 if (i < 0 || p == &ibuf[0]) 1095 goto noident; 1096 1097 if (*--p == '\n' && *--p == '\r') 1098 p--; 1099 *++p = '\0'; 1100 1101 if (tTd(9, 3)) 1102 printf("getauthinfo: got %s\n", ibuf); 1103 1104 /* parse result */ 1105 p = strchr(ibuf, ':'); 1106 if (p == NULL) 1107 { 1108 /* malformed response */ 1109 goto noident; 1110 } 1111 while (isascii(*++p) && isspace(*p)) 1112 continue; 1113 if (strncasecmp(p, "userid", 6) != 0) 1114 { 1115 /* presumably an error string */ 1116 goto noident; 1117 } 1118 p += 6; 1119 while (isascii(*p) && isspace(*p)) 1120 p++; 1121 if (*p++ != ':') 1122 { 1123 /* either useridxx or malformed response */ 1124 goto noident; 1125 } 1126 1127 /* p now points to the OSTYPE field */ 1128 while (isascii(*p) && isspace(*p)) 1129 p++; 1130 if (strncasecmp(p, "other", 5) == 0 && 1131 (p[5] == ':' || p[5] == ' ' || p[5] == ',' || p[5] == '\0')) 1132 { 1133 /* not useful information */ 1134 goto noident; 1135 } 1136 p = strchr(p, ':'); 1137 if (p == NULL) 1138 { 1139 /* malformed response */ 1140 goto noident; 1141 } 1142 1143 /* 1413 says don't do this -- but it's broken otherwise */ 1144 while (isascii(*++p) && isspace(*p)) 1145 continue; 1146 1147 /* p now points to the authenticated name -- copy carefully */ 1148 cleanstrcpy(hbuf, p, MAXNAME); 1149 i = strlen(hbuf); 1150 hbuf[i++] = '@'; 1151 strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName); 1152 goto finish; 1153 1154 closeident: 1155 (void) close(s); 1156 clrevent(ev); 1157 1158 noident: 1159 if (RealHostName == NULL) 1160 { 1161 if (tTd(9, 1)) 1162 printf("getauthinfo: NULL\n"); 1163 return NULL; 1164 } 1165 (void) strcpy(hbuf, RealHostName); 1166 1167 finish: 1168 if (RealHostName != NULL && RealHostName[0] != '[') 1169 { 1170 p = &hbuf[strlen(hbuf)]; 1171 (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 1172 } 1173 if (tTd(9, 1)) 1174 printf("getauthinfo: %s\n", hbuf); 1175 return hbuf; 1176 } 1177 /* 1178 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 1179 ** 1180 ** Parameters: 1181 ** map -- a pointer to this map (unused). 1182 ** name -- the (presumably unqualified) hostname. 1183 ** av -- unused -- for compatibility with other mapping 1184 ** functions. 1185 ** statp -- an exit status (out parameter) -- set to 1186 ** EX_TEMPFAIL if the name server is unavailable. 1187 ** 1188 ** Returns: 1189 ** The mapping, if found. 1190 ** NULL if no mapping found. 1191 ** 1192 ** Side Effects: 1193 ** Looks up the host specified in hbuf. If it is not 1194 ** the canonical name for that host, return the canonical 1195 ** name. 1196 */ 1197 1198 char * 1199 host_map_lookup(map, name, av, statp) 1200 MAP *map; 1201 char *name; 1202 char **av; 1203 int *statp; 1204 { 1205 register struct hostent *hp; 1206 struct in_addr in_addr; 1207 char *cp; 1208 register STAB *s; 1209 char hbuf[MAXNAME + 1]; 1210 #if NAMED_BIND 1211 extern int h_errno; 1212 #endif 1213 1214 /* 1215 ** See if we have already looked up this name. If so, just 1216 ** return it. 1217 */ 1218 1219 s = stab(name, ST_NAMECANON, ST_ENTER); 1220 if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 1221 { 1222 if (tTd(9, 1)) 1223 printf("host_map_lookup(%s) => CACHE %s\n", 1224 name, 1225 s->s_namecanon.nc_cname == NULL 1226 ? "NULL" 1227 : s->s_namecanon.nc_cname); 1228 errno = s->s_namecanon.nc_errno; 1229 #if NAMED_BIND 1230 h_errno = s->s_namecanon.nc_herrno; 1231 #endif 1232 *statp = s->s_namecanon.nc_stat; 1233 if (*statp == EX_TEMPFAIL) 1234 { 1235 CurEnv->e_status = "4.4.3"; 1236 usrerr("451 %s: Name server timeout", 1237 shortenstring(name, 33)); 1238 } 1239 return s->s_namecanon.nc_cname; 1240 } 1241 1242 /* 1243 ** If first character is a bracket, then it is an address 1244 ** lookup. Address is copied into a temporary buffer to 1245 ** strip the brackets and to preserve name if address is 1246 ** unknown. 1247 */ 1248 1249 if (*name != '[') 1250 { 1251 extern bool getcanonname(); 1252 1253 if (tTd(9, 1)) 1254 printf("host_map_lookup(%s) => ", name); 1255 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 1256 if (strlen(name) < sizeof hbuf) 1257 (void) strcpy(hbuf, name); 1258 else 1259 { 1260 bcopy(name, hbuf, sizeof hbuf - 1); 1261 hbuf[sizeof hbuf - 1] = '\0'; 1262 } 1263 if (getcanonname(hbuf, sizeof hbuf - 1, !NoMXforCanon)) 1264 { 1265 if (tTd(9, 1)) 1266 printf("%s\n", hbuf); 1267 cp = map_rewrite(map, hbuf, strlen(hbuf), av); 1268 s->s_namecanon.nc_cname = newstr(cp); 1269 return cp; 1270 } 1271 else 1272 { 1273 register struct hostent *hp; 1274 1275 s->s_namecanon.nc_errno = errno; 1276 #if NAMED_BIND 1277 s->s_namecanon.nc_herrno = h_errno; 1278 if (tTd(9, 1)) 1279 printf("FAIL (%d)\n", h_errno); 1280 switch (h_errno) 1281 { 1282 case TRY_AGAIN: 1283 if (UseNameServer) 1284 { 1285 CurEnv->e_status = "4.4.3"; 1286 usrerr("451 %s: Name server timeout", 1287 shortenstring(name, 33)); 1288 } 1289 *statp = EX_TEMPFAIL; 1290 break; 1291 1292 case HOST_NOT_FOUND: 1293 case NO_DATA: 1294 *statp = EX_NOHOST; 1295 break; 1296 1297 case NO_RECOVERY: 1298 *statp = EX_SOFTWARE; 1299 break; 1300 1301 default: 1302 *statp = EX_UNAVAILABLE; 1303 break; 1304 } 1305 #else 1306 if (tTd(9, 1)) 1307 printf("FAIL\n"); 1308 *statp = EX_NOHOST; 1309 #endif 1310 s->s_namecanon.nc_stat = *statp; 1311 if ((*statp != EX_TEMPFAIL && *statp != EX_NOHOST) || 1312 UseNameServer) 1313 return NULL; 1314 1315 /* 1316 ** Try to look it up in /etc/hosts 1317 */ 1318 1319 hp = sm_gethostbyname(name); 1320 if (hp == NULL) 1321 { 1322 /* no dice there either */ 1323 s->s_namecanon.nc_stat = *statp = EX_NOHOST; 1324 return NULL; 1325 } 1326 1327 s->s_namecanon.nc_stat = *statp = EX_OK; 1328 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 1329 s->s_namecanon.nc_cname = newstr(cp); 1330 return cp; 1331 } 1332 } 1333 if ((cp = strchr(name, ']')) == NULL) 1334 return (NULL); 1335 *cp = '\0'; 1336 in_addr.s_addr = inet_addr(&name[1]); 1337 1338 /* nope -- ask the name server */ 1339 hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET); 1340 s->s_namecanon.nc_errno = errno; 1341 #if NAMED_BIND 1342 s->s_namecanon.nc_herrno = h_errno; 1343 #endif 1344 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 1345 if (hp == NULL) 1346 { 1347 s->s_namecanon.nc_stat = *statp = EX_NOHOST; 1348 return (NULL); 1349 } 1350 1351 /* found a match -- copy out */ 1352 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 1353 s->s_namecanon.nc_stat = *statp = EX_OK; 1354 s->s_namecanon.nc_cname = newstr(cp); 1355 return cp; 1356 } 1357 /* 1358 ** ANYNET_NTOA -- convert a network address to printable form. 1359 ** 1360 ** Parameters: 1361 ** sap -- a pointer to a sockaddr structure. 1362 ** 1363 ** Returns: 1364 ** A printable version of that sockaddr. 1365 */ 1366 1367 #ifdef NETLINK 1368 # include <net/if_dl.h> 1369 #endif 1370 1371 char * 1372 anynet_ntoa(sap) 1373 register SOCKADDR *sap; 1374 { 1375 register char *bp; 1376 register char *ap; 1377 int l; 1378 static char buf[100]; 1379 1380 /* check for null/zero family */ 1381 if (sap == NULL) 1382 return "NULLADDR"; 1383 if (sap->sa.sa_family == 0) 1384 return "0"; 1385 1386 switch (sap->sa.sa_family) 1387 { 1388 #ifdef NETUNIX 1389 case AF_UNIX: 1390 if (sap->sunix.sun_path[0] != '\0') 1391 sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); 1392 else 1393 sprintf(buf, "[UNIX: localhost]"); 1394 return buf; 1395 #endif 1396 1397 #ifdef NETINET 1398 case AF_INET: 1399 return inet_ntoa(sap->sin.sin_addr); 1400 #endif 1401 1402 #ifdef NETLINK 1403 case AF_LINK: 1404 sprintf(buf, "[LINK: %s]", 1405 link_ntoa((struct sockaddr_dl *) &sap->sa)); 1406 return buf; 1407 #endif 1408 default: 1409 /* this case is needed when nothing is #defined */ 1410 /* in order to keep the switch syntactically correct */ 1411 break; 1412 } 1413 1414 /* unknown family -- just dump bytes */ 1415 (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 1416 bp = &buf[strlen(buf)]; 1417 ap = sap->sa.sa_data; 1418 for (l = sizeof sap->sa.sa_data; --l >= 0; ) 1419 { 1420 (void) sprintf(bp, "%02x:", *ap++ & 0377); 1421 bp += 3; 1422 } 1423 *--bp = '\0'; 1424 return buf; 1425 } 1426 /* 1427 ** HOSTNAMEBYANYADDR -- return name of host based on address 1428 ** 1429 ** Parameters: 1430 ** sap -- SOCKADDR pointer 1431 ** 1432 ** Returns: 1433 ** text representation of host name. 1434 ** 1435 ** Side Effects: 1436 ** none. 1437 */ 1438 1439 char * 1440 hostnamebyanyaddr(sap) 1441 register SOCKADDR *sap; 1442 { 1443 register struct hostent *hp; 1444 int saveretry; 1445 1446 #if NAMED_BIND 1447 /* shorten name server timeout to avoid higher level timeouts */ 1448 saveretry = _res.retry; 1449 _res.retry = 3; 1450 #endif /* NAMED_BIND */ 1451 1452 switch (sap->sa.sa_family) 1453 { 1454 #ifdef NETINET 1455 case AF_INET: 1456 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 1457 INADDRSZ, 1458 AF_INET); 1459 break; 1460 #endif 1461 1462 #ifdef NETISO 1463 case AF_ISO: 1464 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 1465 sizeof sap->siso.siso_addr, 1466 AF_ISO); 1467 break; 1468 #endif 1469 1470 case AF_UNIX: 1471 hp = NULL; 1472 break; 1473 1474 default: 1475 hp = sm_gethostbyaddr(sap->sa.sa_data, 1476 sizeof sap->sa.sa_data, 1477 sap->sa.sa_family); 1478 break; 1479 } 1480 1481 #if NAMED_BIND 1482 _res.retry = saveretry; 1483 #endif /* NAMED_BIND */ 1484 1485 if (hp != NULL) 1486 return hp->h_name; 1487 else 1488 { 1489 /* produce a dotted quad */ 1490 static char buf[512]; 1491 1492 (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 1493 return buf; 1494 } 1495 } 1496 1497 # else /* DAEMON */ 1498 /* code for systems without sophisticated networking */ 1499 1500 /* 1501 ** MYHOSTNAME -- stub version for case of no daemon code. 1502 ** 1503 ** Can't convert to upper case here because might be a UUCP name. 1504 ** 1505 ** Mark, you can change this to be anything you want...... 1506 */ 1507 1508 char ** 1509 myhostname(hostbuf, size) 1510 char hostbuf[]; 1511 int size; 1512 { 1513 register FILE *f; 1514 1515 hostbuf[0] = '\0'; 1516 f = fopen("/usr/include/whoami", "r"); 1517 if (f != NULL) 1518 { 1519 (void) fgets(hostbuf, size, f); 1520 fixcrlf(hostbuf, TRUE); 1521 (void) fclose(f); 1522 } 1523 return (NULL); 1524 } 1525 /* 1526 ** GETAUTHINFO -- get the real host name asociated with a file descriptor 1527 ** 1528 ** Parameters: 1529 ** fd -- the descriptor 1530 ** 1531 ** Returns: 1532 ** The host name associated with this descriptor, if it can 1533 ** be determined. 1534 ** NULL otherwise. 1535 ** 1536 ** Side Effects: 1537 ** none 1538 */ 1539 1540 char * 1541 getauthinfo(fd) 1542 int fd; 1543 { 1544 return NULL; 1545 } 1546 /* 1547 ** MAPHOSTNAME -- turn a hostname into canonical form 1548 ** 1549 ** Parameters: 1550 ** map -- a pointer to the database map. 1551 ** name -- a buffer containing a hostname. 1552 ** avp -- a pointer to a (cf file defined) argument vector. 1553 ** statp -- an exit status (out parameter). 1554 ** 1555 ** Returns: 1556 ** mapped host name 1557 ** FALSE otherwise. 1558 ** 1559 ** Side Effects: 1560 ** Looks up the host specified in name. If it is not 1561 ** the canonical name for that host, replace it with 1562 ** the canonical name. If the name is unknown, or it 1563 ** is already the canonical name, leave it unchanged. 1564 */ 1565 1566 /*ARGSUSED*/ 1567 char * 1568 host_map_lookup(map, name, avp, statp) 1569 MAP *map; 1570 char *name; 1571 char **avp; 1572 char *statp; 1573 { 1574 register struct hostent *hp; 1575 1576 hp = sm_gethostbyname(name); 1577 if (hp != NULL) 1578 return hp->h_name; 1579 *statp = EX_NOHOST; 1580 return NULL; 1581 } 1582 1583 #endif /* DAEMON */ 1584