-
Notifications
You must be signed in to change notification settings - Fork 0
/
chkspam
executable file
·389 lines (335 loc) · 10.4 KB
/
chkspam
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
#!/usr/local/bin/perl
# SMTP email verifier
# A.Daviel, Vancouver Webpages
sub disc {
print <<EOM ;
$0 SMTP email relay check
DISCLAIMER: This script is intended to test mail relaying capabilities.
Unauthorized use of this script on non-local hosts may be interpreted as
a network attack.
Each copy of this script is identified by a unique serial number and
may be traced back to the user.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 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. UNAUTHORIZED MODIFICATION OF THIS SOFTWARE IS FORBIDDEN
UNDER COPYRIGHT LAW.
EOM
}
$here = `hostname` ; chop($here) ;
($hname,$aliases,$addrtype,$length,@addrs) =gethostbyname($here) ;
$me = `whoami` ; chop($me) ;
$good_address = $me.'@'.$here ;
$bad_address = 'spammer@100.spammers.com' ;
$bad_org = '100.spammers.com' ;
$bad_user = 'baduser' ;
require 5.003;
use Socket;
$tout1 = 10 ; # timeout on initial connection
$tout = 60 ; # timeout on complete transaction
# typical errors from sendmail:
#220 connect
#250 command OK
#221 disconnect
#214 help
#252 not implemented
#500 command bad
#503 need mail
# internal errors:
#901 getprotobyname
#902 inet_aton
#903 socket fail
#904 connect fail
#905 timed out
#906 node not found
#907 loop test
if ($ARGV[0] =~ /^-/) { $opt = shift(@ARGV) ;}
$_= unpack("%16C*", $(.$<.$]) ; $|=1 ; # flush buffers
$debug = ($opt eq '-t') ;
print STDERR "$0 S/N $_ Email Relay Checker Copyright 1997 A.Daviel; please read disclaimer ($0 -D)\n\n";
if ($opt =~ /-h/) { &help ; exit ; }
if ($opt =~ /-D/) { &disc ; exit ; }
$prstat = ($opt eq '-s') ;
$quiet = ($opt eq '-q' || $prstat) ;
$node = $ARGV[0] ;
$one = $ARGV[0] ;
$bad_address = $_.$bad_address ;
if ($node) {
&checknode ($node) ;
exit ;
}
while (<STDIN>) {
chop ;
s/^\s+// ;
if (/^#/) { next ; }
s/\s.*// ;
&checknode ($_) ;
}
if (!$nname) { &help ; }
sub checknode {
local($node) = $_[0] ;
undef(@status) ; $timed_out=0 ; $sec=0 ;
($nname,$aliases,$addrtype,$length,@addrs) =gethostbyname($node) ;
if ($timed_out) { return ; }
#@f = unpack('C4',$addrs[0]);
unless ($nname) {
push(@status,"906") ;
&clean ; return ;
}
if (!$quiet) { print "Spam Test for $nname\n"; }
if (!$debug) { $SIG{'ALRM'} = "timed_out" ; alarm($tout1) ; }
$start = time ;
$proto = getprotobyname('tcp') ;
if ($timed_out) { return ; }
unless ($proto) {
print STDERR "ERROR: getprotobyname fail ($!)\n";
push(@status,"901") ;
&clean ; return ;
}
$port = 25;
$iaddr = inet_aton ($node) ;
if ($timed_out) { return ; }
unless ($iaddr) {
print STDERR "ERROR: inet_aton ($!)\n";
push(@status,"902") ;
&clean ; return ;
}
$sin = sockaddr_in ($port, $iaddr);
$stat = socket(S, PF_INET, SOCK_STREAM, $proto) ;
if ($timed_out) { return ; }
unless ($stat) {
print STDERR "ERROR: socket fail ($!): $proto\n" ;
push(@status,"903") ;
&clean ; return ;
}
$stat = connect(S, $sin) ;
if ($timed_out) { return ; }
unless ($stat) {
#print STDERR "ERROR: connect fail ($!)\n";
push(@status,"904") ;
&clean ; return ;
}
if (!$debug) { alarm($tout) ; }
recv S,$_,999,0 ;
if ($timed_out) { return ; }
$version = $_ ;
if (!$quiet) { print "$_\n"; }
&pstat ;
if (!$quiet) { print "Check HELO\n";}
send S, "MAIL From:<".$good_address.">\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_\n"; }
&pstat ;
&rset ;
if (!$quiet) { print "HELO $bad_org .. " ;}
send S, "HELO ".$bad_org."\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_"; }
&pstat ;
&rset ;
if (!$quiet) { print "HELO $here .. " ;}
send S, "HELO ".$here."\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_"; }
&pstat ;
if (!$quiet) { print "\nCheck VRFY and EXPN\n"; }
if (!$quiet) { print "VRFY <postmaster> .. " ;}
send S, "VRFY <postmaster>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_"; }
&pstat ;
if (!$quiet) { print "EXPN <postmaster> .. " ;}
send S, "EXPN <postmaster>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_"; }
&pstat ;
# try bogus FROM
if (!$quiet) { print "\nTest FROM spoofing\n";}
if (!$quiet) { print "From:<$bad_address> .. ";}
send S, "MAIL From:<".$bad_address.">\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
&rset ;
if (!$quiet) { print "From:<nosuchperson> .. " ; }
send S, "MAIL From:<nosuchperson>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
&rset ;
if (!$quiet) { print "From:<$good_address> .. " ;}
send S, "MAIL From:<".$good_address.">\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_\n";}
&pstat ;
if (!$quiet) { print "Test mail relay\n";}
if ($hname eq $nname && !$quiet) { print "$hname is local\n"; }
if (!$quiet) { print "To:<$bad_address> .. ";}
send S, "RCPT To:<".$bad_address.">\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "To:<$good_address> .. ";}
send S, "RCPT To:<".$good_address.">\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "To:<$good_address\@$node> .." ; }
send S, "RCPT To:<".$good_address."\@$node>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "To <$me%$here\@$node> .." ;}
send S, "RCPT To:<".$me."%".$here."\@$node>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "To <$here!$me\@$node> .." ;}
send S, "RCPT To:<".$here."!".$me."\@$node>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if ($hname eq $nname) { $status[9] = '907'; }
if (!$quiet) { print "\nInvalid user\n";}
if (!$quiet) { print "To <no.such.user\@$node> .." ;}
send S, "RCPT To:<no.such.user\@$node>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "\nValid user\n";}
if (!$quiet) { print "To <postmaster\@$node> .." ;}
send S, "RCPT To:<postmaster\@$node>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "To <webmaster\@$node> .." ;}
send S, "RCPT To:<webmaster\@$node>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "To <abuse\@$node> .." ;}
send S, "RCPT To:<abuse\@$node>\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_";}
&pstat ;
if (!$quiet) { print "\nQuit.\n";}
send S, "QUIT\r\n",0 ;
recv S,$_,999,0 ;
if ($timed_out) { return ; }
if (!$quiet) { print "$_\n";}
&clean ;
} # end checknode
sub timed_out {
#print STDERR "Port 25 timed out to $node\n";
push(@status,"905") ;
$timed_out=1 ; &clean ;
}
sub clean {
$sec = time - $start ;
if ($prstat) {
print "$node ";
foreach $_ (@status) {
print "$_ ";
}
print "\n";
}
if (!$prstat) {
if ($status[0] eq '904') { print "$nname rejects SMTP mail\n";
} elsif ($status[0] eq '905') { print "$nname could not be reached\n";
} elsif ($status[0] eq '906') { print "$node not found\n";
} elsif ($status[0] =~ /^9/) { print "Internal error\n" ;
} else {
if ($version) { print "$nname $version" ; }
print "$nname requires HELO: " ; &npyn(1) ;
print "$nname allows VRFY username verification: "; &pyn(4) ;
print "$nname allows EXPN forwarding expansion: "; &pyn(5) ;
print "$nname allows bogus From: header: "; &pyn(6) ;
if ($status[9] eq '907') {
print "$nname is local\n";
} else {
print "$nname allows mail relaying: ";
if (($status[9] =~ /^2/) ||
($status[10] =~ /^2/) ||
($status[11] =~ /^2/) ||
($status[12] =~ /^2/) ||
($status[13] =~ /^2/)) {
print "YES\n";
} else { print "NO\n"; }
}
print "$nname can mail to postmaster: "; &pyn(15) ;
print "$nname can mail to webmaster: "; &pyn(16) ;
print "$nname can mail to abuse: "; &pyn(17) ;
foreach $_ (@status) {
if ($_ eq '905') { print "$nname timed out\n"; }
}
}
if ($sec>0) { print "$nname - $sec seconds\n"; }
}
alarm(0);
}
sub rset {
if (!$quiet) { print "Reset.. ";}
send S, "RSET\r\n",0 ;
recv S,$_,999,0 ;
if (!$quiet) { print "$_" ;}
}
sub pstat {
tr/\n/ /; chop ; s/\D.*// ; push(@status,$_) ;
}
sub npyn {
if ($status[$_[0]] =~ /^250/) { print "NO\n"; } else { print "YES\n"; }
}
sub pyn {
if (!($status[$_[0]] =~ /^250/)) { print "NO\n"; } else { print "YES\n"; }
}
sub help {
print <<EOM ;
SMTP Email Relay Checker
Usage: $0 [-q|-s|-D|-t] <ip address>
This program attempts to relay email messages through sendmail.
No actual messages are sent; only recipients are tested.
Please read the disclaimer ($0 -D)
If -s is specified, the test runs quietly and only generates a status line.
If -q is specified, the test runs quietly and only generates a summary.
If -t is specified, timeouts are disabled.
If <ip address> is not present, will read a list of addresses from STDIN
such as that produced by "host -l <domain>".
The summary is designed to be fed to "grep", "sort", etc.
The status line is designed to be fed to e.g. another Perl script for statistics gathering.
The status elements (with -s) are from the following commands, sequentially:
connect, mail no helo, helo badorg, helo goodaddr, vrfy postmaster,
expn postmaster, from badaddr, from nosuchperson, from goodaddr,
to badaddr, to goodaddr, to good\@org\@node, to good%org\@node,
to org!good\@node, to nosuchuser, to postmaster, to webmaster,
to abuse
status values are from sendmail, except 900 series which indicate a local error.
904 is connect fail (SMTP mail not supported)
905 is timed out (tcp connect failed)
906 is not found (DNS lookup failure)
907 means you are testing this machine, so relay tests are pointless
EOM
}