summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/daemon.c')
-rw-r--r--usr.sbin/sendmail/src/daemon.c245
1 files changed, 187 insertions, 58 deletions
diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c
index bd8a9146de2eb..41f1a7286d777 100644
--- a/usr.sbin/sendmail/src/daemon.c
+++ b/usr.sbin/sendmail/src/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995, 1996 Eric P. Allman
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -37,13 +37,17 @@
#ifndef lint
#ifdef DAEMON
-static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (with daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.175 (Berkeley) 6/1/97 (with daemon mode)";
#else
-static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (without daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.175 (Berkeley) 6/1/97 (without daemon mode)";
#endif
#endif /* not lint */
-#if DAEMON || defined(SOCK_STREAM)
+#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
+# define USE_SOCK_STREAM 1
+#endif
+
+#if DAEMON || defined(USE_SOCK_STREAM)
# include <arpa/inet.h>
# if NAMED_BIND
# include <resolv.h>
@@ -55,6 +59,8 @@ static char sccsid[] = "@(#)daemon.c 8.159 (Berkeley) 1/14/97 (without daemon mo
#if DAEMON
+# include <sys/time.h>
+
# if IP_SRCROUTE
# include <netinet/in_systm.h>
# include <netinet/ip.h>
@@ -166,8 +172,12 @@ getrequests(e)
/* write the pid to the log file for posterity */
pidf = safefopen(PidFile, O_WRONLY|O_CREAT|O_TRUNC, 0644,
- SFF_NOSLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT);
- if (pidf != NULL)
+ SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT);
+ if (pidf == NULL)
+ {
+ sm_syslog(LOG_ERR, NOQID, "unable to write %s", PidFile);
+ }
+ else
{
extern char *CommandLineArgs;
@@ -200,7 +210,6 @@ getrequests(e)
int savederrno;
int pipefd[2];
extern bool refuseconnections();
- extern int getla();
/* see if we are rejecting connections */
(void) blocksignal(SIGALRM);
@@ -234,13 +243,15 @@ getrequests(e)
if (!wordinclass(jbuf, 'w'))
{
dumpstate("daemon lost $j");
- syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog");
+ sm_syslog(LOG_ALERT, NOQID,
+ "daemon process doesn't have $j in $=w; see syslog");
abort();
}
else if (j_has_dot && strchr(jbuf, '.') == NULL)
{
dumpstate("daemon $j lost dot");
- syslog(LOG_ALERT, "daemon process $j lost dot; see syslog");
+ sm_syslog(LOG_ALERT, NOQID,
+ "daemon process $j lost dot; see syslog");
abort();
}
}
@@ -260,13 +271,29 @@ getrequests(e)
log an error here;
#endif
(void) releasesignal(SIGALRM);
- do
+ for (;;)
{
+ fd_set readfds;
+ struct timeval timeout;
+
+ FD_ZERO(&readfds);
+ FD_SET(DaemonSocket, &readfds);
+ timeout.tv_sec = 60;
+ timeout.tv_usec = 0;
+
+ t = select(DaemonSocket + 1, &readfds, NULL, NULL, &timeout);
+ if (DoQueueRun)
+ (void) runqueue(TRUE, FALSE);
+ if (t <= 0 || !FD_ISSET(DaemonSocket, &readfds))
+ continue;
+
errno = 0;
lotherend = socksize;
t = accept(DaemonSocket,
(struct sockaddr *)&RealHostAddr, &lotherend);
- } while (t < 0 && errno == EINTR);
+ if (t >= 0 || errno != EINTR)
+ break;
+ }
savederrno = errno;
(void) blocksignal(SIGALRM);
if (t < 0)
@@ -381,6 +408,9 @@ getrequests(e)
OutChannel = outchannel;
DisConnected = FALSE;
+ /* open maps for check_relay ruleset */
+ initmaps(FALSE, e);
+
/* validate the connection */
HoldErrs = TRUE;
nullconn = !validate_connection(&RealHostAddr, RealHostName, e);
@@ -463,10 +493,9 @@ opendaemonsocket(firsttime)
saveerrno = errno;
syserr("opendaemonsocket: can't create server SMTP socket");
severe:
-# ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "problem creating SMTP socket");
-# endif /* LOG */
+ sm_syslog(LOG_ALERT, NOQID,
+ "problem creating SMTP socket");
DaemonSocket = -1;
continue;
}
@@ -747,7 +776,7 @@ makeconnection(host, port, mci, e)
register MCI *mci;
ENVELOPE *e;
{
- register volatile int i = 0;
+ register volatile int addrno = 0;
register volatile int s;
register struct hostent *volatile hp = (struct hostent *)NULL;
SOCKADDR addr;
@@ -870,7 +899,7 @@ gothostent:
hp->h_length);
break;
}
- i = 1;
+ addrno = 1;
}
/*
@@ -883,10 +912,9 @@ gothostent:
if (sp == NULL)
{
-#ifdef LOG
if (LogLevel > 2)
- syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown");
-#endif
+ sm_syslog(LOG_ERR, NOQID,
+ "makeconnection: service \"smtp\" unknown");
port = htons(25);
}
else
@@ -988,22 +1016,23 @@ gothostent:
if (setjmp(CtxConnectTimeout) == 0)
{
+ int i;
+
if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
else if (TimeOuts.to_connect != 0)
ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
else
ev = NULL;
- if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
- {
- if (ev != NULL)
- clrevent(ev);
+ i = connect(s, (struct sockaddr *) &addr, addrlen);
+ sav_errno = errno;
+ if (ev != NULL)
+ clrevent(ev);
+ if (i >= 0)
break;
- }
}
- sav_errno = errno;
- if (ev != NULL)
- clrevent(ev);
+ else
+ sav_errno = errno;
/* if running demand-dialed connection, try again */
if (DialDelay > 0 && firstconnect)
@@ -1018,7 +1047,7 @@ gothostent:
/* couldn't connect.... figure out why */
(void) close(s);
- if (hp != NULL && hp->h_addr_list[i])
+ if (hp != NULL && hp->h_addr_list[addrno])
{
if (tTd(16, 1))
printf("Connect failed (%s); trying new address....\n",
@@ -1027,14 +1056,14 @@ gothostent:
{
#if NETINET
case AF_INET:
- bcopy(hp->h_addr_list[i++],
+ bcopy(hp->h_addr_list[addrno++],
&addr.sin.sin_addr,
INADDRSZ);
break;
#endif
default:
- bcopy(hp->h_addr_list[i++],
+ bcopy(hp->h_addr_list[addrno++],
addr.sa.sa_data,
hp->h_length);
break;
@@ -1129,19 +1158,17 @@ myhostname(hostbuf, size)
if (strchr(hostbuf, '.') == NULL &&
!getcanonname(hostbuf, size, TRUE))
{
-#ifdef LOG
- syslog(LOG_CRIT, "My unqualified host name (%s) unknown; sleeping for retry",
+ sm_syslog(LOG_CRIT, NOQID,
+ "My unqualified host name (%s) unknown; sleeping for retry",
hostbuf);
-#endif
message("My unqualified host name (%s) unknown; sleeping for retry",
hostbuf);
sleep(60);
if (!getcanonname(hostbuf, size, TRUE))
{
-#ifdef LOG
- syslog(LOG_ALERT, "unable to qualify my own domain name (%s) -- using short name",
+ sm_syslog(LOG_ALERT, NOQID,
+ "unable to qualify my own domain name (%s) -- using short name",
hostbuf);
-#endif
message("WARNING: unable to qualify my own domain name (%s) -- using short name",
hostbuf);
}
@@ -1181,6 +1208,9 @@ getauthinfo(fd)
int i;
EVENT *ev;
int nleft;
+ struct hostent *hp;
+ char **ha;
+ bool may_be_forged;
char ibuf[MAXNAME + 1];
static char hbuf[MAXNAME * 2 + 2];
@@ -1203,6 +1233,30 @@ getauthinfo(fd)
RealHostName[MAXNAME - 1] = '\0';
}
+ /* cross check RealHostName with forward DNS lookup */
+ if (anynet_ntoa(&RealHostAddr)[0] == '[')
+ {
+ /* address is not a socket */
+ may_be_forged = FALSE;
+ }
+ else
+ {
+ /* try to match the reverse against the forward lookup */
+ hp = gethostbyname(RealHostName);
+
+ if (hp == NULL)
+ may_be_forged = TRUE;
+ else
+ {
+ for (ha = hp->h_addr_list; *ha != NULL; ha++)
+ if (bcmp(*ha,
+ (char *) &RealHostAddr.sin.sin_addr,
+ hp->h_length) == 0)
+ break;
+ may_be_forged = *ha == NULL;
+ }
+ }
+
if (TimeOuts.to_ident == 0)
goto noident;
@@ -1340,6 +1394,9 @@ noident:
postident:
#if IP_SRCROUTE
+# ifndef GET_IPOPT_DST
+# define GET_IPOPT_DST(dst) (dst)
+# endif
/*
** Extract IP source routing information.
**
@@ -1383,21 +1440,31 @@ postident:
case IPOPT_SSRR:
case IPOPT_LSRR:
+ /*
+ ** Source routing.
+ ** o[0] is the option type (loose/strict).
+ ** o[1] is the length of this option,
+ ** including option type and
+ ** length.
+ ** o[2] is the pointer into the route
+ ** data.
+ ** o[3] begins the route data.
+ */
+
p = &hbuf[strlen(hbuf)];
l = sizeof hbuf - (hbuf - p) - 6;
snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s",
*o == IPOPT_SSRR ? "!" : "",
l > 240 ? 120 : l / 2,
- inet_ntoa(ipopt.ipopt_dst));
+ inet_ntoa(GET_IPOPT_DST(ipopt.ipopt_dst)));
i = strlen(p);
p += i;
l -= strlen(p);
- /* o[1] is option length */
- j = *++o / sizeof(struct in_addr) - 1;
+ j = o[1] / sizeof(struct in_addr) - 1;
/* q skips length and router pointer to data */
- q = o + 2;
+ q = &o[3];
for ( ; j >= 0; j--)
{
memcpy(&addr, q, sizeof(addr));
@@ -1412,7 +1479,7 @@ postident:
l -= i + 1;
q += sizeof(struct in_addr);
}
- o += *o;
+ o += o[1];
break;
default:
@@ -1433,6 +1500,11 @@ noipsr:
(void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]",
anynet_ntoa(&RealHostAddr));
}
+ if (may_be_forged)
+ {
+ p = &hbuf[strlen(hbuf)];
+ (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)");
+ }
postipsr:
if (tTd(9, 1))
@@ -1443,7 +1515,7 @@ postipsr:
** HOST_MAP_LOOKUP -- turn a hostname into canonical form
**
** Parameters:
-** map -- a pointer to this map (unused).
+** map -- a pointer to this map.
** name -- the (presumably unqualified) hostname.
** av -- unused -- for compatibility with other mapping
** functions.
@@ -1457,7 +1529,8 @@ postipsr:
** Side Effects:
** Looks up the host specified in hbuf. If it is not
** the canonical name for that host, return the canonical
-** name.
+** name (unless MF_MATCHONLY is set, which will cause the
+** status only to be returned).
*/
char *
@@ -1498,7 +1571,16 @@ host_map_lookup(map, name, av, statp)
message("851 %s: Name server timeout",
shortenstring(name, 33));
}
- return s->s_namecanon.nc_cname;
+ if (*statp != EX_OK)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ cp = map_rewrite(map, name, strlen(name), NULL);
+ else
+ cp = map_rewrite(map,
+ s->s_namecanon.nc_cname,
+ strlen(s->s_namecanon.nc_cname),
+ av);
+ return cp;
}
/*
@@ -1532,16 +1614,12 @@ host_map_lookup(map, name, av, statp)
{
if (tTd(9, 1))
printf("%s\n", hbuf);
+ s->s_namecanon.nc_stat = EX_OK;
+ s->s_namecanon.nc_cname = newstr(hbuf);
if (bitset(MF_MATCHONLY, map->map_mflags))
- {
- cp = map_rewrite(map, name, strlen(name), av);
- s->s_namecanon.nc_cname = newstr(hbuf);
- }
+ cp = map_rewrite(map, name, strlen(name), NULL);
else
- {
cp = map_rewrite(map, hbuf, strlen(hbuf), av);
- s->s_namecanon.nc_cname = newstr(cp);
- }
return cp;
}
else
@@ -1589,6 +1667,7 @@ host_map_lookup(map, name, av, statp)
return (NULL);
*cp = '\0';
in_addr.s_addr = inet_addr(&name[1]);
+ *cp = ']';
/* nope -- ask the name server */
hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET);
@@ -1604,9 +1683,12 @@ host_map_lookup(map, name, av, statp)
}
/* found a match -- copy out */
- cp = map_rewrite(map, (char *) hp->h_name, strlen(hp->h_name), av);
s->s_namecanon.nc_stat = *statp = EX_OK;
- s->s_namecanon.nc_cname = newstr(cp);
+ s->s_namecanon.nc_cname = newstr(hp->h_name);
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ cp = map_rewrite(map, name, strlen(name), NULL);
+ else
+ cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av);
return cp;
}
@@ -1688,16 +1770,63 @@ host_map_lookup(map, name, avp, statp)
char *statp;
{
register struct hostent *hp;
+ char *cp;
hp = sm_gethostbyname(name);
- if (hp != NULL)
- return hp->h_name;
- *statp = EX_NOHOST;
- return NULL;
+ if (hp == NULL)
+ {
+ *statp = EX_NOHOST;
+ return NULL;
+ }
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ cp = map_rewrite(map, name, strlen(name), NULL);
+ else
+ cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av);
+ return cp;
}
#endif /* DAEMON */
/*
+** HOST_MAP_INIT -- initialize host class structures
+*/
+
+bool
+host_map_init(map, args)
+ MAP *map;
+ char *args;
+{
+ register char *p = args;
+
+ for (;;)
+ {
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p != '-')
+ break;
+ switch (*++p)
+ {
+ case 'a':
+ map->map_app = ++p;
+ break;
+
+ case 'm':
+ map->map_mflags |= MF_MATCHONLY;
+ break;
+
+ case 't':
+ map->map_mflags |= MF_NODEFER;
+ break;
+ }
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+ }
+ if (map->map_app != NULL)
+ map->map_app = newstr(map->map_app);
+ return TRUE;
+}
+ /*
** ANYNET_NTOA -- convert a network address to printable form.
**
** Parameters:
@@ -1707,7 +1836,7 @@ host_map_lookup(map, name, avp, statp)
** A printable version of that sockaddr.
*/
-#ifdef SOCK_STREAM
+#ifdef USE_SOCK_STREAM
#if NETLINK
# include <net/if_dl.h>