20.2 The CookbookIn this section we show several examples of possible uses for the checkcompat () routine. Among those we illustrate are the following:
Note that in all of the following examples the numbers to the left indicate line numbers for discussion and are not a part of the code. 20.2.1 Accept Mail Only From Our DomainIf your site lives behind a firewall , [2] you might want to use checkcompat () to configure the internal sendmail so that it accepts only mail that is generated locally. The external sendmail (outside the firewall or part of it) acts as a proxy. That is, it accepts external mail that is destined for internal delivery from the outside and forwards it to the internal sendmail . Because the external sendmail is part of the local domain, its envelope always appears to be local. Any external mail that somehow bypasses the firewall needs to be bounced. The way to do this in checkcompat () looks like this:
# define OUR_NET_IN_HEX 0x7b2d4300 /* 123.45.67.0 in hex */ # define OUR_NETMASK 0xffffff00 checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { if (tTd(49, 1)) printf("checkcompat(to=%s, from=%s)\n", to->q_paddr, e->e_from.q_paddr); if (RealHostAddr.sa.sa_family == 0) { /* this is a locally submitted message */ return EX_OK; } if (RealHostAddr.sa.sa_family != AF_INET || (RealHostAddr.sin.sin_addr.s_addr & OUR_NETMASK)!= OUR_NET_IN_HEX) {
The The EF_NO_BODY_RETN (line 22 ) causes only the headers from the message to be returned in bounced mail, not the original message body. Other envelope flags of interest can be found in Table 37.3 of Section 37.5.12 .
The
Also note that this code sample is only a suggestion. It doesn't take into account
that 20.2.2 Workstation Refuses to Act as a Mail GatewayIf you've spent many months getting your workstation set up and running perfectly, you might not want outsiders using it as a knowledgeable mail relay. One way to prevent such unwanted use is to set up checkcompat () in conf.c so that it rejects any mail from outside your machine that is destined to another site outside your machine. A desirable side effect is that this will also prevent outsiders from directly posting into your internal mailing lists.
checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { if (tTd(49, 1)) printf("checkcompat(to=%s, from=%s)\n", to->q_paddr, e->e_from.q_paddr); if (RealHostAddr.sa.sa_family == 0) { /* this is a locally submitted message */ return (EX_OK); } /* only accept local delivery from outside */
Although Note that this form of rejecting messages will not work on a mail hub. In that case more sophisticated checks need to be made. Among them are the following:
20.2.3 Limit the Size of Guest MessagesSuppose your site has reserved uid s numbered from 900 to 999 for guest users. Because guests are sometimes inconsiderate, you might want to limit the size of their messages and the number of simultaneous recipients they may specify. One way to do this is with the checkcompat () routine:
#define MAXGUESTSIZE 8000 #define MAXGUESTNRCP 4 checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { if (tTd(49, 1)) printf("checkcompat(to=%s, from=%s)\n", to->q_paddr, e->e_from.q_paddr); /* does q_uid contain a valid uid? - no external */
Note that Also note that we specifically do not return the message body (EF_NO_BODY_RETN) if the message was returned because it was too large (line 24 ). But we do return the message body if the message was rejected for too many recipients (line 35 ). Other envelope flags of interest can be found in Table 37.3 of Section 37.5.12 . 20.2.4 Verify identd Information
When an outside host connects to the local
sendmail
via SMTP,
its hostname is saved in the
If you are unusually picky about the identity of other hosts,
you may wish to confirm that the host in
checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { char *s, *u, *v; int len; static char old_s[MAXHOSTNAMELEN]; if (tTd(49, 1)) printf("checkcompat(to=%s, from=%s)\n", to->q_paddr, e->e_from.q_paddr); /* if $s is localhost or in $=w, accept it */ if ((s = macvalue('s', e)) == NULL) return (EX_OK);
First (line
16
) we check to see whether we have already checked
this value of
Then we make sure that the local host (no
matter what its name) is acceptable (lines
20
and
22
).
If this is an offsite host,
we compare the values of 20.2.5 Prune Received: Headers at Firewall
In routing mail outward from a firewall (see
Section 20.2.1
),
it may be advantageous to
replace all the internal
# define OUR_NET_IN_HEX 0x7b2d4300 /* 123.45.67.0 in hex */ # define OUR_NETMASK 0xffffff00 # define LOOP_CHECK "X-Loop-Check" checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { HDR *h; int cnt;
Because we are stripping the message of
If it is okay to do so, we scan all the headers (line
30
) looking
for all
Be aware that this is only one possible approach and that, depending on
what other hosts on the Internet do to the message, this loop detection may
break. A safer but more difficult approach is to rewrite the 20.2.6 Reject Mail from Spamming or Mail-bombing SitesAs the Internet grows, your site may become more and more subject to advertising and vengeful attacks from the outside. Advertising attacks are called "spams" and are symptomized by advertisers sending multiple copies of advertisements through your internal mail lists or to several of your users. Vengeful attacks are called "mail bombs" and usually are detected by your mail spool directory filling with a huge number of messages from a single sender. [3]
To limit your vulnerability to such events (and to others of a similar nature that may be invented in the future), you may screen mail from outside hosts using a combination of a database and checkcompat (). First we show you how to set up such a database, then we show you a checkcompat () routine for using it. [4]
The source file for the database will look like this:
user@spam.host spam user@bomb.host bomb
Here, each left-hand side entry is an email address with a user part,
an If the source file is called /etc/mail/blockusers , the database will be created like this:
%
Here, we create a
Once the database is in place, your configuration file needs to be
told of its existence. To do that, we use the
Kbadusers hash -o /etc/mail/blockusers.db For the m4 configuration technique you would place this declaration under the LOCAL_CONFIG line in your mc file (see Section 19.6.30, LOCAL-CONFIG ). One possible checkcompat () routine to handle all this will look like this:
checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { STAB *map; char *p; int ret = 0;
Here we first look up the database named
If the address was found in the database, we have a potential bad person. So we first
check to see whether the address was marked as a We also bounce the message if it is a mail bomb (line 24 ). This is fraught with risk however. The bounced mail can fill up the outgoing queue, thereby accomplishing the bomber's ends in a different way. A better approach might be to drop the mail on the floor (see dropenvelope () in envelope.c ), but we leave this as an exercise for the reader. |
|