122700Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333780Sbostic * Copyright (c) 1988 Regents of the University of California. 433780Sbostic * All rights reserved. 533780Sbostic * 642825Sbostic * %sccs.include.redist.c% 733780Sbostic */ 822700Sdist 933932Sbostic #include <errno.h> 1058153Seric #include <signal.h> 1140962Sbostic #include "sendmail.h" 124535Seric 1333780Sbostic #ifndef lint 1433780Sbostic #ifdef DAEMON 15*58951Seric static char sccsid[] = "@(#)daemon.c 6.32 (Berkeley) 04/04/93 (with daemon mode)"; 1633780Sbostic #else 17*58951Seric static char sccsid[] = "@(#)daemon.c 6.32 (Berkeley) 04/04/93 (without daemon mode)"; 1833780Sbostic #endif 1933780Sbostic #endif /* not lint */ 204535Seric 2133780Sbostic #ifdef DAEMON 2233780Sbostic 2323120Seric # include <netdb.h> 2423120Seric # include <sys/wait.h> 2523120Seric # include <sys/time.h> 265978Seric 274535Seric /* 284535Seric ** DAEMON.C -- routines to use when running as a daemon. 297556Seric ** 307556Seric ** This entire file is highly dependent on the 4.2 BSD 317556Seric ** interprocess communication primitives. No attempt has 327556Seric ** been made to make this file portable to Version 7, 337556Seric ** Version 6, MPX files, etc. If you should try such a 347556Seric ** thing yourself, I recommend chucking the entire file 357556Seric ** and starting from scratch. Basic semantics are: 367556Seric ** 377556Seric ** getrequests() 387556Seric ** Opens a port and initiates a connection. 397556Seric ** Returns in a child. Must set InChannel and 407556Seric ** OutChannel appropriately. 4110206Seric ** clrdaemon() 4210206Seric ** Close any open files associated with getting 4310206Seric ** the connection; this is used when running the queue, 4410206Seric ** etc., to avoid having extra file descriptors during 4510206Seric ** the queue run and to avoid confusing the network 4610206Seric ** code (if it cares). 4752106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 487556Seric ** Make a connection to the named host on the given 497556Seric ** port. Set *outfile and *infile to the files 507556Seric ** appropriate for communication. Returns zero on 517556Seric ** success, else an exit status describing the 527556Seric ** error. 5356823Seric ** maphostname(map, hbuf, hbufsiz, avp) 5456823Seric ** Convert the entry in hbuf into a canonical form. 554535Seric */ 5658755Seric 5758755Seric extern char *anynet_ntoa(); 584535Seric /* 594535Seric ** GETREQUESTS -- open mail IPC port and get requests. 604535Seric ** 614535Seric ** Parameters: 624535Seric ** none. 634535Seric ** 644535Seric ** Returns: 654535Seric ** none. 664535Seric ** 674535Seric ** Side Effects: 684535Seric ** Waits until some interesting activity occurs. When 694535Seric ** it does, a child is created to process it, and the 704535Seric ** parent waits for completion. Return from this 719886Seric ** routine is always in the child. The file pointers 729886Seric ** "InChannel" and "OutChannel" should be set to point 739886Seric ** to the communication channel. 744535Seric */ 754535Seric 7658849Seric int DaemonSocket = -1; /* fd describing socket */ 7758849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 7816144Seric 794535Seric getrequests() 804535Seric { 819610Seric int t; 829610Seric register struct servent *sp; 8325027Seric int on = 1; 8453751Seric bool refusingconnections = TRUE; 8558419Seric FILE *pidf; 8646928Sbostic extern void reapchild(); 877117Seric 889610Seric /* 899610Seric ** Set up the address for the mailer. 909610Seric */ 919610Seric 9258849Seric if (DaemonAddr.sin.sin_family == 0) 9358849Seric DaemonAddr.sin.sin_family = AF_INET; 9458849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 9558849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 9658849Seric if (DaemonAddr.sin.sin_port == 0) 979610Seric { 9858849Seric sp = getservbyname("smtp", "tcp"); 9958849Seric if (sp == NULL) 10058849Seric { 10158909Seric syserr("554 service \"smtp\" unknown"); 10258849Seric goto severe; 10358849Seric } 10458849Seric DaemonAddr.sin.sin_port = sp->s_port; 1059610Seric } 1069610Seric 1079610Seric /* 1089610Seric ** Try to actually open the connection. 1099610Seric */ 1109610Seric 1119610Seric if (tTd(15, 1)) 11258849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1139610Seric 1149610Seric /* get a socket for the SMTP connection */ 11523120Seric DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 11610206Seric if (DaemonSocket < 0) 1179610Seric { 1189610Seric /* probably another daemon already */ 1199610Seric syserr("getrequests: can't create socket"); 1209610Seric severe: 1219610Seric # ifdef LOG 1229610Seric if (LogLevel > 0) 12357663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12456795Seric # endif /* LOG */ 1259610Seric finis(); 1269610Seric } 12710347Seric 12810347Seric /* turn on network debugging? */ 12956328Seric if (tTd(15, 101)) 13024945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13110347Seric 13225027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13325027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13425027Seric 13558849Seric if (bind(DaemonSocket, &DaemonAddr.sa, sizeof DaemonAddr) < 0) 1369610Seric { 1379610Seric syserr("getrequests: cannot bind"); 13810206Seric (void) close(DaemonSocket); 1399610Seric goto severe; 1409610Seric } 1419610Seric 14224955Seric (void) signal(SIGCHLD, reapchild); 14324945Seric 14458419Seric /* write the pid to the log file for posterity */ 14558419Seric pidf = fopen(PidFile, "w"); 14658419Seric if (pidf != NULL) 14758419Seric { 14858419Seric fprintf(pidf, "%d\n", getpid()); 14958419Seric fclose(pidf); 15058419Seric } 15158419Seric 15258419Seric 1539610Seric if (tTd(15, 1)) 15410206Seric printf("getrequests: %d\n", DaemonSocket); 1559610Seric 1564631Seric for (;;) 1574631Seric { 15814875Seric register int pid; 15911147Seric auto int lotherend; 16053751Seric extern bool refuseconnections(); 16111147Seric 16214875Seric /* see if we are rejecting connections */ 16353751Seric CurrentLA = getla(); 16453751Seric if (refuseconnections()) 16536584Sbostic { 16653751Seric if (!refusingconnections) 16753751Seric { 16853751Seric /* don't queue so peer will fail quickly */ 16953751Seric (void) listen(DaemonSocket, 0); 17053751Seric refusingconnections = TRUE; 17153751Seric } 17257385Seric setproctitle("rejecting connections: load average: %d", 17357385Seric CurrentLA); 17414875Seric sleep(5); 17553751Seric continue; 17636584Sbostic } 17714875Seric 17853751Seric if (refusingconnections) 17953751Seric { 18053751Seric /* start listening again */ 18153751Seric if (listen(DaemonSocket, 10) < 0) 18253751Seric { 18353751Seric syserr("getrequests: cannot listen"); 18453751Seric (void) close(DaemonSocket); 18553751Seric goto severe; 18653751Seric } 18753751Seric setproctitle("accepting connections"); 18853751Seric refusingconnections = FALSE; 18953751Seric } 19053751Seric 1919610Seric /* wait for a connection */ 1929610Seric do 1939610Seric { 1949610Seric errno = 0; 19536230Skarels lotherend = sizeof RealHostAddr; 19646928Sbostic t = accept(DaemonSocket, 19746928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 1989610Seric } while (t < 0 && errno == EINTR); 1999610Seric if (t < 0) 2005978Seric { 2019610Seric syserr("getrequests: accept"); 2029610Seric sleep(5); 2039610Seric continue; 2045978Seric } 2054631Seric 2065978Seric /* 2075978Seric ** Create a subprocess to process the mail. 2085978Seric */ 2095978Seric 2107677Seric if (tTd(15, 2)) 2119610Seric printf("getrequests: forking (fd = %d)\n", t); 2125978Seric 2134636Seric pid = fork(); 2144636Seric if (pid < 0) 2154631Seric { 2164636Seric syserr("daemon: cannot fork"); 2174636Seric sleep(10); 2189610Seric (void) close(t); 2194636Seric continue; 2204631Seric } 2214631Seric 2224636Seric if (pid == 0) 2234631Seric { 224*58951Seric extern char *hostnamebyanyaddr(); 22511147Seric 2264636Seric /* 2274636Seric ** CHILD -- return to caller. 22811147Seric ** Collect verified idea of sending host. 2294636Seric ** Verify calling user id if possible here. 2304636Seric */ 2314631Seric 23224955Seric (void) signal(SIGCHLD, SIG_DFL); 23324950Seric 23411147Seric /* determine host name */ 235*58951Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 23658778Seric 23755173Seric #ifdef LOG 23857977Seric if (LogLevel > 10) 23955173Seric { 24055173Seric /* log connection information */ 24155173Seric syslog(LOG_INFO, "connect from %s (%s)", 242*58951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 24355173Seric } 24455173Seric #endif 24555173Seric 24616884Seric /* should we check for illegal connection here? XXX */ 24716884Seric 24811147Seric 24910206Seric (void) close(DaemonSocket); 2509610Seric InChannel = fdopen(t, "r"); 25121062Seric OutChannel = fdopen(dup(t), "w"); 2527677Seric if (tTd(15, 2)) 2535978Seric printf("getreq: returning\n"); 2544636Seric return; 2554631Seric } 2564631Seric 2577117Seric /* close the port so that others will hang (for a while) */ 2589610Seric (void) close(t); 2594631Seric } 2609886Seric /*NOTREACHED*/ 2614631Seric } 2625978Seric /* 26310206Seric ** CLRDAEMON -- reset the daemon connection 26410206Seric ** 26510206Seric ** Parameters: 26610206Seric ** none. 26710206Seric ** 26810206Seric ** Returns: 26910206Seric ** none. 27010206Seric ** 27110206Seric ** Side Effects: 27210206Seric ** releases any resources used by the passive daemon. 27310206Seric */ 27410206Seric 27510206Seric clrdaemon() 27610206Seric { 27710206Seric if (DaemonSocket >= 0) 27810206Seric (void) close(DaemonSocket); 27910206Seric DaemonSocket = -1; 28010206Seric } 28110206Seric /* 28258849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 28358849Seric ** 28458849Seric ** Parameters: 28558849Seric ** p -- the options line. 28658849Seric ** 28758849Seric ** Returns: 28858849Seric ** none. 28958849Seric */ 29058849Seric 29158849Seric setdaemonoptions(p) 29258849Seric register char *p; 29358849Seric { 29458873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 29558873Seric DaemonAddr.sa.sa_family = AF_INET; 29658873Seric 29758849Seric while (p != NULL) 29858849Seric { 29958849Seric register char *f; 30058849Seric register char *v; 30158849Seric 30258849Seric while (isascii(*p) && isspace(*p)) 30358849Seric p++; 30458849Seric if (*p == '\0') 30558849Seric break; 30658849Seric f = p; 30758849Seric p = strchr(p, ','); 30858849Seric if (p != NULL) 30958849Seric *p++ = '\0'; 31058849Seric v = strchr(f, '='); 31158849Seric if (v == NULL) 31258849Seric continue; 31358849Seric while (isascii(*++v) && isspace(*v)) 31458849Seric continue; 31558849Seric 31658849Seric switch (*f) 31758849Seric { 31858873Seric case 'F': /* address family */ 31958849Seric if (isascii(*v) && isdigit(*v)) 32058873Seric DaemonAddr.sa.sa_family = atoi(v); 32158873Seric #ifdef NETINET 32258873Seric else if (strcasecmp(v, "inet") == 0) 32358873Seric DaemonAddr.sa.sa_family = AF_INET; 32458873Seric #endif 32558873Seric #ifdef NETISO 32658873Seric else if (strcasecmp(v, "iso") == 0) 32758873Seric DaemonAddr.sa.sa_family = AF_ISO; 32858873Seric #endif 32958873Seric #ifdef NETNS 33058873Seric else if (strcasecmp(v, "ns") == 0) 33158873Seric DaemonAddr.sa.sa_family = AF_NS; 33258873Seric #endif 33358873Seric #ifdef NETX25 33458873Seric else if (strcasecmp(v, "x.25") == 0) 33558873Seric DaemonAddr.sa.sa_family = AF_CCITT; 33658873Seric #endif 33758849Seric else 33858873Seric syserr("554 Unknown address family %s in Family=option", v); 33958873Seric break; 34058873Seric 34158873Seric case 'A': /* address */ 34258873Seric switch (DaemonAddr.sa.sa_family) 34358849Seric { 34458873Seric #ifdef NETINET 34558873Seric case AF_INET: 34658873Seric if (isascii(*v) && isdigit(*v)) 34758873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 34858873Seric else 34958873Seric { 35058873Seric register struct netent *np; 35158849Seric 35258873Seric np = getnetbyname(v); 35358873Seric if (np == NULL) 35458873Seric syserr("554 network \"%s\" unknown", v); 35558873Seric else 35658873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 35758873Seric } 35858873Seric break; 35958873Seric #endif 36058873Seric 36158873Seric default: 36258873Seric syserr("554 Address= option unsupported for family %d", 36358873Seric DaemonAddr.sa.sa_family); 36458873Seric break; 36558849Seric } 36658849Seric break; 36758849Seric 36858873Seric case 'P': /* port */ 36958873Seric switch (DaemonAddr.sa.sa_family) 37058849Seric { 37158873Seric short port; 37258849Seric 37358873Seric #ifdef NETINET 37458873Seric case AF_INET: 37558873Seric if (isascii(*v) && isdigit(*v)) 37658873Seric DaemonAddr.sin.sin_port = atoi(v); 37758849Seric else 37858873Seric { 37958873Seric register struct servent *sp; 38058873Seric 38158873Seric sp = getservbyname(v, "tcp"); 38258873Seric if (sp == NULL) 38358909Seric syserr("554 service \"%s\" unknown", v); 38458873Seric else 38558873Seric DaemonAddr.sin.sin_port = sp->s_port; 38658873Seric } 38758873Seric break; 38858873Seric #endif 38958873Seric 39058873Seric #ifdef NETISO 39158873Seric case AF_ISO: 39258873Seric /* assume two byte transport selector */ 39358873Seric if (isascii(*v) && isdigit(*v)) 39458873Seric port = atoi(v); 39558873Seric else 39658873Seric { 39758873Seric register struct servent *sp; 39858873Seric 39958873Seric sp = getservbyname(v, "tcp"); 40058873Seric if (sp == NULL) 40158909Seric syserr("554 service \"%s\" unknown", v); 40258873Seric else 40358873Seric port = sp->s_port; 40458873Seric } 40558873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 40658873Seric break; 40758873Seric #endif 40858873Seric 40958873Seric default: 41058873Seric syserr("554 Port= option unsupported for family %d", 41158873Seric DaemonAddr.sa.sa_family); 41258873Seric break; 41358849Seric } 41458849Seric break; 41558849Seric } 41658849Seric } 41758849Seric } 41858849Seric /* 4196039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4206039Seric ** 4216039Seric ** Parameters: 4226039Seric ** host -- the name of the host. 4236633Seric ** port -- the port number to connect to. 42453739Seric ** mci -- a pointer to the mail connection information 42553739Seric ** structure to be filled in. 42652106Seric ** usesecureport -- if set, use a low numbered (reserved) 42752106Seric ** port to provide some rudimentary authentication. 4286039Seric ** 4296039Seric ** Returns: 4306039Seric ** An exit code telling whether the connection could be 4316039Seric ** made and if not why not. 4326039Seric ** 4336039Seric ** Side Effects: 4346039Seric ** none. 4356039Seric */ 4365978Seric 43758755Seric SOCKADDR CurHostAddr; /* address of current host */ 43858305Seric 43954967Seric int 44053739Seric makeconnection(host, port, mci, usesecureport) 4416039Seric char *host; 4427286Seric u_short port; 44354967Seric register MCI *mci; 44452106Seric bool usesecureport; 4456039Seric { 44629430Sbloom register int i, s; 44729430Sbloom register struct hostent *hp = (struct hostent *)NULL; 44858755Seric SOCKADDR addr; 44952106Seric int sav_errno; 45058755Seric int addrlen; 45135651Seric #ifdef NAMED_BIND 45235651Seric extern int h_errno; 45335651Seric #endif 4546039Seric 4556039Seric /* 4566039Seric ** Set up the address for the mailer. 4579308Seric ** Accept "[a.b.c.d]" syntax for host name. 4586039Seric */ 4596039Seric 46035651Seric #ifdef NAMED_BIND 46125475Smiriam h_errno = 0; 46235651Seric #endif 46325475Smiriam errno = 0; 46458864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 46558906Seric CurHostName = host; 46625475Smiriam 4679308Seric if (host[0] == '[') 4689308Seric { 46911147Seric long hid; 47056795Seric register char *p = strchr(host, ']'); 4719308Seric 47211147Seric if (p != NULL) 4739308Seric { 47411147Seric *p = '\0'; 47511147Seric hid = inet_addr(&host[1]); 47658360Seric if (hid == -1) 47758360Seric { 47858360Seric /* try it as a host name (avoid MX lookup) */ 47958360Seric hp = gethostbyname(&host[1]); 48058360Seric *p = ']'; 48158360Seric goto gothostent; 48258360Seric } 48311147Seric *p = ']'; 4849308Seric } 48558360Seric if (p == NULL) 4869308Seric { 48758151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 4889308Seric return (EX_NOHOST); 4899308Seric } 49058778Seric addr.sin.sin_family = AF_INET; 49158778Seric addr.sin.sin_addr.s_addr = hid; 4929308Seric } 4939610Seric else 4949610Seric { 49529430Sbloom hp = gethostbyname(host); 49658360Seric gothostent: 49725475Smiriam if (hp == NULL) 49824945Seric { 49935651Seric #ifdef NAMED_BIND 50025475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 50125475Smiriam return (EX_TEMPFAIL); 50225657Seric 50335651Seric /* if name server is specified, assume temp fail */ 50435651Seric if (errno == ECONNREFUSED && UseNameServer) 50535651Seric return (EX_TEMPFAIL); 50635651Seric #endif 50725475Smiriam return (EX_NOHOST); 50824945Seric } 50958778Seric addr.sa.sa_family = hp->h_addrtype; 51058778Seric switch (hp->h_addrtype) 51158778Seric { 51258778Seric #ifdef NETINET 51358778Seric case AF_INET: 51458755Seric bcopy(hp->h_addr, 51558778Seric &addr.sin.sin_addr, 51658755Seric hp->h_length); 51758778Seric break; 51858778Seric #endif 51958778Seric 52058778Seric default: 52158755Seric bcopy(hp->h_addr, 52258778Seric addr.sa.sa_data, 52358755Seric hp->h_length); 52458778Seric break; 52558778Seric } 52629430Sbloom i = 1; 5279610Seric } 5289610Seric 5299610Seric /* 5309610Seric ** Determine the port number. 5319610Seric */ 5329610Seric 53310011Seric if (port != 0) 53458755Seric port = htons(port); 53510011Seric else 5369610Seric { 5379610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5389610Seric 5399610Seric if (sp == NULL) 5409610Seric { 54158909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 54257977Seric return (EX_OSERR); 5439610Seric } 54458755Seric port = sp->s_port; 5459610Seric } 5466039Seric 54758778Seric switch (addr.sa.sa_family) 54858755Seric { 54958755Seric case AF_INET: 55058778Seric addr.sin.sin_port = port; 55158755Seric addrlen = sizeof (struct sockaddr_in); 55258755Seric break; 55358755Seric 55458755Seric #ifdef NETISO 55558755Seric case AF_ISO: 55658755Seric /* assume two byte transport selector */ 55758755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 55858755Seric addrlen = sizeof (struct sockaddr_iso); 55958755Seric break; 56058755Seric #endif 56158755Seric 56258755Seric default: 56358778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 56458755Seric return (EX_NOHOST); 56558755Seric } 56658755Seric 5676039Seric /* 5686039Seric ** Try to actually open the connection. 5696039Seric */ 5706039Seric 57157736Seric for (;;) 57252106Seric { 57357736Seric if (tTd(16, 1)) 57458755Seric printf("makeconnection (%s [%s])\n", 57558755Seric host, anynet_ntoa(&addr)); 57652106Seric 57758588Seric /* save for logging */ 57858588Seric CurHostAddr = addr; 57958588Seric 58057736Seric if (usesecureport) 58157736Seric { 58257736Seric int rport = IPPORT_RESERVED - 1; 5836039Seric 58457736Seric s = rresvport(&rport); 58557736Seric } 58657736Seric else 58757736Seric { 58857736Seric s = socket(AF_INET, SOCK_STREAM, 0); 58957736Seric } 59057736Seric if (s < 0) 59157736Seric { 59257736Seric sav_errno = errno; 59357736Seric syserr("makeconnection: no socket"); 59457736Seric goto failure; 59557736Seric } 59610347Seric 59757736Seric if (tTd(16, 1)) 59857736Seric printf("makeconnection: fd=%d\n", s); 59957736Seric 60057736Seric /* turn on network debugging? */ 60157736Seric if (tTd(16, 101)) 60257736Seric { 60357736Seric int on = 1; 60457736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 60557736Seric (char *)&on, sizeof on); 60657736Seric } 60757736Seric if (CurEnv->e_xfp != NULL) 60857736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 60957736Seric errno = 0; /* for debugging */ 61058755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 61157736Seric break; 61257736Seric 61357736Seric /* couldn't connect.... figure out why */ 61427744Sbloom sav_errno = errno; 61527744Sbloom (void) close(s); 61629430Sbloom if (hp && hp->h_addr_list[i]) 61729430Sbloom { 61858755Seric extern char *errstring(); 61958755Seric 62057736Seric if (tTd(16, 1)) 62158755Seric printf("Connect failed (%s); trying new address....\n", 62258755Seric errstring(sav_errno)); 62358778Seric switch (addr.sa.sa_family) 62458778Seric { 62558778Seric #ifdef NETINET 62658778Seric case AF_INET: 62758755Seric bcopy(hp->h_addr_list[i++], 62858778Seric &addr.sin.sin_addr, 62958755Seric hp->h_length); 63058778Seric break; 63158778Seric #endif 63258778Seric 63358778Seric default: 63458755Seric bcopy(hp->h_addr_list[i++], 63558778Seric addr.sa.sa_data, 63652106Seric hp->h_length); 63758778Seric break; 63858778Seric } 63957736Seric continue; 64029430Sbloom } 64129430Sbloom 6426039Seric /* failure, decide if temporary or not */ 6436039Seric failure: 64458542Seric if (transienterror(sav_errno)) 64558542Seric return EX_TEMPFAIL; 64658542Seric else 64758542Seric { 64858542Seric extern char *errstring(); 64911147Seric 65058542Seric message("%s", errstring(sav_errno)); 65158542Seric return (EX_UNAVAILABLE); 6526039Seric } 6536039Seric } 6546039Seric 6556039Seric /* connection ok, put it into canonical form */ 65653739Seric mci->mci_out = fdopen(s, "w"); 65753739Seric mci->mci_in = fdopen(dup(s), "r"); 6586039Seric 65910098Seric return (EX_OK); 6606039Seric } 66110758Seric /* 66210758Seric ** MYHOSTNAME -- return the name of this host. 66310758Seric ** 66410758Seric ** Parameters: 66510758Seric ** hostbuf -- a place to return the name of this host. 66612313Seric ** size -- the size of hostbuf. 66710758Seric ** 66810758Seric ** Returns: 66910758Seric ** A list of aliases for this host. 67010758Seric ** 67110758Seric ** Side Effects: 67258110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 67310758Seric */ 6746039Seric 67558110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 67658110Seric 67710758Seric char ** 67812313Seric myhostname(hostbuf, size) 67910758Seric char hostbuf[]; 68012313Seric int size; 68110758Seric { 68258110Seric register struct hostent *hp; 68310758Seric extern struct hostent *gethostbyname(); 68410758Seric 68523120Seric if (gethostname(hostbuf, size) < 0) 68623120Seric { 68723120Seric (void) strcpy(hostbuf, "localhost"); 68823120Seric } 68911147Seric hp = gethostbyname(hostbuf); 69011147Seric if (hp != NULL) 69116877Seric { 69258110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 69358110Seric hostbuf[size - 1] = '\0'; 69458110Seric 69558110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 69658110Seric { 69758110Seric register int i; 69858110Seric 69958110Seric for (i = 0; i < MAXIPADDR; i++) 70058110Seric { 70158110Seric if (hp->h_addr_list[i] == NULL) 70258110Seric break; 70358110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 70458110Seric } 70558110Seric MyIpAddrs[i].s_addr = 0; 70658110Seric } 70758110Seric 70811147Seric return (hp->h_aliases); 70916877Seric } 71010758Seric else 71110758Seric return (NULL); 71210758Seric } 71351315Seric /* 714*58951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 71558308Seric ** 716*58951Seric ** Uses RFC1413 protocol to try to get info from the other end. 717*58951Seric ** 71858308Seric ** Parameters: 71958308Seric ** fd -- the descriptor 72058308Seric ** 72158308Seric ** Returns: 722*58951Seric ** The user@host information associated with this descriptor. 72358308Seric ** 72458308Seric ** Side Effects: 725*58951Seric ** Sets RealHostName to the name of the host at the other end. 72658308Seric */ 72758308Seric 728*58951Seric #define IDENTPROTO 1 729*58951Seric 730*58951Seric #ifdef IDENTPROTO 731*58951Seric 732*58951Seric static jmp_buf CtxAuthTimeout; 733*58951Seric 734*58951Seric static 735*58951Seric authtimeout() 736*58951Seric { 737*58951Seric longjmp(CtxAuthTimeout, 1); 738*58951Seric } 739*58951Seric 740*58951Seric #endif 741*58951Seric 74258308Seric char * 743*58951Seric getauthinfo(fd) 74458308Seric int fd; 74558308Seric { 746*58951Seric SOCKADDR fa; 747*58951Seric int falen; 748*58951Seric #ifdef IDENTPROTO 749*58951Seric SOCKADDR la; 750*58951Seric int lalen; 751*58951Seric register struct servent *sp; 752*58951Seric int s; 753*58951Seric int i; 754*58951Seric register char *p; 755*58951Seric EVENT *ev; 756*58951Seric #endif 757*58951Seric static char hbuf[MAXNAME * 2 + 2]; 758*58951Seric extern char *hostnamebyanyaddr(); 759*58951Seric extern char RealUserName[]; /* main.c */ 76058308Seric 761*58951Seric falen = sizeof fa; 762*58951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 763*58951Seric { 764*58951Seric RealHostName = "localhost"; 765*58951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 766*58951Seric if (tTd(29, 1)) 767*58951Seric printf("getauthinfo: %s\n", hbuf); 768*58951Seric return hbuf; 769*58951Seric } 770*58951Seric 771*58951Seric RealHostName = newstr(hostnamebyanyaddr(&fa)); 772*58951Seric RealHostAddr = fa; 773*58951Seric 774*58951Seric #ifdef IDENTPROTO 775*58951Seric lalen = sizeof la; 776*58951Seric if (fa.sa.sa_family != AF_INET || 777*58951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 778*58951Seric la.sa.sa_family != AF_INET) 779*58951Seric { 780*58951Seric /* no ident info */ 781*58951Seric goto noident; 782*58951Seric } 783*58951Seric 784*58951Seric /* create ident query */ 785*58951Seric (void) sprintf(hbuf, "%d,%d\r\n", fa.sin.sin_port, la.sin.sin_port); 786*58951Seric 787*58951Seric /* create local address */ 788*58951Seric bzero(&la, sizeof la); 789*58951Seric 790*58951Seric /* create foreign address */ 791*58951Seric sp = getservbyname("auth", "tcp"); 792*58951Seric if (sp != NULL) 793*58951Seric fa.sin.sin_port = sp->s_port; 79458308Seric else 795*58951Seric fa.sin.sin_port = 113; 796*58951Seric 797*58951Seric s = -1; 798*58951Seric if (setjmp(CtxAuthTimeout) != 0) 799*58951Seric { 800*58951Seric if (s >= 0) 801*58951Seric (void) close(s); 802*58951Seric goto noident; 803*58951Seric } 804*58951Seric 805*58951Seric /* put a timeout around the whole thing */ 806*58951Seric ev = setevent((time_t) 30, authtimeout, 0); 807*58951Seric 808*58951Seric /* connect to foreign IDENT server */ 809*58951Seric s = socket(AF_INET, SOCK_STREAM, 0); 810*58951Seric if (s < 0) 811*58951Seric { 812*58951Seric clrevent(ev); 813*58951Seric goto noident; 814*58951Seric } 815*58951Seric if (connect(s, &fa.sa, sizeof fa.sin) < 0) 816*58951Seric { 817*58951Seric closeident: 818*58951Seric (void) close(s); 819*58951Seric clrevent(ev); 820*58951Seric goto noident; 821*58951Seric } 822*58951Seric 823*58951Seric if (tTd(29, 1)) 824*58951Seric printf("getauthinfo: sent %s", hbuf); 825*58951Seric 826*58951Seric /* send query */ 827*58951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 828*58951Seric goto closeident; 829*58951Seric 830*58951Seric /* get result */ 831*58951Seric i = read(s, hbuf, sizeof hbuf); 832*58951Seric (void) close(s); 833*58951Seric clrevent(ev); 834*58951Seric if (i <= 0) 835*58951Seric goto noident; 836*58951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 837*58951Seric i--; 838*58951Seric hbuf[++i] = '\0'; 839*58951Seric 840*58951Seric if (tTd(29, 1)) 841*58951Seric printf("getauthinfo: got %s\n", hbuf); 842*58951Seric 843*58951Seric /* parse result */ 844*58951Seric p = strchr(hbuf, ':'); 845*58951Seric if (p == NULL) 846*58951Seric { 847*58951Seric /* malformed response */ 848*58951Seric goto noident; 849*58951Seric } 850*58951Seric while (isascii(*++p) && isspace(*p)) 851*58951Seric continue; 852*58951Seric if (strncasecmp(p, "userid", 6) != 0) 853*58951Seric { 854*58951Seric /* presumably an error string */ 855*58951Seric goto noident; 856*58951Seric } 857*58951Seric p += 6; 858*58951Seric while (isascii(*p) && isspace(*p)) 859*58951Seric p++; 860*58951Seric if (*p++ != ':') 861*58951Seric { 862*58951Seric /* either useridxx or malformed response */ 863*58951Seric goto noident; 864*58951Seric } 865*58951Seric 866*58951Seric /* p now points to the OSTYPE field */ 867*58951Seric p = strchr(p, ':'); 868*58951Seric if (p == NULL) 869*58951Seric { 870*58951Seric /* malformed response */ 871*58951Seric goto noident; 872*58951Seric } 873*58951Seric p++; 874*58951Seric 875*58951Seric /* p now points to the authenticated name */ 876*58951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 877*58951Seric if (RealHostName[0] != '[') 878*58951Seric { 879*58951Seric p = &hbuf[strlen(hbuf)]; 880*58951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 881*58951Seric } 882*58951Seric if (tTd(29, 1)) 883*58951Seric printf("getauthinfo: %s\n", hbuf); 88458308Seric return hbuf; 885*58951Seric 886*58951Seric #endif /* IDENTPROTO */ 887*58951Seric 888*58951Seric noident: 889*58951Seric return NULL; 89058308Seric } 89158308Seric /* 89253751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 89353751Seric ** 89453751Seric ** Parameters: 89556823Seric ** map -- a pointer to this map (unused). 89653751Seric ** hbuf -- a buffer containing a hostname. 89753751Seric ** hbsize -- the size of hbuf. 89855019Seric ** avp -- unused -- for compatibility with other mapping 89955019Seric ** functions. 90053751Seric ** 90153751Seric ** Returns: 90253751Seric ** The mapping, if found. 90353751Seric ** NULL if no mapping found. 90453751Seric ** 90553751Seric ** Side Effects: 90653751Seric ** Looks up the host specified in hbuf. If it is not 90753751Seric ** the canonical name for that host, return the canonical 90853751Seric ** name. 90953751Seric */ 91051315Seric 91153751Seric char * 91256823Seric maphostname(map, hbuf, hbsize, avp) 91356823Seric MAP *map; 91416911Seric char *hbuf; 91516911Seric int hbsize; 91653751Seric char **avp; 91716911Seric { 91816911Seric register struct hostent *hp; 91933932Sbostic u_long in_addr; 92056823Seric char *cp; 92158110Seric int i; 92233932Sbostic struct hostent *gethostbyaddr(); 92316911Seric 92456836Seric /* allow room for null */ 92556823Seric hbsize--; 92653751Seric 92725574Smiriam /* 92833932Sbostic * If first character is a bracket, then it is an address 92933932Sbostic * lookup. Address is copied into a temporary buffer to 93033932Sbostic * strip the brackets and to preserve hbuf if address is 93133932Sbostic * unknown. 93233932Sbostic */ 93353751Seric 93451315Seric if (*hbuf != '[') 93553751Seric { 93655019Seric extern bool getcanonname(); 93755019Seric 93858798Seric if (tTd(9, 1)) 93958798Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 94058674Seric if (getcanonname(hbuf, hbsize)) 94158796Seric { 94258796Seric if (tTd(9, 1)) 94358796Seric printf("%s\n", hbuf); 94453751Seric return hbuf; 94558796Seric } 94653751Seric else 94758796Seric { 94858796Seric if (tTd(9, 1)) 94958796Seric printf("FAIL\n"); 95053751Seric return NULL; 95158796Seric } 95253751Seric } 95356823Seric if ((cp = strchr(hbuf, ']')) == NULL) 95453751Seric return (NULL); 95540994Sbostic *cp = '\0'; 95656823Seric in_addr = inet_addr(&hbuf[1]); 95758110Seric 95858110Seric /* check to see if this is one of our addresses */ 95958110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 96058110Seric { 96158110Seric if (MyIpAddrs[i].s_addr == in_addr) 96258110Seric { 96358110Seric strncpy(hbuf, MyHostName, hbsize); 96458110Seric hbuf[hbsize] = '\0'; 96558110Seric return hbuf; 96658110Seric } 96758110Seric } 96858110Seric 96958110Seric /* nope -- ask the name server */ 97033932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 97133932Sbostic if (hp == NULL) 97253751Seric return (NULL); 97353751Seric 97458110Seric /* found a match -- copy out */ 97556823Seric if (strlen(hp->h_name) > hbsize) 97656823Seric hp->h_name[hbsize] = '\0'; 97753751Seric (void) strcpy(hbuf, hp->h_name); 97853751Seric return hbuf; 97933932Sbostic } 98058755Seric /* 98158755Seric ** ANYNET_NTOA -- convert a network address to printable form. 98258755Seric ** 98358755Seric ** Parameters: 98458755Seric ** sap -- a pointer to a sockaddr structure. 98558755Seric ** 98658755Seric ** Returns: 98758755Seric ** A printable version of that sockaddr. 98858755Seric */ 98916911Seric 99058755Seric char * 99158755Seric anynet_ntoa(sap) 99258755Seric register SOCKADDR *sap; 99358755Seric { 99458755Seric register char *bp; 99558755Seric register char *ap; 99658755Seric int l; 99758755Seric static char buf[80]; 99858755Seric 99958798Seric /* check for null/zero family */ 100058798Seric if (sap == NULL) 100158798Seric return "NULLADDR"; 100258798Seric if (sap->sa.sa_family == 0) 100358798Seric return "0"; 100458798Seric 100558778Seric #ifdef NETINET 100658778Seric if (sap->sa.sa_family == AF_INET) 100758755Seric { 100858755Seric extern char *inet_ntoa(); 100958755Seric 101058755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 101158755Seric } 101258778Seric #endif 101358755Seric 101458755Seric /* unknown family -- just dump bytes */ 101558778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 101658755Seric bp = &buf[strlen(buf)]; 101758778Seric ap = sap->sa.sa_data; 101858778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 101958755Seric { 102058755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 102158755Seric bp += 3; 102258755Seric } 102358755Seric *--bp = '\0'; 102458755Seric return buf; 102558755Seric } 1026*58951Seric /* 1027*58951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 1028*58951Seric ** 1029*58951Seric ** Parameters: 1030*58951Seric ** sap -- SOCKADDR pointer 1031*58951Seric ** 1032*58951Seric ** Returns: 1033*58951Seric ** text representation of host name. 1034*58951Seric ** 1035*58951Seric ** Side Effects: 1036*58951Seric ** none. 1037*58951Seric */ 103858755Seric 1039*58951Seric char * 1040*58951Seric hostnamebyanyaddr(sap) 1041*58951Seric register SOCKADDR *sap; 1042*58951Seric { 1043*58951Seric register struct hostent *hp; 1044*58951Seric 1045*58951Seric switch (sap->sa.sa_family) 1046*58951Seric { 1047*58951Seric #ifdef NETINET 1048*58951Seric case AF_INET: 1049*58951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 1050*58951Seric sizeof sap->sin.sin_addr, 1051*58951Seric AF_INET); 1052*58951Seric break; 1053*58951Seric #endif 1054*58951Seric 1055*58951Seric #ifdef NETISO 1056*58951Seric case AF_ISO: 1057*58951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 1058*58951Seric sizeof sap->siso.siso_addr, 1059*58951Seric AF_ISO); 1060*58951Seric break; 1061*58951Seric #endif 1062*58951Seric 1063*58951Seric default: 1064*58951Seric hp = gethostbyaddr(sap->sa.sa_data, 1065*58951Seric sizeof sap->sa.sa_data, 1066*58951Seric sap->sa.sa_family); 1067*58951Seric break; 1068*58951Seric } 1069*58951Seric 1070*58951Seric if (hp != NULL) 1071*58951Seric return hp->h_name; 1072*58951Seric else 1073*58951Seric { 1074*58951Seric /* produce a dotted quad */ 1075*58951Seric static char buf[512]; 1076*58951Seric 1077*58951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 1078*58951Seric return buf; 1079*58951Seric } 1080*58951Seric } 1081*58951Seric 108256795Seric # else /* DAEMON */ 108316911Seric /* code for systems without sophisticated networking */ 108410758Seric 108510758Seric /* 108610758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 108711297Seric ** 108811297Seric ** Can't convert to upper case here because might be a UUCP name. 108912313Seric ** 109012313Seric ** Mark, you can change this to be anything you want...... 109110758Seric */ 109210758Seric 109310758Seric char ** 109412313Seric myhostname(hostbuf, size) 109510758Seric char hostbuf[]; 109612313Seric int size; 109710758Seric { 109810758Seric register FILE *f; 109910758Seric 110010758Seric hostbuf[0] = '\0'; 110110758Seric f = fopen("/usr/include/whoami", "r"); 110210758Seric if (f != NULL) 110310758Seric { 110412313Seric (void) fgets(hostbuf, size, f); 110510758Seric fixcrlf(hostbuf, TRUE); 110610758Seric (void) fclose(f); 110710758Seric } 110810758Seric return (NULL); 110910758Seric } 111016911Seric /* 1111*58951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 111258308Seric ** 111358308Seric ** Parameters: 111458308Seric ** fd -- the descriptor 111558308Seric ** 111658308Seric ** Returns: 111758308Seric ** The host name associated with this descriptor, if it can 111858308Seric ** be determined. 111958308Seric ** NULL otherwise. 112058308Seric ** 112158308Seric ** Side Effects: 112258308Seric ** none 112358308Seric */ 112458308Seric 112558308Seric char * 1126*58951Seric getauthinfo(fd) 112758308Seric int fd; 112858308Seric { 112958308Seric return NULL; 113058308Seric } 113158308Seric /* 113216911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 113316911Seric ** 113416911Seric ** Parameters: 113556823Seric ** map -- a pointer to the database map. 113616911Seric ** hbuf -- a buffer containing a hostname. 113753751Seric ** avp -- a pointer to a (cf file defined) argument vector. 113816911Seric ** 113916911Seric ** Returns: 114053751Seric ** mapped host name 114151315Seric ** FALSE otherwise. 114216911Seric ** 114316911Seric ** Side Effects: 114416911Seric ** Looks up the host specified in hbuf. If it is not 114516911Seric ** the canonical name for that host, replace it with 114616911Seric ** the canonical name. If the name is unknown, or it 114716911Seric ** is already the canonical name, leave it unchanged. 114816911Seric */ 114910758Seric 115016911Seric /*ARGSUSED*/ 115153751Seric char * 115256823Seric maphostname(map, hbuf, hbsize, avp) 115356823Seric MAP *map; 115416911Seric char *hbuf; 115516911Seric int hbsize; 115653751Seric char **avp; 115716911Seric { 115853751Seric return NULL; 115916911Seric } 116016911Seric 116156795Seric #endif /* DAEMON */ 1162