View | Details | Raw Unified | Return to bug 157107 | Differences between
and this patch

Collapse All | Expand All

(-)p5-Mail-SPF/Makefile (-2 / +22 lines)
Lines 12-17 Link Here
12
OPTIONS=	SPFQUERY "Install spfquery command-line tool" on \
13
		SPFQUERY_SUFFIX "Add .pl suffix to spfquery" off
14
Lines 20-31 Link Here
20
CONFLICTS=	libspf2-[0-9]* p5-Mail-SPF-Query-[0-9]*
23
CONFLICTS=	p5-Mail-SPF-Query-[0-9]*
21
MAN1=		spfquery.1
Lines 42-47 Link Here
44
.if defined(WITH_SPFQUERY)
45
PLIST_SUB+= SPFQUERY=""
46
47
.if defined(WITH_SPFQUERY_SUFFIX)
48
PLIST_SUB+= SPFQUERY_SUFFIX=".pl"
49
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-spfquery-suffix
50
MAN1+=		spfquery.pl.1
51
.else
52
PLIST_SUB+= SPFQUERY_SUFFIX=""
53
MAN1+=		spfquery.1
54
CONFLICTS+=	libspf2*
55
.endif
56
57
.else
58
PLIST_SUB+= SPFQUERY="@comment "
59
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-no-spfquery
60
.endif
61
(-)p5-Mail-SPF/files/extra-patch-no-spfquery (+33 lines)
Line 0 Link Here
1
diff -Naur orig/Build.PL Build.PL
2
--- orig/Build.PL	2009-10-31 23:16:14.000000000 +0100
3
+++ Build.PL	2011-05-24 19:27:19.000000000 +0200
4
@@ -66,7 +66,6 @@
5
                         => 'v0.002.1',
6
     },
7
     script_files    => [
8
-        'bin/spfquery'
9
     ],
10
     install_path    => {
11
         'sbin'          => '/usr/sbin'
12
diff -Naur orig/MANIFEST MANIFEST
13
--- orig/MANIFEST	2009-10-31 23:16:14.000000000 +0100
14
+++ MANIFEST	2011-05-24 19:26:56.000000000 +0200
15
@@ -1,4 +1,3 @@
16
-bin/spfquery
17
 Build.PL
18
 CHANGES
19
 debian/changelog
20
diff -Naur orig/README README
21
--- orig/README	2009-10-31 23:16:14.000000000 +0100
22
+++ README	2011-05-24 19:27:05.000000000 +0200
23
@@ -12,9 +12,8 @@
24
 This release of Mail::SPF fully conforms to RFC 4408 and passes the 2008.08
25
 release of the official test-suite <http://www.openspf.org/Test_Suite>.
26
 
27
-The Mail::SPF source package includes the following additional tools:
28
+The Mail::SPF source package includes the following additional tool:
29
 
30
-  * spfquery:  A command-line tool for performing SPF checks.
31
   * spfd:      A daemon for services that perform SPF checks frequently.
32
 
33
 Mail::SPF is not your mother!
(-)p5-Mail-SPF/files/extra-patch-spfquery-suffix (+1505 lines)
Line 0 Link Here
1
diff -Naur orig/Build.PL Build.PL
2
--- orig/Build.PL	2009-10-31 23:16:14.000000000 +0100
3
+++ Build.PL	2011-05-24 19:40:10.000000000 +0200
4
@@ -66,7 +66,7 @@
5
                         => 'v0.002.1',
6
     },
7
     script_files    => [
8
-        'bin/spfquery'
9
+        'bin/spfquery.pl'
10
     ],
11
     install_path    => {
12
         'sbin'          => '/usr/sbin'
13
diff -Naur orig/MANIFEST MANIFEST
14
--- orig/MANIFEST	2009-10-31 23:16:14.000000000 +0100
15
+++ MANIFEST	2011-05-24 19:40:36.000000000 +0200
16
@@ -1,4 +1,4 @@
17
-bin/spfquery
18
+bin/spfquery.pl
19
 Build.PL
20
 CHANGES
21
 debian/changelog
22
diff -Naur orig/README README
23
--- orig/README	2009-10-31 23:16:14.000000000 +0100
24
+++ README	2011-05-24 19:40:54.000000000 +0200
25
@@ -14,8 +14,8 @@
26
 
27
 The Mail::SPF source package includes the following additional tools:
28
 
29
-  * spfquery:  A command-line tool for performing SPF checks.
30
-  * spfd:      A daemon for services that perform SPF checks frequently.
31
+  * spfquery.pl: A command-line tool for performing SPF checks.
32
+  * spfd:        A daemon for services that perform SPF checks frequently.
33
 
34
 Mail::SPF is not your mother!
35
 -----------------------------
36
diff -Naur orig/bin/spfquery bin/spfquery
37
--- orig/bin/spfquery	2009-10-31 23:16:14.000000000 +0100
38
+++ bin/spfquery	1970-01-01 01:00:00.000000000 +0100
39
@@ -1,731 +0,0 @@
40
-#!/usr/bin/perl
41
-
42
-# 
43
-# spfquery: Command-line tool for performing SPF queries
44
-#
45
-# (C) 2005-2008 Julian Mehnle <julian@mehnle.net>
46
-#     2004      Wayne Schlitt <wayne@schlitt.net>
47
-# $Id: spfquery 138 2006-01-22 18:00:34Z julian $
48
-#
49
-##############################################################################
50
-
51
-=head1 NAME
52
-
53
-spfquery - (Mail::SPF) - Checks if a given set of e-mail parameters matches a
54
-domain's SPF policy
55
-
56
-=head1 VERSION
57
-
58
-2.501
59
-
60
-=head1 SYNOPSIS
61
-
62
-=over
63
-
64
-=item B<Preferred usage:>
65
-
66
-B<spfquery> [B<--versions>|B<-v> B<1>|B<2>|B<1,2>] [B<--scope>|B<-s> B<helo>|B<mfrom>|B<pra>]
67
-B<--identity>|B<--id> I<identity> B<--ip-address>|B<--ip> I<ip-address>
68
-[B<--helo-identity>|B<--helo-id> I<helo-identity>] [I<OPTIONS>]
69
-
70
-B<spfquery> [B<--versions>|B<-v> B<1>|B<2>|B<1,2>] [B<--scope>|B<-s> B<helo>|B<mfrom>|B<pra>]
71
-B<--file>|B<-f> I<filename>|B<-> [I<OPTIONS>]
72
-
73
-=item B<Legacy usage:>
74
-
75
-B<spfquery> B<--helo> I<helo-identity> B<--ip-address>|B<--ip> I<ip-address> [I<OPTIONS>]
76
-
77
-B<spfquery> B<--mfrom> I<mfrom-identity> B<--ip-address>|B<--ip> I<ip-address>
78
-[B<--helo> I<helo-identity>] [I<OPTIONS>]
79
-
80
-B<spfquery> B<--pra> I<pra-identity> B<--ip-address>|B<--ip> I<ip-address> [I<OPTIONS>]
81
-
82
-=item B<Other usage:>
83
-
84
-B<spfquery> B<--version>|B<-V>
85
-
86
-B<spfquery> B<--help>
87
-
88
-=back
89
-
90
-=head1 DESCRIPTION
91
-
92
-B<spfquery> checks if a given set of e-mail parameters (e.g., the SMTP sender's
93
-IP address) matches the responsible domain's Sender Policy Framework (SPF)
94
-policy.  For more information on SPF see L<http://www.openspf.org>.
95
-
96
-=head2 Preferred Usage
97
-
98
-The following usage forms are preferred over the L<legacy forms|/Legacy usage>
99
-used by older B<spfquery> versions:
100
-
101
-The B<--identity> form checks if the given I<ip-address> is an authorized SMTP
102
-sender for the given C<helo> hostname, C<mfrom> envelope sender e-mail address,
103
-or C<pra> (so-called purported resonsible address) e-mail address, depending
104
-on the value of the B<--scope> option (which defaults to B<mfrom> if omitted).
105
-
106
-The B<--file> form reads "I<ip-address> I<identity> [I<helo-identity>]" tuples
107
-from the file with the specified I<filename>, or from standard input if
108
-I<filename> is B<->, and checks them against the specified scope (B<mfrom> by
109
-default).
110
-
111
-Both forms support an optional B<--versions> option, which specifies a
112
-comma-separated list of the SPF version numbers of SPF records that may be
113
-used.  B<1> means that C<v=spf1> records should be used.  B<2> means that
114
-C<spf2.0> records should be used.  Defaults to B<1,2>, i.e., uses any SPF
115
-records that are available.  Records of a higher version are preferred.
116
-
117
-=head2 Legacy Usage
118
-
119
-B<spfquery> versions before 2.500 featured the following usage forms, which are
120
-discouraged but still supported for L<backwards compatibility|/COMPATIBILITY>:
121
-
122
-The B<--helo> form checks if the given I<ip-address> is an authorized SMTP
123
-sender for the C<HELO> hostname given as the I<identity> (so-called C<HELO>
124
-check).
125
-
126
-The B<--mfrom> form checks if the given I<ip-address> is an authorized SMTP
127
-sender for the envelope sender email-address (or domain) given as the
128
-I<identity> (so-called C<MAIL FROM> check).  If a domain is given instead of an
129
-e-mail address, C<postmaster> will be substituted for the localpart.
130
-
131
-The B<--pra> form checks if the given I<ip-address> is an authorized SMTP
132
-sender for the PRA (Purported Responsible Address) e-mail address given as the
133
-identity.
134
-
135
-=head2 Other Usage
136
-
137
-The B<--version> form prints version information of spfquery.  The B<--help>
138
-form prints usage information for spfquery.
139
-
140
-=head1 OPTIONS
141
-
142
-=head2 Standard Options
143
-
144
-The preferred and legacy forms optionally take any of the following
145
-I<OPTIONS>:
146
-
147
-=over
148
-
149
-=item B<--default-explanation> I<string>
150
-
151
-=item B<--def-exp> I<string>
152
-
153
-Use the specified I<string> as the default explanation if the authority domain
154
-does not specify an explanation string of its own.
155
-
156
-=item B<--hostname> I<hostname>
157
-
158
-Use I<hostname> as the host name of the local system instead of auto-detecting
159
-it.
160
-
161
-=item B<--keep-comments>
162
-
163
-=item B<--no-keep-comments>
164
-
165
-Do (not) print any comments found when reading from a file or from standard
166
-input.
167
-
168
-=item B<--sanitize> (currently ignored)
169
-
170
-=item B<--no-sanitize> (currently ignored)
171
-
172
-Do (not) sanitize the output by condensing consecutive white-space into a
173
-single space and replacing non-printable characters with question marks.
174
-Enabled by default.
175
-
176
-=item B<--debug> (currently ignored)
177
-
178
-Print out debug information.
179
-
180
-=back
181
-
182
-=head2 Black Magic Options
183
-
184
-Several options that were supported by earlier versions of B<spfquery> are
185
-considered black magic (i.e. potentially dangerous for the innocent user) and
186
-are thus disabled by default.  If the L<B<Mail::SPF::BlackMagic>> Perl module
187
-is installed, they may be enabled by specifying B<--enable-black-magic>.
188
-
189
-=over
190
-
191
-=item B<--max-dns-interactive-terms> I<n>
192
-
193
-Evaluate a maximum of I<n> DNS-interactive mechanisms and modifiers per SPF
194
-check.  Defaults to B<10>.  Do I<not> override the default unless you know what
195
-you are doing!
196
-
197
-=item B<--max-name-lookups-per-term> I<n>
198
-
199
-Perform a maximum of I<n> DNS name look-ups per mechanism or modifier.
200
-Defaults to B<10>.  Do I<not> override the default unless you know what you are
201
-doing!
202
-
203
-=item B<--authorize-mxes-for> I<email-address>|I<domain>B<,>...
204
-
205
-Consider all the MXes of the comma-separated list of I<email-address>es and
206
-I<domain>s as inherently authorized.
207
-
208
-=item B<--tfwl>
209
-
210
-Perform C<trusted-forwarder.org> accreditation checking.
211
-
212
-=item B<--guess> I<spf-terms>
213
-
214
-Use I<spf-terms> as a default record if no SPF record is found.
215
-
216
-=item B<--local> I<spf-terms>
217
-
218
-Process I<spf-terms> as local policy before resorting to a default result
219
-(the implicit or explicit C<all> mechanism at the end of the domain's SPF
220
-record).  For example, this could be used for white-listing one's secondary
221
-MXes: C<mx:mydomain.example.org>.
222
-
223
-=item B<--override> I<domain>B<=>I<spf-record>
224
-
225
-=item B<--fallback> I<domain>B<=>I<spf-record>
226
-
227
-Set overrides and fallbacks.  Each option can be specified multiple times.  For
228
-example:
229
-
230
-    --override example.org='v=spf1 -all'
231
-    --override '*.example.net'='v=spf1 a mx -all'
232
-    --fallback example.com='v=spf1 -all'
233
-
234
-=back
235
-
236
-=head1 RESULT CODES
237
-
238
-=over 12
239
-
240
-=item B<pass>
241
-
242
-The specified IP address is an authorized SMTP sender for the identity.
243
-
244
-=item B<fail>
245
-
246
-The specified IP address is not an authorized SMTP sender for the identity.
247
-
248
-=item B<softfail>
249
-
250
-The specified IP address is not an authorized SMTP sender for the identity,
251
-however the authority domain is still testing out its SPF policy.
252
-
253
-=item B<neutral>
254
-
255
-The identity's authority domain makes no assertion about the status of the IP
256
-address.
257
-
258
-=item B<permerror>
259
-
260
-A permanent error occurred while evaluating the authority domain's policy
261
-(e.g., a syntax error in the SPF record).  Manual intervention is required
262
-from the authority domain.
263
-
264
-=item B<temperror>
265
-
266
-A temporary error occurred while evaluating the authority domain's policy
267
-(e.g., a DNS error).  Try again later.
268
-
269
-=item B<none>
270
-
271
-There is no applicable SPF policy for the identity domain.
272
-
273
-=back
274
-
275
-=head1 EXIT CODES
276
-
277
-  Result    | Exit code
278
- -----------+-----------
279
-  pass      |     0
280
-  fail      |     1
281
-  softfail  |     2
282
-  neutral   |     3
283
-  permerror |     4
284
-  temperror |     5
285
-  none      |     6
286
-
287
-=head1 EXAMPLES
288
-
289
-    spfquery --scope mfrom --id user@example.com --ip 1.2.3.4
290
-    spfquery --file test_data
291
-    echo "127.0.0.1 user@example.com helohost.example.com" | spfquery -f -
292
-
293
-=head1 COMPATIBILITY
294
-
295
-B<spfquery> has undergone the following interface changes compared to earlier
296
-versions:
297
-
298
-=over
299
-
300
-=item B<2.500>
301
-
302
-=over
303
-
304
-=item *
305
-
306
-A new preferred usage style for performing individual SPF checks has been
307
-introduced.  The new style accepts a unified B<--identity> option and an
308
-optional B<--scope> option that specifies the type (scope) of the identity.  In
309
-contrast, the legacy usage style requires a separate usage form for every
310
-supported scope.  See L</Preferred usage> and L</Legacy usage> for details.
311
-
312
-=item *
313
-
314
-The former C<unknown> and C<error> result codes have been renamed to C<permerror>
315
-and C<temperror>, respectively, in order to comply with RFC 4408 terminology.
316
-
317
-=item *
318
-
319
-SPF checks with an empty identity are no longer supported.  In the case of an
320
-empty C<MAIL FROM> SMTP transaction parameter, perform a check with the C<helo>
321
-scope directly.
322
-
323
-=item *
324
-
325
-The B<--debug> and B<--(no-)sanitize> options are currently ignored by this
326
-version of B<spfquery>.  They will again be supported in the future.
327
-
328
-=item *
329
-
330
-Several features that were supported by earlier versions of B<spfquery> are
331
-considered black magic and thus are now disabled by default.  See L</Black
332
-Magic Options>.
333
-
334
-=item *
335
-
336
-Several option names have been deprecated.  This is a list of them and their
337
-preferred synonyms:
338
-
339
-  Deprecated options  | Preferred options
340
- ---------------------+-----------------------------
341
-  --sender, -s        | --mfrom
342
-  --ipv4, -i          | --ip-address, --ip
343
-  --name              | --hostname
344
-  --max-lookup-count, | --max-dns-interactive-terms
345
-    --max-lookup      |
346
-  --rcpt-to, -r       | --authorize-mxes-for
347
-  --trusted           | --tfwl
348
-
349
-=back
350
-
351
-=back
352
-
353
-=head1 SEE ALSO
354
-
355
-L<Mail::SPF>, L<spfd(8)>
356
-
357
-L<http://www.ietf.org/rfc/rfc4408.txt>
358
-
359
-=head1 AUTHORS
360
-
361
-This version of B<spfquery> is a complete rewrite by Julian Mehnle
362
-<julian@mehnle.net>, based on an earlier version written by Meng Weng Wong
363
-<mengwong+spf@pobox.com> and Wayne Schlitt <wayne@schlitt.net>.
364
-
365
-=cut
366
-
367
-our $VERSION = '2.501';
368
-
369
-use warnings;
370
-use strict;
371
-
372
-use IO::File;
373
-use Getopt::Long qw(:config gnu_compat no_ignore_case);
374
-use Error ':try';
375
-use Mail::SPF;
376
-
377
-use constant TRUE   => (0 == 0);
378
-use constant FALSE  => not TRUE;
379
-
380
-use constant exit_codes_by_result_code => {
381
-    pass        => 0,
382
-    fail        => 1,
383
-    softfail    => 2,
384
-    neutral     => 3,
385
-    permerror   => 4,
386
-    temperror   => 5,
387
-    none        => 6
388
-};
389
-
390
-# Helper Functions
391
-##############################################################################
392
-
393
-sub usage {
394
-    STDERR->printf(<<'EOT');
395
-Preferred Usage:
396
-    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
397
-        --identity|--id <identity> --ip-address|--ip <ip-address>
398
-        [--helo-identity|--helo-id <helo-identity>] [OPTIONS]
399
-    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
400
-        --file|-f <filename>|- [OPTIONS]
401
-
402
-Legacy Usage:
403
-    spfquery --helo <helo-identity> --ip-address|--ip <ip-address> [OPTIONS]
404
-    spfquery --mfrom <mfrom-identity> --ip-address|--ip <ip-address>
405
-        [--helo <helo-identity>] [OPTIONS]
406
-    spfquery --pra <pra-identity> --ip-address|--ip <ip-address> [OPTIONS]
407
-
408
-Other Usage:
409
-    spfquery --version|-V
410
-
411
-See `spfquery --help` for more information.
412
-EOT
413
-    return;
414
-}
415
-
416
-sub help {
417
-    print(<<'EOT');
418
-Preferred Usage:
419
-    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
420
-        --identity|--id <identity> --ip-address|--ip <ip-address>
421
-        [--helo-identity|--helo-id <helo-identity>] [OPTIONS]
422
-    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
423
-        --file|-f <filename>|- [OPTIONS]
424
-
425
-Legacy Usage:
426
-    spfquery --helo <helo-identity> --ip-address|--ip <ip-address> [OPTIONS]
427
-    spfquery --mfrom <mfrom-identity> --ip-address|--ip <ip-address>
428
-        [--helo <helo-identity>] [OPTIONS]
429
-    spfquery --pra <pra-identity> --ip-address|--ip <ip-address> [OPTIONS]
430
-
431
-Other Usage:
432
-    spfquery --version|-V
433
-
434
-spfquery performs SPF checks based on the command-line arguments or data given
435
-in a file or on standard input.
436
-
437
-Only the preferred and other usage forms are explained here.  See the
438
-spfquery(1) man-page for an explanation of the legacy usage forms.
439
-
440
-The "--identity" form checks if the given <ip-address> is an authorized SMTP
441
-sender for the given "helo" hostname, "mfrom" envelope sender e-mail address,
442
-or "pra" (purported resonsible address) e-mail address, depending on the value
443
-of the "--scope" option (which defaults to "mfrom" if omitted).
444
-
445
-The "--file" form reads "<ip-address> <identity> [<helo-identity>]" tuples from
446
-the file with the specified <filename>, or from standard input if <filename> is
447
-"-", and checks them against the specified scope ("mfrom" by default).
448
-
449
-The "--version" form prints version information of spfquery.
450
-
451
-Valid OPTIONS (and their defaults) are:
452
-    --default-explanation <string>
453
-                        Default explanation string to use (sensible default).
454
-    --hostname <hostname>
455
-                        The name of the system doing the SPF checking (local
456
-                        system's configured hostname).
457
-    --keep-comments     Print comments found when reading from a file.
458
-    --no-sanitize       Do not clean up invalid characters in output.
459
-    --debug             Output debugging information.
460
-
461
-Black-magic OPTIONS are:
462
-    --max-dns-interactive-terms <n>
463
-                        Maximum number of DNS-interactive mechanisms and
464
-                        modifiers (10).
465
-    --max-name-lookups-per-term <n>
466
-                        Maximum number of DNS name look-ups per mechanism or
467
-                        modifier (10).
468
-    --authorize-mxes-for <email-address>|<domain>,...
469
-                        A comma-separated list of e-mail addresses and domains
470
-                        whose MXes will be considered inherently authorized.
471
-    --tfwl              Check trusted-forwarder.org white-list.
472
-    --guess <spf-terms> Default checks if no SPF record is found.
473
-    --local <spf-terms> Local policy to process before default result.
474
-    --override <domain>=<spf-record>
475
-    --fallback <domain>=<spf-record>
476
-                        Set override and fallback SPF records for domains.
477
-
478
-Examples:
479
-    spfquery --scope mfrom --id user@example.com --ip 1.2.3.4
480
-    spfquery --file test_data
481
-    echo "127.0.0.1 user@example.com helohost.example.com" | spfquery -f -
482
-EOT
483
-    return;
484
-}
485
-
486
-sub deprecated_option {
487
-    my ($old_option, $new_option, $options) = @_;
488
-    return FALSE if not exists($options->{$old_option});
489
-    STDERR->print(
490
-        "Warning: '$old_option' option is deprecated" .
491
-        ($new_option ? "; use '$new_option' instead" : '') .
492
-        ".\n"
493
-    );
494
-    $options->{$new_option} = delete($options->{$old_option});
495
-    return TRUE;
496
-}
497
-
498
-sub unsupported_option {
499
-    my ($option_name, $options) = @_;
500
-    return FALSE if not exists($options->{$option_name});
501
-    STDERR->print("Error: '$option_name' option is no longer supported.\n");
502
-    return TRUE;
503
-}
504
-
505
-sub black_magic_option {
506
-    my ($option_name, $options) = @_;
507
-    return FALSE if not exists($options->{$option_name});
508
-    STDERR->print("Error: '$option_name' option is black magic! Do not use it!\n");
509
-    return TRUE;
510
-}
511
-
512
-# Command-line Option Handling
513
-##############################################################################
514
-
515
-my $options = {};
516
-my $getopt_result = GetOptions(
517
-    $options,
518
-    
519
-    'file|f=s',
520
-    
521
-    'versions|v=s',
522
-    'scope=s',
523
-    's=s',  # Special handling for ambiguous 's' option (formerly a synonym
524
-            # for 'sender', now preferredly a synonym for 'scope').
525
-    'identity|id=s',
526
-    'ip-address|ip=s',
527
-    'helo-identity|helo-id=s',
528
-    
529
-    # Legacy/shortcut options:
530
-    'mfrom|mail-from|m=s',
531
-    'helo|h=s',
532
-    
533
-    'default-explanation|def-exp=s',
534
-    'hostname=s',
535
-    
536
-    'keep-comments!',
537
-    'debug!',       # TODO Implement!
538
-    'sanitize!',    # TODO Implement!
539
-    
540
-    # Black Magic options:
541
-    'enable-black-magic!',
542
-    'max-dns-interactive-terms=i',
543
-    'max-name-lookups-per-term=i',
544
-    'authorize-mxes-for=s',
545
-                    # TODO implement!
546
-    'tfwl!',        # TODO Implement!
547
-    'guess=s',      # TODO Implement!
548
-    'local=s',      # TODO Implement!
549
-    'override=s%',  # TODO Implement!
550
-    'fallback=s%',  # TODO Implement!
551
-    
552
-    # Meta actions:
553
-    'version|V!',
554
-    'help!',
555
-    
556
-    # Deprecated options:
557
-    'sender=s',     # Now 'scope'/'identity' or 'mfrom'
558
-    'ipv4=s',       # Now 'ip-address'
559
-    'i=s',          # Now 'ip-address'
560
-    'name=s',       # Now 'hostname'
561
-    'max-lookup-count=i',
562
-    'max-lookup=i', # Now 'max-dns-interactive-terms'
563
-    'rcpt-to=s',    # Now 'authorize-mxes-for'
564
-    'r=s',          # Now 'authorize-mxes-for'
565
-    'trusted!'      # Now 'tfwl'
566
-);
567
-
568
-if (not $getopt_result) {
569
-    usage();
570
-    exit(255);
571
-}
572
-
573
-if ($options->{help}) {
574
-    help();
575
-    exit(0);
576
-}
577
-
578
-if ($options->{version}) {
579
-    print("spfquery version $VERSION (using Mail::SPF)\n");
580
-    exit(0);
581
-}
582
-
583
-deprecated_option('sender',           'mfrom',                     $options);
584
-deprecated_option('ipv4',             'ip-address',                $options);
585
-deprecated_option('i',                'ip-address',                $options);
586
-deprecated_option('name',             'hostname',                  $options);
587
-deprecated_option('max-lookup-count', 'max-dns-interactive-terms', $options);
588
-deprecated_option('max-lookup',       'max-dns-interactive-terms', $options);
589
-deprecated_option('rcpt-to',          'authorize-mxes-for',        $options);
590
-deprecated_option('r',                'authorize-mxes-for',        $options);
591
-deprecated_option('trusted',          'tfwl',                      $options);
592
-
593
-if ($options->{'enable-black-magic'}) {
594
-    if (not defined(eval('require Mail::SPF::BlackMagic'))) {
595
-        STDERR->print("Error: Cannot enable black magic. Unable to load Mail::SPF::BlackMagic.\n");
596
-        exit(255);
597
-    }
598
-    # else: Black magic enabled!
599
-}
600
-elsif (
601
-    black_magic_option('max-dns-interactive-terms', $options) or
602
-    black_magic_option('max-name-lookups-per-term', $options) or
603
-    black_magic_option('rcpt-to',                   $options) or
604
-    black_magic_option('trusted',                   $options) or
605
-    black_magic_option('guess',                     $options) or
606
-    black_magic_option('local',                     $options) or
607
-    black_magic_option('override',                  $options) or
608
-    black_magic_option('fallback',                  $options)
609
-) {
610
-    exit(255);
611
-}
612
-
613
-my @versions            = split(',', $options->{versions} || '');
614
-my $scope               = $options->{scope};
615
-my $identity            = $options->{identity};
616
-my $ip_address          = $options->{'ip-address'};
617
-my $helo_identity       = $options->{'helo-identity'};
618
-
619
-# Heuristic for distinguishing between 's(cope)' and 's(ender)':
620
-if (defined(my $s = $options->{s})) {
621
-    if (
622
-        not defined($scope) and  # No explicit 'scope' option has been specified, and
623
-        $s !~ /[@.]/             # 's' option contains neither an '@' nor a dot,
624
-                                 # so it cannot be an e-mail address or a domain.
625
-    ) {
626
-        # Thus it must be meant as the 'scope' option:
627
-        $scope = $s;
628
-    }
629
-    else {
630
-        # Else, it must be meant as the deprecated 'sender' option:
631
-        $options->{mfrom} = $s;
632
-    }
633
-}
634
-
635
-# Heuristic for when explicit 'scope'/'s(cope)' option is absent:
636
-if (not defined($scope)) {
637
-    if (defined($identity) or defined($options->{file})) {
638
-        # Identity has been specified, or input will be read from file:
639
-        # apply the 'scope' option default:
640
-        $scope    = 'mfrom';
641
-    }
642
-    elsif (defined($options->{helo})) {
643
-        $scope    = 'helo';
644
-        $identity = $options->{helo};
645
-    }
646
-    elsif (defined($options->{mfrom})) {
647
-        $scope    = 'mfrom';
648
-        $identity = $options->{mfrom};
649
-        $helo_identity ||= $options->{helo};
650
-    }
651
-    elsif (defined($options->{pra})) {
652
-        $scope    = 'pra';
653
-        $identity = $options->{pra};
654
-    }
655
-}
656
-
657
-my $default_explanation = $options->{'default-explanation'};
658
-my $hostname            = $options->{hostname};
659
-
660
-if (
661
-    not defined($scope) or
662
-    not (defined($identity) xor defined($options->{file}))
663
-) {
664
-    usage();
665
-    exit(255);
666
-}
667
-
668
-if (defined($identity) and $identity eq '') {
669
-    STDERR->print("Error: Empty identities are not supported. See spfquery(1).\n");
670
-    exit(255);
671
-}
672
-
673
-# Process the SPF Request(s)
674
-##############################################################################
675
-
676
-try {
677
-    my $spf_server = Mail::SPF::Server->new(
678
-        default_authority_explanation
679
-                        => $default_explanation,
680
-        hostname        => $hostname,
681
-    #    debug           => $options->{debug},
682
-    #    sanitize        => $options->{sanitize},
683
-
684
-        # Black Magic:
685
-        (
686
-            exists($options->{'max-dns-interactive-terms'}) ?
687
-                (max_dns_interactive_terms  => $options->{'max-dns-interactive-terms'} || undef)
688
-            :   ()
689
-        ),
690
-        (
691
-            exists($options->{'max-name-lookups-per-term'}) ?
692
-                (max_name_lookups_per_term  => $options->{'max-name-lookups-per-term'} || undef)
693
-            :   ()
694
-        )
695
-    #    rcpt_to         => $options->{'rcpt-to'},
696
-    #    trusted         => $options->{trusted},
697
-    #    guess           => $options->{guess},
698
-    #    local           => $options->{local},
699
-    #    override        => $options->{override},
700
-    #    fallback        => $options->{fallback},
701
-    );
702
-
703
-    my $exit_code;
704
-
705
-    if (not defined($options->{file})) {
706
-        # Single request:
707
-        my $result_code = do_process(
708
-            $spf_server,
709
-            versions        => @versions ? [@versions] : undef,
710
-            scope           => $scope,
711
-            identity        => $identity,
712
-            ip_address      => $ip_address,
713
-            helo_identity   => $helo_identity
714
-        );
715
-        $exit_code = exit_codes_by_result_code->{$result_code};
716
-    }
717
-    else {
718
-        # File request:
719
-        my $file = $options->{file} eq '-' ? \*STDIN : IO::File->new($options->{file})
720
-            or die("Could not open: $options->{file}\n");
721
-        while (<$file>) {
722
-            chomp;
723
-            s/^\s*//;
724
-            next if /^$/;
725
-            if (/^#/) {
726
-                print("$_\n") if $options->{'keep-comments'};
727
-                next;
728
-            }
729
-            ($ip_address, $identity, $helo_identity) = split;
730
-            my $result_code = do_process(
731
-                $spf_server,
732
-                versions        => @versions ? [@versions] : undef,
733
-                scope           => $scope,
734
-                identity        => $identity,
735
-                ip_address      => $ip_address,
736
-                helo_identity   => $helo_identity
737
-            );
738
-            $exit_code ||= exit_codes_by_result_code->{$result_code};
739
-        }
740
-    }
741
-
742
-    exit($exit_code);
743
-}
744
-catch Mail::SPF::Exception with {
745
-    my ($e) = @_;
746
-    STDERR->printf("Error: %s.\n", $e->text);
747
-    exit(255);
748
-};
749
-
750
-
751
-# Helper Function
752
-##############################################################################
753
-
754
-sub do_process {
755
-    my ($spf_server, %request_options) = @_;
756
-    my $request = Mail::SPF::Request->new(%request_options);
757
-    my $result  = $spf_server->process($request);
758
-    printf(
759
-        "%s\n%s\n%s\n%s\n",
760
-        $result->code,
761
-        (
762
-            $result->can('authority_explanation') ?
763
-                $result->authority_explanation
764
-            :   $result->local_explanation
765
-        ),
766
-        $result->local_explanation,
767
-        $result->received_spf_header
768
-    );
769
-    return $result->code;
770
-}
771
diff -Naur orig/bin/spfquery.pl bin/spfquery.pl
772
--- orig/bin/spfquery.pl	1970-01-01 01:00:00.000000000 +0100
773
+++ bin/spfquery.pl	2009-10-31 23:16:14.000000000 +0100
774
@@ -0,0 +1,731 @@
775
+#!/usr/bin/perl
776
+
777
+# 
778
+# spfquery: Command-line tool for performing SPF queries
779
+#
780
+# (C) 2005-2008 Julian Mehnle <julian@mehnle.net>
781
+#     2004      Wayne Schlitt <wayne@schlitt.net>
782
+# $Id: spfquery 138 2006-01-22 18:00:34Z julian $
783
+#
784
+##############################################################################
785
+
786
+=head1 NAME
787
+
788
+spfquery - (Mail::SPF) - Checks if a given set of e-mail parameters matches a
789
+domain's SPF policy
790
+
791
+=head1 VERSION
792
+
793
+2.501
794
+
795
+=head1 SYNOPSIS
796
+
797
+=over
798
+
799
+=item B<Preferred usage:>
800
+
801
+B<spfquery> [B<--versions>|B<-v> B<1>|B<2>|B<1,2>] [B<--scope>|B<-s> B<helo>|B<mfrom>|B<pra>]
802
+B<--identity>|B<--id> I<identity> B<--ip-address>|B<--ip> I<ip-address>
803
+[B<--helo-identity>|B<--helo-id> I<helo-identity>] [I<OPTIONS>]
804
+
805
+B<spfquery> [B<--versions>|B<-v> B<1>|B<2>|B<1,2>] [B<--scope>|B<-s> B<helo>|B<mfrom>|B<pra>]
806
+B<--file>|B<-f> I<filename>|B<-> [I<OPTIONS>]
807
+
808
+=item B<Legacy usage:>
809
+
810
+B<spfquery> B<--helo> I<helo-identity> B<--ip-address>|B<--ip> I<ip-address> [I<OPTIONS>]
811
+
812
+B<spfquery> B<--mfrom> I<mfrom-identity> B<--ip-address>|B<--ip> I<ip-address>
813
+[B<--helo> I<helo-identity>] [I<OPTIONS>]
814
+
815
+B<spfquery> B<--pra> I<pra-identity> B<--ip-address>|B<--ip> I<ip-address> [I<OPTIONS>]
816
+
817
+=item B<Other usage:>
818
+
819
+B<spfquery> B<--version>|B<-V>
820
+
821
+B<spfquery> B<--help>
822
+
823
+=back
824
+
825
+=head1 DESCRIPTION
826
+
827
+B<spfquery> checks if a given set of e-mail parameters (e.g., the SMTP sender's
828
+IP address) matches the responsible domain's Sender Policy Framework (SPF)
829
+policy.  For more information on SPF see L<http://www.openspf.org>.
830
+
831
+=head2 Preferred Usage
832
+
833
+The following usage forms are preferred over the L<legacy forms|/Legacy usage>
834
+used by older B<spfquery> versions:
835
+
836
+The B<--identity> form checks if the given I<ip-address> is an authorized SMTP
837
+sender for the given C<helo> hostname, C<mfrom> envelope sender e-mail address,
838
+or C<pra> (so-called purported resonsible address) e-mail address, depending
839
+on the value of the B<--scope> option (which defaults to B<mfrom> if omitted).
840
+
841
+The B<--file> form reads "I<ip-address> I<identity> [I<helo-identity>]" tuples
842
+from the file with the specified I<filename>, or from standard input if
843
+I<filename> is B<->, and checks them against the specified scope (B<mfrom> by
844
+default).
845
+
846
+Both forms support an optional B<--versions> option, which specifies a
847
+comma-separated list of the SPF version numbers of SPF records that may be
848
+used.  B<1> means that C<v=spf1> records should be used.  B<2> means that
849
+C<spf2.0> records should be used.  Defaults to B<1,2>, i.e., uses any SPF
850
+records that are available.  Records of a higher version are preferred.
851
+
852
+=head2 Legacy Usage
853
+
854
+B<spfquery> versions before 2.500 featured the following usage forms, which are
855
+discouraged but still supported for L<backwards compatibility|/COMPATIBILITY>:
856
+
857
+The B<--helo> form checks if the given I<ip-address> is an authorized SMTP
858
+sender for the C<HELO> hostname given as the I<identity> (so-called C<HELO>
859
+check).
860
+
861
+The B<--mfrom> form checks if the given I<ip-address> is an authorized SMTP
862
+sender for the envelope sender email-address (or domain) given as the
863
+I<identity> (so-called C<MAIL FROM> check).  If a domain is given instead of an
864
+e-mail address, C<postmaster> will be substituted for the localpart.
865
+
866
+The B<--pra> form checks if the given I<ip-address> is an authorized SMTP
867
+sender for the PRA (Purported Responsible Address) e-mail address given as the
868
+identity.
869
+
870
+=head2 Other Usage
871
+
872
+The B<--version> form prints version information of spfquery.  The B<--help>
873
+form prints usage information for spfquery.
874
+
875
+=head1 OPTIONS
876
+
877
+=head2 Standard Options
878
+
879
+The preferred and legacy forms optionally take any of the following
880
+I<OPTIONS>:
881
+
882
+=over
883
+
884
+=item B<--default-explanation> I<string>
885
+
886
+=item B<--def-exp> I<string>
887
+
888
+Use the specified I<string> as the default explanation if the authority domain
889
+does not specify an explanation string of its own.
890
+
891
+=item B<--hostname> I<hostname>
892
+
893
+Use I<hostname> as the host name of the local system instead of auto-detecting
894
+it.
895
+
896
+=item B<--keep-comments>
897
+
898
+=item B<--no-keep-comments>
899
+
900
+Do (not) print any comments found when reading from a file or from standard
901
+input.
902
+
903
+=item B<--sanitize> (currently ignored)
904
+
905
+=item B<--no-sanitize> (currently ignored)
906
+
907
+Do (not) sanitize the output by condensing consecutive white-space into a
908
+single space and replacing non-printable characters with question marks.
909
+Enabled by default.
910
+
911
+=item B<--debug> (currently ignored)
912
+
913
+Print out debug information.
914
+
915
+=back
916
+
917
+=head2 Black Magic Options
918
+
919
+Several options that were supported by earlier versions of B<spfquery> are
920
+considered black magic (i.e. potentially dangerous for the innocent user) and
921
+are thus disabled by default.  If the L<B<Mail::SPF::BlackMagic>> Perl module
922
+is installed, they may be enabled by specifying B<--enable-black-magic>.
923
+
924
+=over
925
+
926
+=item B<--max-dns-interactive-terms> I<n>
927
+
928
+Evaluate a maximum of I<n> DNS-interactive mechanisms and modifiers per SPF
929
+check.  Defaults to B<10>.  Do I<not> override the default unless you know what
930
+you are doing!
931
+
932
+=item B<--max-name-lookups-per-term> I<n>
933
+
934
+Perform a maximum of I<n> DNS name look-ups per mechanism or modifier.
935
+Defaults to B<10>.  Do I<not> override the default unless you know what you are
936
+doing!
937
+
938
+=item B<--authorize-mxes-for> I<email-address>|I<domain>B<,>...
939
+
940
+Consider all the MXes of the comma-separated list of I<email-address>es and
941
+I<domain>s as inherently authorized.
942
+
943
+=item B<--tfwl>
944
+
945
+Perform C<trusted-forwarder.org> accreditation checking.
946
+
947
+=item B<--guess> I<spf-terms>
948
+
949
+Use I<spf-terms> as a default record if no SPF record is found.
950
+
951
+=item B<--local> I<spf-terms>
952
+
953
+Process I<spf-terms> as local policy before resorting to a default result
954
+(the implicit or explicit C<all> mechanism at the end of the domain's SPF
955
+record).  For example, this could be used for white-listing one's secondary
956
+MXes: C<mx:mydomain.example.org>.
957
+
958
+=item B<--override> I<domain>B<=>I<spf-record>
959
+
960
+=item B<--fallback> I<domain>B<=>I<spf-record>
961
+
962
+Set overrides and fallbacks.  Each option can be specified multiple times.  For
963
+example:
964
+
965
+    --override example.org='v=spf1 -all'
966
+    --override '*.example.net'='v=spf1 a mx -all'
967
+    --fallback example.com='v=spf1 -all'
968
+
969
+=back
970
+
971
+=head1 RESULT CODES
972
+
973
+=over 12
974
+
975
+=item B<pass>
976
+
977
+The specified IP address is an authorized SMTP sender for the identity.
978
+
979
+=item B<fail>
980
+
981
+The specified IP address is not an authorized SMTP sender for the identity.
982
+
983
+=item B<softfail>
984
+
985
+The specified IP address is not an authorized SMTP sender for the identity,
986
+however the authority domain is still testing out its SPF policy.
987
+
988
+=item B<neutral>
989
+
990
+The identity's authority domain makes no assertion about the status of the IP
991
+address.
992
+
993
+=item B<permerror>
994
+
995
+A permanent error occurred while evaluating the authority domain's policy
996
+(e.g., a syntax error in the SPF record).  Manual intervention is required
997
+from the authority domain.
998
+
999
+=item B<temperror>
1000
+
1001
+A temporary error occurred while evaluating the authority domain's policy
1002
+(e.g., a DNS error).  Try again later.
1003
+
1004
+=item B<none>
1005
+
1006
+There is no applicable SPF policy for the identity domain.
1007
+
1008
+=back
1009
+
1010
+=head1 EXIT CODES
1011
+
1012
+  Result    | Exit code
1013
+ -----------+-----------
1014
+  pass      |     0
1015
+  fail      |     1
1016
+  softfail  |     2
1017
+  neutral   |     3
1018
+  permerror |     4
1019
+  temperror |     5
1020
+  none      |     6
1021
+
1022
+=head1 EXAMPLES
1023
+
1024
+    spfquery --scope mfrom --id user@example.com --ip 1.2.3.4
1025
+    spfquery --file test_data
1026
+    echo "127.0.0.1 user@example.com helohost.example.com" | spfquery -f -
1027
+
1028
+=head1 COMPATIBILITY
1029
+
1030
+B<spfquery> has undergone the following interface changes compared to earlier
1031
+versions:
1032
+
1033
+=over
1034
+
1035
+=item B<2.500>
1036
+
1037
+=over
1038
+
1039
+=item *
1040
+
1041
+A new preferred usage style for performing individual SPF checks has been
1042
+introduced.  The new style accepts a unified B<--identity> option and an
1043
+optional B<--scope> option that specifies the type (scope) of the identity.  In
1044
+contrast, the legacy usage style requires a separate usage form for every
1045
+supported scope.  See L</Preferred usage> and L</Legacy usage> for details.
1046
+
1047
+=item *
1048
+
1049
+The former C<unknown> and C<error> result codes have been renamed to C<permerror>
1050
+and C<temperror>, respectively, in order to comply with RFC 4408 terminology.
1051
+
1052
+=item *
1053
+
1054
+SPF checks with an empty identity are no longer supported.  In the case of an
1055
+empty C<MAIL FROM> SMTP transaction parameter, perform a check with the C<helo>
1056
+scope directly.
1057
+
1058
+=item *
1059
+
1060
+The B<--debug> and B<--(no-)sanitize> options are currently ignored by this
1061
+version of B<spfquery>.  They will again be supported in the future.
1062
+
1063
+=item *
1064
+
1065
+Several features that were supported by earlier versions of B<spfquery> are
1066
+considered black magic and thus are now disabled by default.  See L</Black
1067
+Magic Options>.
1068
+
1069
+=item *
1070
+
1071
+Several option names have been deprecated.  This is a list of them and their
1072
+preferred synonyms:
1073
+
1074
+  Deprecated options  | Preferred options
1075
+ ---------------------+-----------------------------
1076
+  --sender, -s        | --mfrom
1077
+  --ipv4, -i          | --ip-address, --ip
1078
+  --name              | --hostname
1079
+  --max-lookup-count, | --max-dns-interactive-terms
1080
+    --max-lookup      |
1081
+  --rcpt-to, -r       | --authorize-mxes-for
1082
+  --trusted           | --tfwl
1083
+
1084
+=back
1085
+
1086
+=back
1087
+
1088
+=head1 SEE ALSO
1089
+
1090
+L<Mail::SPF>, L<spfd(8)>
1091
+
1092
+L<http://www.ietf.org/rfc/rfc4408.txt>
1093
+
1094
+=head1 AUTHORS
1095
+
1096
+This version of B<spfquery> is a complete rewrite by Julian Mehnle
1097
+<julian@mehnle.net>, based on an earlier version written by Meng Weng Wong
1098
+<mengwong+spf@pobox.com> and Wayne Schlitt <wayne@schlitt.net>.
1099
+
1100
+=cut
1101
+
1102
+our $VERSION = '2.501';
1103
+
1104
+use warnings;
1105
+use strict;
1106
+
1107
+use IO::File;
1108
+use Getopt::Long qw(:config gnu_compat no_ignore_case);
1109
+use Error ':try';
1110
+use Mail::SPF;
1111
+
1112
+use constant TRUE   => (0 == 0);
1113
+use constant FALSE  => not TRUE;
1114
+
1115
+use constant exit_codes_by_result_code => {
1116
+    pass        => 0,
1117
+    fail        => 1,
1118
+    softfail    => 2,
1119
+    neutral     => 3,
1120
+    permerror   => 4,
1121
+    temperror   => 5,
1122
+    none        => 6
1123
+};
1124
+
1125
+# Helper Functions
1126
+##############################################################################
1127
+
1128
+sub usage {
1129
+    STDERR->printf(<<'EOT');
1130
+Preferred Usage:
1131
+    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
1132
+        --identity|--id <identity> --ip-address|--ip <ip-address>
1133
+        [--helo-identity|--helo-id <helo-identity>] [OPTIONS]
1134
+    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
1135
+        --file|-f <filename>|- [OPTIONS]
1136
+
1137
+Legacy Usage:
1138
+    spfquery --helo <helo-identity> --ip-address|--ip <ip-address> [OPTIONS]
1139
+    spfquery --mfrom <mfrom-identity> --ip-address|--ip <ip-address>
1140
+        [--helo <helo-identity>] [OPTIONS]
1141
+    spfquery --pra <pra-identity> --ip-address|--ip <ip-address> [OPTIONS]
1142
+
1143
+Other Usage:
1144
+    spfquery --version|-V
1145
+
1146
+See `spfquery --help` for more information.
1147
+EOT
1148
+    return;
1149
+}
1150
+
1151
+sub help {
1152
+    print(<<'EOT');
1153
+Preferred Usage:
1154
+    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
1155
+        --identity|--id <identity> --ip-address|--ip <ip-address>
1156
+        [--helo-identity|--helo-id <helo-identity>] [OPTIONS]
1157
+    spfquery [--versions|-v 1|2|1,2] [--scope|-s helo|mfrom|pra]
1158
+        --file|-f <filename>|- [OPTIONS]
1159
+
1160
+Legacy Usage:
1161
+    spfquery --helo <helo-identity> --ip-address|--ip <ip-address> [OPTIONS]
1162
+    spfquery --mfrom <mfrom-identity> --ip-address|--ip <ip-address>
1163
+        [--helo <helo-identity>] [OPTIONS]
1164
+    spfquery --pra <pra-identity> --ip-address|--ip <ip-address> [OPTIONS]
1165
+
1166
+Other Usage:
1167
+    spfquery --version|-V
1168
+
1169
+spfquery performs SPF checks based on the command-line arguments or data given
1170
+in a file or on standard input.
1171
+
1172
+Only the preferred and other usage forms are explained here.  See the
1173
+spfquery(1) man-page for an explanation of the legacy usage forms.
1174
+
1175
+The "--identity" form checks if the given <ip-address> is an authorized SMTP
1176
+sender for the given "helo" hostname, "mfrom" envelope sender e-mail address,
1177
+or "pra" (purported resonsible address) e-mail address, depending on the value
1178
+of the "--scope" option (which defaults to "mfrom" if omitted).
1179
+
1180
+The "--file" form reads "<ip-address> <identity> [<helo-identity>]" tuples from
1181
+the file with the specified <filename>, or from standard input if <filename> is
1182
+"-", and checks them against the specified scope ("mfrom" by default).
1183
+
1184
+The "--version" form prints version information of spfquery.
1185
+
1186
+Valid OPTIONS (and their defaults) are:
1187
+    --default-explanation <string>
1188
+                        Default explanation string to use (sensible default).
1189
+    --hostname <hostname>
1190
+                        The name of the system doing the SPF checking (local
1191
+                        system's configured hostname).
1192
+    --keep-comments     Print comments found when reading from a file.
1193
+    --no-sanitize       Do not clean up invalid characters in output.
1194
+    --debug             Output debugging information.
1195
+
1196
+Black-magic OPTIONS are:
1197
+    --max-dns-interactive-terms <n>
1198
+                        Maximum number of DNS-interactive mechanisms and
1199
+                        modifiers (10).
1200
+    --max-name-lookups-per-term <n>
1201
+                        Maximum number of DNS name look-ups per mechanism or
1202
+                        modifier (10).
1203
+    --authorize-mxes-for <email-address>|<domain>,...
1204
+                        A comma-separated list of e-mail addresses and domains
1205
+                        whose MXes will be considered inherently authorized.
1206
+    --tfwl              Check trusted-forwarder.org white-list.
1207
+    --guess <spf-terms> Default checks if no SPF record is found.
1208
+    --local <spf-terms> Local policy to process before default result.
1209
+    --override <domain>=<spf-record>
1210
+    --fallback <domain>=<spf-record>
1211
+                        Set override and fallback SPF records for domains.
1212
+
1213
+Examples:
1214
+    spfquery --scope mfrom --id user@example.com --ip 1.2.3.4
1215
+    spfquery --file test_data
1216
+    echo "127.0.0.1 user@example.com helohost.example.com" | spfquery -f -
1217
+EOT
1218
+    return;
1219
+}
1220
+
1221
+sub deprecated_option {
1222
+    my ($old_option, $new_option, $options) = @_;
1223
+    return FALSE if not exists($options->{$old_option});
1224
+    STDERR->print(
1225
+        "Warning: '$old_option' option is deprecated" .
1226
+        ($new_option ? "; use '$new_option' instead" : '') .
1227
+        ".\n"
1228
+    );
1229
+    $options->{$new_option} = delete($options->{$old_option});
1230
+    return TRUE;
1231
+}
1232
+
1233
+sub unsupported_option {
1234
+    my ($option_name, $options) = @_;
1235
+    return FALSE if not exists($options->{$option_name});
1236
+    STDERR->print("Error: '$option_name' option is no longer supported.\n");
1237
+    return TRUE;
1238
+}
1239
+
1240
+sub black_magic_option {
1241
+    my ($option_name, $options) = @_;
1242
+    return FALSE if not exists($options->{$option_name});
1243
+    STDERR->print("Error: '$option_name' option is black magic! Do not use it!\n");
1244
+    return TRUE;
1245
+}
1246
+
1247
+# Command-line Option Handling
1248
+##############################################################################
1249
+
1250
+my $options = {};
1251
+my $getopt_result = GetOptions(
1252
+    $options,
1253
+    
1254
+    'file|f=s',
1255
+    
1256
+    'versions|v=s',
1257
+    'scope=s',
1258
+    's=s',  # Special handling for ambiguous 's' option (formerly a synonym
1259
+            # for 'sender', now preferredly a synonym for 'scope').
1260
+    'identity|id=s',
1261
+    'ip-address|ip=s',
1262
+    'helo-identity|helo-id=s',
1263
+    
1264
+    # Legacy/shortcut options:
1265
+    'mfrom|mail-from|m=s',
1266
+    'helo|h=s',
1267
+    
1268
+    'default-explanation|def-exp=s',
1269
+    'hostname=s',
1270
+    
1271
+    'keep-comments!',
1272
+    'debug!',       # TODO Implement!
1273
+    'sanitize!',    # TODO Implement!
1274
+    
1275
+    # Black Magic options:
1276
+    'enable-black-magic!',
1277
+    'max-dns-interactive-terms=i',
1278
+    'max-name-lookups-per-term=i',
1279
+    'authorize-mxes-for=s',
1280
+                    # TODO implement!
1281
+    'tfwl!',        # TODO Implement!
1282
+    'guess=s',      # TODO Implement!
1283
+    'local=s',      # TODO Implement!
1284
+    'override=s%',  # TODO Implement!
1285
+    'fallback=s%',  # TODO Implement!
1286
+    
1287
+    # Meta actions:
1288
+    'version|V!',
1289
+    'help!',
1290
+    
1291
+    # Deprecated options:
1292
+    'sender=s',     # Now 'scope'/'identity' or 'mfrom'
1293
+    'ipv4=s',       # Now 'ip-address'
1294
+    'i=s',          # Now 'ip-address'
1295
+    'name=s',       # Now 'hostname'
1296
+    'max-lookup-count=i',
1297
+    'max-lookup=i', # Now 'max-dns-interactive-terms'
1298
+    'rcpt-to=s',    # Now 'authorize-mxes-for'
1299
+    'r=s',          # Now 'authorize-mxes-for'
1300
+    'trusted!'      # Now 'tfwl'
1301
+);
1302
+
1303
+if (not $getopt_result) {
1304
+    usage();
1305
+    exit(255);
1306
+}
1307
+
1308
+if ($options->{help}) {
1309
+    help();
1310
+    exit(0);
1311
+}
1312
+
1313
+if ($options->{version}) {
1314
+    print("spfquery version $VERSION (using Mail::SPF)\n");
1315
+    exit(0);
1316
+}
1317
+
1318
+deprecated_option('sender',           'mfrom',                     $options);
1319
+deprecated_option('ipv4',             'ip-address',                $options);
1320
+deprecated_option('i',                'ip-address',                $options);
1321
+deprecated_option('name',             'hostname',                  $options);
1322
+deprecated_option('max-lookup-count', 'max-dns-interactive-terms', $options);
1323
+deprecated_option('max-lookup',       'max-dns-interactive-terms', $options);
1324
+deprecated_option('rcpt-to',          'authorize-mxes-for',        $options);
1325
+deprecated_option('r',                'authorize-mxes-for',        $options);
1326
+deprecated_option('trusted',          'tfwl',                      $options);
1327
+
1328
+if ($options->{'enable-black-magic'}) {
1329
+    if (not defined(eval('require Mail::SPF::BlackMagic'))) {
1330
+        STDERR->print("Error: Cannot enable black magic. Unable to load Mail::SPF::BlackMagic.\n");
1331
+        exit(255);
1332
+    }
1333
+    # else: Black magic enabled!
1334
+}
1335
+elsif (
1336
+    black_magic_option('max-dns-interactive-terms', $options) or
1337
+    black_magic_option('max-name-lookups-per-term', $options) or
1338
+    black_magic_option('rcpt-to',                   $options) or
1339
+    black_magic_option('trusted',                   $options) or
1340
+    black_magic_option('guess',                     $options) or
1341
+    black_magic_option('local',                     $options) or
1342
+    black_magic_option('override',                  $options) or
1343
+    black_magic_option('fallback',                  $options)
1344
+) {
1345
+    exit(255);
1346
+}
1347
+
1348
+my @versions            = split(',', $options->{versions} || '');
1349
+my $scope               = $options->{scope};
1350
+my $identity            = $options->{identity};
1351
+my $ip_address          = $options->{'ip-address'};
1352
+my $helo_identity       = $options->{'helo-identity'};
1353
+
1354
+# Heuristic for distinguishing between 's(cope)' and 's(ender)':
1355
+if (defined(my $s = $options->{s})) {
1356
+    if (
1357
+        not defined($scope) and  # No explicit 'scope' option has been specified, and
1358
+        $s !~ /[@.]/             # 's' option contains neither an '@' nor a dot,
1359
+                                 # so it cannot be an e-mail address or a domain.
1360
+    ) {
1361
+        # Thus it must be meant as the 'scope' option:
1362
+        $scope = $s;
1363
+    }
1364
+    else {
1365
+        # Else, it must be meant as the deprecated 'sender' option:
1366
+        $options->{mfrom} = $s;
1367
+    }
1368
+}
1369
+
1370
+# Heuristic for when explicit 'scope'/'s(cope)' option is absent:
1371
+if (not defined($scope)) {
1372
+    if (defined($identity) or defined($options->{file})) {
1373
+        # Identity has been specified, or input will be read from file:
1374
+        # apply the 'scope' option default:
1375
+        $scope    = 'mfrom';
1376
+    }
1377
+    elsif (defined($options->{helo})) {
1378
+        $scope    = 'helo';
1379
+        $identity = $options->{helo};
1380
+    }
1381
+    elsif (defined($options->{mfrom})) {
1382
+        $scope    = 'mfrom';
1383
+        $identity = $options->{mfrom};
1384
+        $helo_identity ||= $options->{helo};
1385
+    }
1386
+    elsif (defined($options->{pra})) {
1387
+        $scope    = 'pra';
1388
+        $identity = $options->{pra};
1389
+    }
1390
+}
1391
+
1392
+my $default_explanation = $options->{'default-explanation'};
1393
+my $hostname            = $options->{hostname};
1394
+
1395
+if (
1396
+    not defined($scope) or
1397
+    not (defined($identity) xor defined($options->{file}))
1398
+) {
1399
+    usage();
1400
+    exit(255);
1401
+}
1402
+
1403
+if (defined($identity) and $identity eq '') {
1404
+    STDERR->print("Error: Empty identities are not supported. See spfquery(1).\n");
1405
+    exit(255);
1406
+}
1407
+
1408
+# Process the SPF Request(s)
1409
+##############################################################################
1410
+
1411
+try {
1412
+    my $spf_server = Mail::SPF::Server->new(
1413
+        default_authority_explanation
1414
+                        => $default_explanation,
1415
+        hostname        => $hostname,
1416
+    #    debug           => $options->{debug},
1417
+    #    sanitize        => $options->{sanitize},
1418
+
1419
+        # Black Magic:
1420
+        (
1421
+            exists($options->{'max-dns-interactive-terms'}) ?
1422
+                (max_dns_interactive_terms  => $options->{'max-dns-interactive-terms'} || undef)
1423
+            :   ()
1424
+        ),
1425
+        (
1426
+            exists($options->{'max-name-lookups-per-term'}) ?
1427
+                (max_name_lookups_per_term  => $options->{'max-name-lookups-per-term'} || undef)
1428
+            :   ()
1429
+        )
1430
+    #    rcpt_to         => $options->{'rcpt-to'},
1431
+    #    trusted         => $options->{trusted},
1432
+    #    guess           => $options->{guess},
1433
+    #    local           => $options->{local},
1434
+    #    override        => $options->{override},
1435
+    #    fallback        => $options->{fallback},
1436
+    );
1437
+
1438
+    my $exit_code;
1439
+
1440
+    if (not defined($options->{file})) {
1441
+        # Single request:
1442
+        my $result_code = do_process(
1443
+            $spf_server,
1444
+            versions        => @versions ? [@versions] : undef,
1445
+            scope           => $scope,
1446
+            identity        => $identity,
1447
+            ip_address      => $ip_address,
1448
+            helo_identity   => $helo_identity
1449
+        );
1450
+        $exit_code = exit_codes_by_result_code->{$result_code};
1451
+    }
1452
+    else {
1453
+        # File request:
1454
+        my $file = $options->{file} eq '-' ? \*STDIN : IO::File->new($options->{file})
1455
+            or die("Could not open: $options->{file}\n");
1456
+        while (<$file>) {
1457
+            chomp;
1458
+            s/^\s*//;
1459
+            next if /^$/;
1460
+            if (/^#/) {
1461
+                print("$_\n") if $options->{'keep-comments'};
1462
+                next;
1463
+            }
1464
+            ($ip_address, $identity, $helo_identity) = split;
1465
+            my $result_code = do_process(
1466
+                $spf_server,
1467
+                versions        => @versions ? [@versions] : undef,
1468
+                scope           => $scope,
1469
+                identity        => $identity,
1470
+                ip_address      => $ip_address,
1471
+                helo_identity   => $helo_identity
1472
+            );
1473
+            $exit_code ||= exit_codes_by_result_code->{$result_code};
1474
+        }
1475
+    }
1476
+
1477
+    exit($exit_code);
1478
+}
1479
+catch Mail::SPF::Exception with {
1480
+    my ($e) = @_;
1481
+    STDERR->printf("Error: %s.\n", $e->text);
1482
+    exit(255);
1483
+};
1484
+
1485
+
1486
+# Helper Function
1487
+##############################################################################
1488
+
1489
+sub do_process {
1490
+    my ($spf_server, %request_options) = @_;
1491
+    my $request = Mail::SPF::Request->new(%request_options);
1492
+    my $result  = $spf_server->process($request);
1493
+    printf(
1494
+        "%s\n%s\n%s\n%s\n",
1495
+        $result->code,
1496
+        (
1497
+            $result->can('authority_explanation') ?
1498
+                $result->authority_explanation
1499
+            :   $result->local_explanation
1500
+        ),
1501
+        $result->local_explanation,
1502
+        $result->received_spf_header
1503
+    );
1504
+    return $result->code;
1505
+}
(-)p5-Mail-SPF/pkg-plist (-1 / +1 lines)
Lines 1-4 Link Here
1
bin/spfquery
1
%%SPFQUERY%%bin/spfquery%%SPFQUERY_SUFFIX%%

Return to bug 157107