/usr/sbin/exim_checkaccess is in exim4-base 4.84.2-2+deb8u5.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | #! /bin/sh
# Copyright (c) University of Cambridge, 1995 - 2007
# See the file NOTICE for conditions of use and distribution.
# Except when they appear in comments, the following placeholders in this
# source are replaced when it is turned into a runnable script:
#
# CONFIGURE_FILE_USE_NODE
# CONFIGURE_FILE
# BIN_DIRECTORY
# PERL_COMMAND
# This file has been so processed.
# A shell+perl wrapper script to run an automated -bh test to check out
# ACLs for incoming addresses.
# Save the shell arguments because we are going to need the shell variables
# while sorting out the configuration file.
args="$@"
# See if this installation is using the esoteric "USE_NODE" feature of Exim,
# in which it uses the host's name as a suffix for the configuration file name.
if [ "" = "yes" ]; then
hostsuffix=.`uname -n`
fi
# Now find the configuration file name. This has got complicated because
# CONFIGURE_FILE may now be a list of files. The one that is used is the first
# one that exists. Mimic the code in readconf.c by testing first for the
# suffixed file in each case.
set `awk -F: '{ for (i = 1; i <= NF; i++) print $i }' <<End
/etc/exim4/exim4.conf:/var/lib/exim4/config.autogenerated
End
`
while [ "$config" = "" -a $# -gt 0 ] ; do
if [ -f "$1$hostsuffix" ] ; then
config="$1$hostsuffix"
elif [ -f "$1" ] ; then
config="$1"
fi
shift
done
# Search for an exim_path setting in the configure file; otherwise use the bin
# directory. BEWARE: a tab character is needed in the command below. It has had
# a nasty tendency to get lost in the past. Use a variable to hold a space and
# a tab to keep the tab in one place.
exim_path=`perl -ne 'chop;if (/^\s*exim_path\s*=\s*(.*)/){print "$1\n";last;}' $config`
if test "$exim_path" = ""; then exim_path=/usr/sbin/exim4; fi
#########################################################################
# Now run the perl script, passing in the Exim path and the arguments given
# to the overall script.
/usr/bin/perl - $exim_path $args <<'End'
use FileHandle;
use IPC::Open2;
if (scalar(@ARGV) < 3)
{
print "Usage: exim_checkaccess <IP address> <email address> [exim options]\n";
exit(1);
}
$exim_path = $ARGV[0]; # Set up by the calling shell script
$host = $ARGV[1]; # Mandatory original first argument
$recipient = $ARGV[2]; # Mandatory original second argument
$c4 = qr/2 (?:[0-4]\d | 5[0-5]) | 1\d\d | \d{1,2}/x; # IPv4 component
$a4 = qr/^$c4\.$c4\.$c4\.$c4$/; # IPv4 address
$c6 = qr/[0-9a-f]{1,4}/i; # IPv6 component
# Split the various formats of IPv6 addresses into several cases. I don't
# think I can graft regex that matches all of them without using alternatives.
# 1. Starts with :: followed by up to 7 components
$a6_0 = qr/^::(?:$c6:){0,6}$c6$/x;
# 2. 8 non-empty components
$a6_1 = qr/^(?:$c6:){7}$c6$/x;
# 3. This is the cunning one. Up to 7 components, one (and only one) of which
# can be empty. We use 0 to cause a failure when we've already matched
# an empty component and may be hitting other. This has to fail, because we
# know we've just failed to match a component. We also do a final check to
# ensure that there has been an empty component.
$a6_2 = qr/^(?: (?: $c6 | (?(1)0 | () ) ) : ){1,7}$c6 $ (?(1)|.)/x;
if ($host !~ /$a4 | $a6_0 | $a6_1 | $a6_2/x)
{
print "** Invalid IP address \"$host\"\n";
print "Usage: exim_checkaccess <IP address> <email address> [exim options]\n";
exit(1);
}
# Build any remaining original arguments into a string for passing over
# as Exim options.
$opt = "";
for ($i = 3; $i < scalar(@ARGV); $i++) { $opt .= "$ARGV[$i] "; }
# If the string contains "-f xxxx", extract that as the sender. Otherwise
# the sender is <>.
$sender = "";
if ($opt =~ /(?:^|\s)-f\s+(\S+|"[^"]*")/)
{
$sender = $1;
$opt = $` . $';
}
# Run a -bh test in Exim, passing the test data
$pid = open2(*IN, *OUT, "$exim_path -bh $host $opt 2>/dev/null");
print OUT "HELO [$host]\r\n";
print OUT "MAIL FROM:<$sender>\r\n";
print OUT "RCPT TO:<$recipient>\r\n";
print OUT "QUIT\r\n";
close OUT;
# Read the output, ignoring anything but the SMTP response to the RCPT
# command.
$count = 0;
$reply = "";
while (<IN>)
{
next if !/^\d\d\d/;
$reply .= $_;
next if /^\d\d\d\-/;
if (++$count != 4)
{
$reply = "";
next;
}
# We have the response we want. Interpret it.
if ($reply =~ /^2\d\d/)
{
print "Accepted\n";
}
else
{
print "Rejected:\n";
$reply =~ s/\n(.)/\n $1/g;
print " $reply";
}
last;
}
# Reap the child process
waitpid $pid, 0;
End
|