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