divert(-1) # Copyright 1997 Steve VanDevender # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. divert(0) VERSIONID(`@(#)relaycontrol.m4 1.2 (Steve VanDevender) 1997-12-18') divert(-1) PUSHDIVERT(6) # Class R contains a list of host/domain names that you want to relay mail # from or to. This can be used to avoid map lookups for common cases, # or to ensure that particular domains are hardwired into your configuration # so that they can't be accidentally deleted from the maps. ifdef(`confRELAYS',`',`#')CR`'ifdef(`confRELAYS', confRELAYS) # Read class R from file ifdef(`_USE_CR_FILE_', `', `#')FR`'ifdef(`confCR_FILE', confCR_FILE, `-o /usr/local/etc/sendmail.cR') # These maps contain a domain name or ip number (maybe partly specified) # on the LHS, and *OK* on the RHS (to avoid confusion with valid host or # user names). The check_rcpt rule below will not accept top-level domain # names (com, org, etc.). Krelay_to_domain ifdef(`RELAY_TO_DOMAIN', RELAY_TO_DOMAIN, `hash -o /usr/local/etc/relay_to_domain') Krelay_to_ip ifdef(`RELAY_TO_IP', RELAY_TO_IP, `hash -o /usr/local/etc/relay_to_ip') Krelay_from_domain ifdef(`RELAY_FROM_DOMAIN', RELAY_FROM_DOMAIN, `hash -o /usr/local/etc/relay_from_domain') Krelay_from_ip ifdef(`RELAY_FROM_IP', RELAY_FROM_IP, `hash -o /usr/local/etc/relay_from_ip') POPDIVERT PUSHDIVERT(9) # check RCPT TO: address. Actually, first check to see if the client is # one we permit to relay through us, and don't bother to check the # recipient if the client is local. If the client is non-local, then # check the recipient using the Relay_to ruleset. Return an error if a # non-local client tries to relay to a non-local address. Scheck_rcpt # check client domain name (save rcpt to: argument for later) R$* $: $(dequote "" $&{client_name} $) $| $1 R$@ $| $* $@ OK permit local user R$=w $| $* $@ OK permit hosts in Cw ifdef(`_R_CLIENTS_', ifdef(`_R_DOMAINS_', `R$* $=R $| $* $@ OK permit domains in CR', `R$=R $| $* $@ OK permit hosts in CR'), `dnl') # check client domain name against relay_from_domain map until found # or remove left component and iterate until down to one token R$-.$+ $| $* $(relay_from_domain $1.$2 $: $2 $) $| $3 R*OK* $| $* $@ OK OK to relay from this client # check client IP address R$* $| $* $: $(dequote "" $&{client_addr} $) $| $2 R0 $| $* $@ OK permit local user # check client IP address against relay_from_ip map until found # or remove right component and iterate until down to one token R$+.$- $| $* $(relay_from_ip $1.$2 $: $1 $) $| $3 R*OK* $| $* $@ OK OK to relay from this client ifdef(`_CLASS_A_RELAY_', `# check class A (/24) IP range R$- $| $* $: $(relay_from_ip $1 $: $1 $) $| $2 R*OK* $| $* $@ OK', `dnl') # check supplied rcpt to: address after dequoting R$* $| $* $: $>Relay_to $(dequote $2 $) R*OK* $@ OK OK to relay to address # If this rule is reached, this recipient should not be accepted R$* $#error $@ ifdef(`RELAY_ERROR', RELAY_ERROR, `5.5.1') $: ifdef(`RELAY_MESSAGE', RELAY_MESSAGE, `"551 Relaying denied"') # Relay_to: check for an address that we will relay mail TO. Accepts # address and canonifies with ruleset 3; returns token *OK* if address # specifies or routes through hosts we will relay to or *NOTOK* for # anything else SRelay_to R$* *OK* $* $@ *NOTOK* reject marker in input R$* $: $>3 $1 canonify and focus R$* <@ $* .> $* $: $1 <@ $2 > $3 remove a trailing . in focus ifdef(`MAILER_TABLE', `# pass domain in focus through mailertable, do not change if not found R$* <@ $+ > $* $: $1 <@ $(mailertable $2 $: $2 $) > $3 R$* <@ $~[ : $+ > $* $: $1 <@ *OK* > $4 permit host found in mailertable', `dnl') R$* <@ $=w > $* $: $1 <@ *OK* > $3 permit hosts in Cw ifdef(`_R_DOMAINS_', `R$* <@ $* $=R > $* $: $1 <@ *OK* > $4 permit domains in CR', `R$* <@ $=R > $* $: $1 <@ *OK* > $3 permit hosts in CR') ifdef(`_CLASS_U_', `R$* <@ $=U . UUCP > $* $: $1 <@ *OK* > $3 permit uucp relay', `dnl') ifdef(`_CLASS_V_', `R$* <@ $=V . UUCP > $* $: $1 <@ *OK* > $3 permit uucp relay', `dnl') ifdef(`_CLASS_W_', `R$* <@ $=W . UUCP > $* $: $1 <@ *OK* > $3 permit uucp relay', `dnl') ifdef(`_CLASS_X_', `R$* <@ $=X . UUCP > $* $: $1 <@ *OK* > $3 permit uucp relay', `dnl') ifdef(`_CLASS_Y_', `R$* <@ $=Y . UUCP > $* $: $1 <@ *OK* > $3 permit uucp relay', `dnl') ifdef(`_CLASS_Z_', `R$* <@ $=Z . UUCP > $* $: $1 <@ *OK* > $3 permit uucp relay', `dnl') # check numeric IP address in focus against relay_to_ip map until found # or remove right component and iterate until down to one token R$* <@[ $+.$- ]> $* $1 <@[ $(relay_to_ip $2.$3 $: $2 $) ]> $4 R$* <@[ *OK* ]> $* $: $1 <@ *OK* > $2 remove brackets around *OK* ifdef(`_CLASS_A_RELAY_', `# check class A (/24) IP address range R$* <@[ $- ]> $* $: $1 <@[ $(relay_to_ip $2 $: $2 $) ]> $3 R$* <@[ *OK* ]> $* $: $1 <@ *OK* > $2 remove brackets around *OK*', `dnl') # check domain name in focus against relay_to_domain map until found # or remove left component and iterate until down to one token R$* <@ $-.$+ > $* $1 <@ $(relay_to_domain $2.$3 $: $3 $) > $4 R$* <@ *OK* > $: $>Relay_to $1 focus is OK, remove it and recurse R<@ *OK* >: $* $: $>Relay_to $1 same for weird source route form R$* <@ $* > $* $@ *NOTOK* reject focus without marker R*NOTOK* $@ *NOTOK* return *NOTOK* from above # if we get here, then it's just a local user form and that's OK R$* $@ *OK* POPDIVERT