Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 165604
Collapse All | Expand All

(-)postfix-2.3.2/README_FILES/SPF_README (+88 lines)
Line 0 Link Here
1
Postfix SPF readme
2
-------------------
3
4
SPF patch for libspf2 >= 1.2.0 by Nigel Kukard, partly based on work
5
by Dean Strik's and Jef Poskanzer's spfmilter
6
7
Official site:    http://www.linuxrulz.org/nkukard/postfix/
8
License:          Secure Mailer License (Postfix License)
9
10
----
11
12
This document describes how to configure Postfix to use SPF ("Sender
13
Policy Framework") validation. It does not describe the function or
14
design of SPF itself. Refer to one or more of the websites listed at
15
the end of this text for more information.
16
17
The actual SPF validation is offloaded to a special library called
18
libspf2. It is therefore necessary that you install libspf2 on your
19
system. You can find libspf2 either in your usual package repository or
20
at http://www.libspf2.org/.
21
22
To build Postfix, after installing libspf2, use something like:
23
24
    % make tidy
25
    % make makefiles CCARGS="-I/usr/local/include -DHAVE_NS_TYPE" \
26
        AUXLIBS="-L/usr/local/lib -lspf2"
27
    % make
28
29
-DHAVE_NS_TYPE is only needed if your system complains about ns_type
30
conflicting.
31
32
The pathnames here are the default pathnames used by libspf2's
33
installation procedure, which is not documented here.
34
35
SPF sender validation is implemented using a standard Postfix
36
restriction, called "reject_spf_invalid_sender". This means that you
37
can put this restriction in e.g. your smtpd_recipient_restrictions.
38
For more information on how to do this, consult your Postfix
39
documentation.
40
41
Postfix will by default add a mail header, Received-SPF:, to any mail
42
passing the SPF validation. This information can be useful for the
43
recipient of the message. You can disable this behaviour by setting
44
'spf_received_header = no'.
45
46
By default, Postfix will reject mail with invalid sender credentials.
47
You can however choose to prevent this from happening, and let the mail
48
pass, by setting 'spf_mark_only = yes'. The Received-SPF: header
49
(if enabled, see above) will show that the mail failed the test.
50
51
You can set the numerical SMTP response code when rejecting mails
52
due to SPF rule violations by changing the value of the
53
'spf_reject_code' variable (default: 550).
54
55
If a site does provide SPF DNS records yet no explanation, a generic
56
explanation will be used, with a URL to visit for more information.
57
You can override this generic explanation by setting the spf_explanation
58
setting, e.g.:
59
60
    spf_explanation = "%{h} [%{i}] is not allowed to send mail for %{s}"
61
62
See the SPF reference sites for information about the format used.
63
64
It is also possible to set a local policy using the spf_local_policy
65
setting. Currently the format is not documented here.
66
67
There exists a global SPF whitelist on trusted-forwarder.org. You can
68
enable use of this global whitelist by setting the variable
69
'spf_global_whitelist = yes'.
70
71
----
72
73
Bugs/problems/reports: the author of this patch, Nigel Kukard, can be
74
contacted at <nkukard@lbsd.net>. If reporting a problem, please send
75
the output of
76
    postconf -d spf_patch_version spf_libspf2_version
77
with your report.
78
79
Downloads and information with regard to this patch can be found at 
80
http://www.lbsd.net/~nkukard/postfix/
81
82
Links:
83
	http://www.ipnet6.org/postfix/spf/	- Original patch home
84
	http://spf.pobox.com/			- SPF background
85
	http://www.libspf2.org/			- LibSPF2 site
86
	http://www.trusted-forwarder.org/	- Global whitelist
87
	http://www.postfix.org/			- Postfix home page
88
(-)postfix-2.3.2/conf/postfix-files (+1 lines)
Lines 262-267 Link Here
262
$readme_directory/SMTPD_ACCESS_README:f:root:-:644
262
$readme_directory/SMTPD_ACCESS_README:f:root:-:644
263
$readme_directory/SMTPD_POLICY_README:f:root:-:644
263
$readme_directory/SMTPD_POLICY_README:f:root:-:644
264
$readme_directory/SMTPD_PROXY_README:f:root:-:644
264
$readme_directory/SMTPD_PROXY_README:f:root:-:644
265
$readme_directory/SPF_README:f:root:-:644
265
$readme_directory/STANDARD_CONFIGURATION_README:f:root:-:644
266
$readme_directory/STANDARD_CONFIGURATION_README:f:root:-:644
266
$readme_directory/TLS_README:f:root:-:644
267
$readme_directory/TLS_README:f:root:-:644
267
$readme_directory/TUNING_README:f:root:-:644
268
$readme_directory/TUNING_README:f:root:-:644
(-)postfix-2.3.2/src/global/mail_params.h (+33 lines)
Lines 2505-2510 Link Here
2505
#define CHECK_POLICY_SERVICE		"check_policy_service"
2505
#define CHECK_POLICY_SERVICE		"check_policy_service"
2506
2506
2507
 /*
2507
 /*
2508
  * SPF support.
2509
  */
2510
#define REJECT_ILL_SPF_SENDER		"reject_spf_invalid_sender"
2511
2512
#define VAR_SPF_REJECT_CODE		"spf_reject_code"
2513
#define DEF_SPF_REJECT_CODE		550
2514
extern int var_spf_reject_code;
2515
2516
#define VAR_SPF_REJECT_DSN              "spf_reject_dsn"
2517
#define DEF_SPF_REJECT_DSN              "5.7.1"
2518
extern char *var_spf_reject_dsn;
2519
2520
#define VAR_SPF_MARK_ONLY		"spf_mark_only"
2521
#define DEF_SPF_MARK_ONLY		0
2522
extern bool var_spf_mark_only;
2523
2524
#define VAR_SPF_RCVD_HEADER		"spf_received_header"
2525
#define DEF_SPF_RCVD_HEADER		1
2526
extern bool var_spf_rcvd_header;
2527
2528
#define VAR_SPF_LOCAL_POLICY		"spf_local_policy"
2529
#define DEF_SPF_LOCAL_POLICY		""
2530
extern char *var_spf_local_policy;
2531
2532
#define VAR_SPF_EXPLANATION		"spf_explanation"
2533
#define DEF_SPF_EXPLANATION		""
2534
extern char *var_spf_explanation;
2535
2536
#define VAR_SPF_GLOBAL_WHITELIST	"spf_global_whitelist"
2537
#define DEF_SPF_GLOBAL_WHITELIST	0
2538
extern bool var_spf_global_whitelist;
2539
2540
 /*
2508
  * Client rate control.
2541
  * Client rate control.
2509
  */
2542
  */
2510
#define VAR_SMTPD_CRATE_LIMIT		"smtpd_client_connection_rate_limit"
2543
#define VAR_SMTPD_CRATE_LIMIT		"smtpd_client_connection_rate_limit"
(-)postfix-2.3.2/src/global/mail_version.h (+7 lines)
Lines 47-52 Link Here
47
#define DEF_MAIL_RELEASE	MAIL_RELEASE_DATE
47
#define DEF_MAIL_RELEASE	MAIL_RELEASE_DATE
48
extern char *var_mail_release;
48
extern char *var_mail_release;
49
49
50
/*
51
 * SPF patch version.
52
 */
53
#define VAR_SPF_PVERSION	"spf_patch_version"
54
#define DEF_SPF_PVERSION	"1.0.0"
55
extern char *var_spf_version;
56
50
/* LICENSE
57
/* LICENSE
51
/* .ad
58
/* .ad
52
/* .fi
59
/* .fi
(-)postfix-2.3.2/src/smtpd/Makefile.in (-3 / +4 lines)
Lines 1-12 Link Here
1
SHELL	= /bin/sh
1
SHELL	= /bin/sh
2
SRCS	= smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
2
SRCS	= smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \
3
	smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
3
	smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \
4
	smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c
4
	smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c smtpd_spf.c
5
OBJS	= smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
5
OBJS	= smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \
6
	smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
6
	smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \
7
	smtpd_xforward.o smtpd_dsn_fix.o smtpd_milter.o
7
	smtpd_xforward.o smtpd_dsn_fix.o smtpd_milter.o smtpd_spf.o
8
HDRS	= smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
8
HDRS	= smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \
9
	smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h smtpd_milter.h
9
	smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h smtpd_milter.h \
10
        smtpd_spf.h
10
TESTSRC	= smtpd_token_test.c
11
TESTSRC	= smtpd_token_test.c
11
DEFS	= -I. -I$(INC_DIR) -D$(SYSTYPE)
12
DEFS	= -I. -I$(INC_DIR) -D$(SYSTYPE)
12
CFLAGS	= $(DEBUG) $(OPT) $(DEFS)
13
CFLAGS	= $(DEBUG) $(OPT) $(DEFS)
(-)postfix-2.3.2/src/smtpd/smtpd.c (+26 lines)
Lines 948-953 Link Here
948
#include <smtpd_chat.h>
948
#include <smtpd_chat.h>
949
#include <smtpd_sasl_proto.h>
949
#include <smtpd_sasl_proto.h>
950
#include <smtpd_sasl_glue.h>
950
#include <smtpd_sasl_glue.h>
951
#include <smtpd_spf.h>
951
#include <smtpd_proxy.h>
952
#include <smtpd_proxy.h>
952
#include <smtpd_milter.h>
953
#include <smtpd_milter.h>
953
954
Lines 1052-1057 Link Here
1052
char   *var_smtpd_ehlo_dis_words;
1053
char   *var_smtpd_ehlo_dis_words;
1053
char   *var_smtpd_ehlo_dis_maps;
1054
char   *var_smtpd_ehlo_dis_maps;
1054
1055
1056
bool    var_spf_mark_only;
1057
int     var_spf_reject_code;
1058
char   *var_spf_reject_dsn;
1059
bool    var_spf_rcvd_header;
1060
1061
char   *var_spf_local_policy;
1062
char   *var_spf_explanation;
1063
bool    var_spf_global_whitelist;
1064
1055
char   *var_smtpd_tls_level;
1065
char   *var_smtpd_tls_level;
1056
bool    var_smtpd_use_tls;
1066
bool    var_smtpd_use_tls;
1057
bool    var_smtpd_enforce_tls;
1067
bool    var_smtpd_enforce_tls;
Lines 2130-2135 Link Here
2130
#ifdef DELAY_ACTION
2140
#ifdef DELAY_ACTION
2131
    state->saved_delay = 0;
2141
    state->saved_delay = 0;
2132
#endif
2142
#endif
2143
    smtpd_spf_sess_reset(state);
2133
#ifdef USE_SASL_AUTH
2144
#ifdef USE_SASL_AUTH
2134
    if (var_smtpd_sasl_enable)
2145
    if (var_smtpd_sasl_enable)
2135
	smtpd_sasl_mail_reset(state);
2146
	smtpd_sasl_mail_reset(state);
Lines 2531-2536 Link Here
2531
	    out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
2542
	    out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
2532
2543
2533
    /*
2544
    /*
2545
     * Prepend Received-SPF header. The header (name,value) has been
2546
     * constructed before in the SPF handler (if SPF is enabled).
2547
     */
2548
    if (var_spf_rcvd_header && state->spf_sess_data != NULL
2549
	    && state->spf_header)
2550
	out_fprintf(out_stream, REC_TYPE_NORM, "%s", state->spf_header);
2551
    
2552
    /*
2534
     * Suppress our own Received: header in the unlikely case that we are an
2553
     * Suppress our own Received: header in the unlikely case that we are an
2535
     * intermediate proxy.
2554
     * intermediate proxy.
2536
     */
2555
     */
Lines 4415-4420 Link Here
4415
	VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
4434
	VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
4416
	VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0,
4435
	VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0,
4417
	VAR_SMTPD_CNTLS_LIMIT, DEF_SMTPD_CNTLS_LIMIT, &var_smtpd_cntls_limit, 0, 0,
4436
	VAR_SMTPD_CNTLS_LIMIT, DEF_SMTPD_CNTLS_LIMIT, &var_smtpd_cntls_limit, 0, 0,
4437
        VAR_SPF_REJECT_CODE, DEF_SPF_REJECT_CODE, &var_spf_reject_code, 0, 0,
4418
#ifdef USE_TLS
4438
#ifdef USE_TLS
4419
	VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
4439
	VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
4420
	VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
4440
	VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0,
Lines 4454-4459 Link Here
4454
	VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
4474
	VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls,
4455
	VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
4475
	VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls,
4456
	VAR_SMTPD_TLS_WRAPPER, DEF_SMTPD_TLS_WRAPPER, &var_smtpd_tls_wrappermode,
4476
	VAR_SMTPD_TLS_WRAPPER, DEF_SMTPD_TLS_WRAPPER, &var_smtpd_tls_wrappermode,
4477
	VAR_SPF_MARK_ONLY, DEF_SPF_MARK_ONLY, &var_spf_mark_only,
4478
	VAR_SPF_RCVD_HEADER, DEF_SPF_RCVD_HEADER, &var_spf_rcvd_header,
4479
	VAR_SPF_GLOBAL_WHITELIST, DEF_SPF_GLOBAL_WHITELIST, &var_spf_global_whitelist,
4457
#ifdef USE_TLS
4480
#ifdef USE_TLS
4458
	VAR_SMTPD_TLS_AUTH_ONLY, DEF_SMTPD_TLS_AUTH_ONLY, &var_smtpd_tls_auth_only,
4481
	VAR_SMTPD_TLS_AUTH_ONLY, DEF_SMTPD_TLS_AUTH_ONLY, &var_smtpd_tls_auth_only,
4459
	VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
4482
	VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
Lines 4507-4512 Link Here
4507
	VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients, 0, 0,
4530
	VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients, 0, 0,
4508
	VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0,
4531
	VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0,
4509
	VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0,
4532
	VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0,
4533
	VAR_SPF_LOCAL_POLICY, DEF_SPF_LOCAL_POLICY, &var_spf_local_policy, 0, 0,
4534
	VAR_SPF_EXPLANATION, DEF_SPF_EXPLANATION, &var_spf_explanation, 0, 0,
4535
        VAR_SPF_REJECT_DSN, DEF_SPF_REJECT_DSN, &var_spf_reject_dsn, 0, 0,
4510
#ifdef USE_TLS
4536
#ifdef USE_TLS
4511
	VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_smtpd_relay_ccerts, 0, 0,
4537
	VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_smtpd_relay_ccerts, 0, 0,
4512
	VAR_SMTPD_SASL_TLS_OPTS, DEF_SMTPD_SASL_TLS_OPTS, &var_smtpd_sasl_tls_opts, 0, 0,
4538
	VAR_SMTPD_SASL_TLS_OPTS, DEF_SMTPD_SASL_TLS_OPTS, &var_smtpd_sasl_tls_opts, 0, 0,
(-)postfix-2.3.2/src/smtpd/smtpd.h (+10 lines)
Lines 13-18 Link Here
13
  */
13
  */
14
#include <sys/time.h>
14
#include <sys/time.h>
15
#include <unistd.h>
15
#include <unistd.h>
16
#include <arpa/nameser.h>		/* for spf2/spf.h */
17
#include <sys/socket.h>			/* for spf2/spf.h */
18
#include <netinet/in.h>			/* for spf2/spf.h */
19
#include <spf2/spf.h>
16
20
17
 /*
21
 /*
18
  * Utility library.
22
  * Utility library.
Lines 148-153 Link Here
148
    VSTRING *dsn_orcpt_buf;		/* scratch space for ORCPT parsing */
152
    VSTRING *dsn_orcpt_buf;		/* scratch space for ORCPT parsing */
149
153
150
    /*
154
    /*
155
     * SPF.
156
     */
157
    SPF_request_t *spf_sess_data;	/* session specific SPF data */
158
    char *spf_header;			/* SPF header to insert */
159
160
    /*
151
     * Pass-through proxy client.
161
     * Pass-through proxy client.
152
     */
162
     */
153
    VSTREAM *proxy;			/* proxy handle */
163
    VSTREAM *proxy;			/* proxy handle */
(-)postfix-2.3.2/src/smtpd/smtpd_check.c (+66 lines)
Lines 244-249 Link Here
244
#include "smtpd_sasl_glue.h"
244
#include "smtpd_sasl_glue.h"
245
#include "smtpd_check.h"
245
#include "smtpd_check.h"
246
#include "smtpd_dsn_fix.h"
246
#include "smtpd_dsn_fix.h"
247
#include "smtpd_spf.h"
247
248
248
#define RESTRICTION_SEPARATORS ", \t\r\n"
249
#define RESTRICTION_SEPARATORS ", \t\r\n"
249
250
Lines 1725-1730 Link Here
1725
    return (stat);
1726
    return (stat);
1726
}
1727
}
1727
1728
1729
/* reject_spf_invalid_sender - check sender validity using SPF records */
1730
1731
static int reject_spf_invalid_sender(SMTPD_STATE *state, const char *addr,
1732
			    const char *reply_name, const char *reply_class)
1733
{
1734
    char   *myname = "reject_spf_invalid_sender";
1735
    char   *comment;
1736
    int     action, stat;
1737
1738
    /*
1739
     * Currently, this is the only place where SPF routines are used.
1740
     * It therefore makes little sense to initialize the SPF data
1741
     * before now.
1742
     */
1743
    smtpd_spf_sess_init(state);
1744
    smtpd_spf_set_helo(state, state->helo_name);
1745
    smtpd_spf_set_from(state, state->sender);
1746
1747
    /*
1748
     * Obtain SPF result.
1749
     */
1750
    comment = NULL;
1751
    action = smtpd_spf_result(state,
1752
		(var_spf_rcvd_header ? &state->spf_header : NULL),
1753
		&comment);
1754
1755
    /*
1756
     * Perform actions.
1757
     */
1758
    stat = SMTPD_CHECK_DUNNO;
1759
    switch (action) {
1760
        case SPF_ACTION_REJECT:
1761
            stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
1762
                    var_spf_reject_code, var_spf_reject_dsn,
1763
                    "<%s>: %s rejected: %s",
1764
                    reply_name, reply_class,
1765
                    (comment ? comment : "SPF policy violation"));
1766
            break;
1767
	    
1768
        case SPF_ACTION_TEMPFAIL:
1769
            /* XXX log error? */
1770
           DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
1771
                   450, "4.7.1",
1772
                   "<%s>: %s rejected: Unable to look up SPF information",
1773
                   reply_name, reply_class);
1774
           break;
1775
1776
        default:
1777
           break;
1778
    }
1779
1780
1781
    /*
1782
     * Cleanup.
1783
     */
1784
    if (comment != NULL)
1785
        myfree(comment);
1786
1787
    return (stat);
1788
}
1789
1728
/* reject_unknown_address - fail if address does not resolve */
1790
/* reject_unknown_address - fail if address does not resolve */
1729
1791
1730
static int reject_unknown_address(SMTPD_STATE *state, const char *addr,
1792
static int reject_unknown_address(SMTPD_STATE *state, const char *addr,
Lines 3670-3675 Link Here
3670
	    if (state->sender && *state->sender)
3732
	    if (state->sender && *state->sender)
3671
		status = reject_non_fqdn_address(state, state->sender,
3733
		status = reject_non_fqdn_address(state, state->sender,
3672
					  state->sender, SMTPD_NAME_SENDER);
3734
					  state->sender, SMTPD_NAME_SENDER);
3735
	} else if (strcasecmp(name, REJECT_ILL_SPF_SENDER) == 0) {
3736
	    if (state->sender && *state->sender)
3737
		status = reject_spf_invalid_sender(state, state->sender,
3738
					  state->sender, SMTPD_NAME_SENDER);
3673
	} else if (strcasecmp(name, REJECT_AUTH_SENDER_LOGIN_MISMATCH) == 0) {
3739
	} else if (strcasecmp(name, REJECT_AUTH_SENDER_LOGIN_MISMATCH) == 0) {
3674
#ifdef USE_SASL_AUTH
3740
#ifdef USE_SASL_AUTH
3675
	    if (var_smtpd_sasl_enable) {
3741
	    if (var_smtpd_sasl_enable) {
(-)postfix-2.3.2/src/smtpd/smtpd_spf.c (+332 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*	smtpd_spf 3
4
/* SUMMARY
5
/*	SMTP server SPF support
6
/* SYNOPSIS
7
/*	#include <smtpd.h>
8
/*	#include <smtpd_spf.h>
9
/*
10
/*	void	smtpd_spf_init(state)
11
/*	SMTPD_STATE *state;
12
/*
13
/*	int	smtpd_spf_sess_init(state)
14
/*	SMTPD_STATE *state;
15
/*
16
/*	void	smtpd_spf_sess_reset(state)
17
/*	SMTPD_STATE *state;
18
/*
19
/*	int	smtpd_spf_set_helo(state, name)
20
/*	SMTPD_STATE *state;
21
/*	char	*name;
22
/*
23
/*	int	smtpd_spf_set_from(state, name)
24
/*	SMTPD_STATE *state;
25
/*	char	*name;
26
/*
27
/*	int	smtpd_spf_result(state, *header, *comment)
28
/*	SMTPD_STATE *state;
29
/*	char	**header;
30
/*	char	**comment;
31
/*
32
/* DESCRIPTION
33
/*	This modules provides SPF state management functions,
34
/*	making the other SMTP components independent on the
35
/*	actual SPF routines used.
36
/*
37
/*	smtpd_spf_init() initializes global SPF context.
38
/*
39
/*	smtpd_spf_sess_init() initializes SPF session context.
40
/*
41
/*	smtpd_spf_sess_reset() cleans up SPF session context.
42
/*
43
/*	smtpd_spf_set_helo() passes the client HELO name to
44
/*	the underlying libspf2 context.
45
/*
46
/*	smtpd_spf_set_from() passes the SMTP envelope sender
47
/*	to the underlying libspf2 context.
48
/*
49
/*	smtpd_spf_result() performs (via libspf2) the SPF lookups
50
/*	and handling, and creates a Received-SPF header.
51
/*
52
/*	Arguments:
53
/* .IP state
54
/*	Session context.
55
/* .IP name
56
/*	The value to set in the low-level SPF context.
57
/* DIAGNOSTICS
58
/*	Panic: interface violations. Fatal errors: out of memory.
59
/*	internal protocol errors.
60
/* LICENSE
61
/* .ad
62
/* .fi
63
/*	The Secure Mailer license must be distributed with this software.
64
/* AUTHOR(S)
65
/* 	Nigel Kukard
66
/* 	E-mail: <nkukard@lbsd.net>
67
/* 
68
/*      Dean C. Strik
69
/*      Department ICT
70
/*      Eindhoven University of Technology
71
/*      P.O. Box 513
72
/*      5600 MB  Eindhoven, Netherlands
73
/*      E-mail: <dean@ipnet6.org>
74
/*--*/
75
76
77
/* System library. */
78
#include <sys_defs.h>
79
#include <sys/socket.h>
80
#include <netinet/in.h>
81
#include <arpa/inet.h>
82
#include <arpa/nameser.h>
83
#include <errno.h>
84
#include <netdb.h>
85
#include <string.h>
86
#include <spf2/spf.h>
87
#include <spf2/spf_dns_resolv.h>
88
#include <spf2/spf_dns_cache.h>
89
90
/* Global library */
91
#include <mail_params.h>
92
#include <msg.h>
93
#include <mymalloc.h>
94
95
/* Application library */
96
#include "smtpd.h"
97
#include "smtpd_spf.h"
98
99
#define SPF_DNS_CACHE_BITS 8
100
101
//static SPF_config_t	spf_global_data;	/* common SPF configuration data */
102
//static SPF_dns_config_t	spf_resolv_data;	/* SPF DNS resolver data */
103
//static SPF_dns_config_t	spf_resolv_cache;	/* SPF DNS resolver cache */
104
//static SPF_c_results_t	spf_local_policy;	/* compiled local policy */
105
//static SPF_c_results_t	spf_explanation;	/* custom explanation */
106
107
static SPF_server_t	*spf_global_server;
108
109
110
/* Initialize global SPF context */
111
void smtpd_spf_init(SMTPD_STATE *state)
112
{
113
	char   *myname = "smtpd_spf_global_init";
114
	SPF_response_t *spf_response;
115
	int res;
116
	
117
118
	/*
119
	* Initialize libspf2 server
120
	*/
121
	spf_global_server = SPF_server_new(SPF_DNS_CACHE, 0);
122
	if (spf_global_server == NULL)
123
		msg_fatal("%s: unable to create SPF server", myname);
124
125
	if (SPF_server_set_rec_dom(spf_global_server, var_myhostname) != 0)
126
		msg_fatal("%s: can't set SPF hostname", myname);
127
   
128
	if (var_spf_explanation != NULL && *var_spf_explanation != 0)
129
	{
130
		res = SPF_server_set_explanation(spf_global_server, var_spf_explanation, 
131
				&spf_response);
132
		SPF_response_free(spf_response);
133
		if (res != 0)
134
		{	
135
			msg_fatal("%s: can't set SPF explanation", myname);
136
		}
137
	}
138
139
	if (var_spf_local_policy != NULL && *var_spf_local_policy != 0)
140
	{	
141
		res = SPF_server_set_localpolicy(spf_global_server, var_spf_local_policy, 0, 
142
				&spf_response);
143
		SPF_response_free(spf_response);
144
		if (res != 0)
145
		{	
146
			msg_fatal("%s: can't set SPF local policy", myname);
147
		}
148
	}
149
	
150
	/*
151
	* Clear session-specific data (session init is on-demand)
152
	*/
153
	state->spf_sess_data = NULL;
154
	state->spf_header = NULL;
155
}
156
157
158
/* Initialize session dependent SPF context */
159
int smtpd_spf_sess_init(SMTPD_STATE *state)
160
{
161
	char   *myname = "smtpd_spf_init_sess_data";
162
163
164
	/*
165
	 * Sanity checks.
166
	 */
167
	if (state->addr == 0)
168
		msg_panic("%s: client address not initialized", myname);
169
	if (spf_global_server == NULL)
170
		msg_panic("%s: spf_global_server not initialized", myname);
171
172
	/*
173
	 * This code is recipient-independent. SPF session data is
174
	 * already initialized if there have been earlier RCPT TO
175
	 * commands in this transaction, and we're done.
176
	 * XXX: make the code recipient-dependent (restriction classes)
177
	 */
178
	if (state->spf_sess_data != NULL)
179
		return 0;
180
181
	/*
182
	 * Initialize session-specific SPF data.
183
	 */
184
	state->spf_sess_data = SPF_request_new(spf_global_server);
185
	if (state->spf_sess_data == NULL)
186
		msg_fatal("%s: failed to create SPF session data structure",
187
				myname);
188
189
	state->spf_header = NULL;
190
191
	/*
192
	 * Pass client address to libspf2.
193
	 */
194
	if (SPF_request_set_ipv4_str(state->spf_sess_data, state->addr) != 0)
195
		msg_fatal("%s: SPF_request_set_ipv4 failure", myname);
196
197
198
	return 0;
199
}
200
201
202
/* Cleanup after disconnect */
203
void smtpd_spf_sess_reset(SMTPD_STATE *state)
204
{
205
	char   *myname = "smtpd_spf_sess_reset";
206
	
207
	/*
208
	 * Sanity checks.
209
	 */
210
	if (spf_global_server == NULL)
211
		msg_panic("%s: no global SPF data initialized", myname);
212
213
	if (state->spf_sess_data == NULL)
214
		return; /* initialisation is only on demand */
215
	
216
	/*
217
	 * Cleanup SPF session data.
218
	 */
219
	if (state->spf_header != NULL)
220
		myfree(state->spf_header);
221
222
	state->spf_header = NULL;
223
	
224
	SPF_request_free(state->spf_sess_data);
225
226
	state->spf_sess_data = NULL;
227
}
228
229
230
/* Pass HELO/EHLO name to libspf2 */
231
int smtpd_spf_set_helo(SMTPD_STATE *state, const char *name)
232
{
233
	char   *myname = "smtpd_spf_set_helo";
234
235
	/*
236
	 * Sanity checks.
237
	 *
238
	 * 'name' may be NULL, to unset registered HELO. This may
239
	 * even happen when SPF is not initialized yet (SPF init
240
	 * is only on demand).
241
	 */
242
	if (state->spf_sess_data == NULL && name == NULL)
243
		return 0;
244
245
	if (state->spf_sess_data == NULL)
246
		msg_panic("%s: setting SPF HELO with null session",
247
			myname);
248
    
249
	/*
250
	 * Pass the HELO name to libspf2.
251
	 */
252
	if (SPF_request_set_helo_dom(state->spf_sess_data, name) != 0)
253
		msg_fatal("%s: error in SPF_request_set_helo_dom", myname); 
254
255
256
	return 0;
257
}
258
259
260
/* Pass sender (env.from) name to libspf2 */
261
int smtpd_spf_set_from(SMTPD_STATE *state, const char *name)
262
{
263
	char *myname = "smtpd_spf_set_from";
264
265
	/*
266
	 * Pass the envelope sender to libspf2.
267
	 */
268
	if (SPF_request_set_env_from(state->spf_sess_data, state->sender) != 0)
269
		msg_fatal("%s: error in SPF_request_set_env_from", myname);
270
271
	return 0;
272
}
273
274
275
/* Obtain SPF result */
276
int smtpd_spf_result(SMTPD_STATE *state, char **headerp, char **commentp)
277
{
278
	char *myname = "smtpd_spf_result";
279
	int action = SPF_ACTION_UNKNOWN;
280
	SPF_response_t *spf_response = NULL;
281
	int res;
282
	char *res_received_spf;
283
	char *res_smtp_comment;
284
	
285
	/*
286
	 * Obtain SPF result.
287
	 */
288
	res = SPF_request_query_mailfrom(state->spf_sess_data, &spf_response);
289
	if (res != 0)
290
		goto clean_end;
291
292
	res = SPF_response_result(spf_response);
293
	switch (res) {
294
		case SPF_RESULT_PASS:
295
		case SPF_RESULT_SOFTFAIL:
296
		case SPF_RESULT_NEUTRAL:
297
		case SPF_RESULT_NONE:
298
			action = SPF_ACTION_MARK;
299
			break;
300
301
		case SPF_RESULT_FAIL:
302
			action = var_spf_mark_only ? SPF_ACTION_MARK : SPF_ACTION_REJECT;
303
			break;
304
		
305
		default:	
306
			msg_warn("%s: unknown SPF result %d (%s)", myname, res,
307
					SPF_strresult(res));
308
			action = SPF_ACTION_ACCEPT;
309
			break;
310
	}
311
312
	/*
313
	 * Save the output header/comment.
314
	 */
315
	res_received_spf = SPF_response_get_received_spf(spf_response);
316
	res_smtp_comment = SPF_response_get_smtp_comment(spf_response);
317
	
318
	if (headerp != NULL && res_received_spf != NULL)
319
		*headerp = mystrdup(res_received_spf);
320
321
	if (commentp != NULL && res_smtp_comment != NULL)
322
		*commentp = mystrdup(res_smtp_comment);
323
    
324
	/*
325
	 * Cleanup.
326
	 */
327
clean_end:		
328
	SPF_response_free(spf_response);
329
330
	return (action);
331
}
332
(-)postfix-2.3.2/src/smtpd/smtpd_spf.h (+43 lines)
Line 0 Link Here
1
/*++
2
/* NAME
3
/*	smtpd_spf 3h
4
/* SUMMARY
5
/*	SMTP server SPF support
6
/* SYNOPSIS
7
/*	#include <smtpd.h>
8
/*	#include <smtpd_spf.h>
9
/* DESCRIPTION
10
/* .nf
11
12
 /*
13
  * External interface.
14
  */
15
extern void smtpd_spf_init(SMTPD_STATE *);
16
extern int smtpd_spf_sess_init(SMTPD_STATE *);
17
extern void smtpd_spf_sess_reset(SMTPD_STATE *);
18
extern int smtpd_spf_set_helo(SMTPD_STATE *, const char *);
19
extern int smtpd_spf_set_from(SMTPD_STATE *, const char *);
20
extern int smtpd_spf_result(SMTPD_STATE *, char **, char **);
21
22
#define SPF_ACTION_UNKNOWN  0
23
#define SPF_ACTION_ACCEPT   1
24
#define SPF_ACTION_REJECT   2
25
#define SPF_ACTION_MARK     3
26
#define SPF_ACTION_TEMPFAIL 4
27
28
/* LICENSE
29
/* .ad
30
/* .fi
31
/*	The Secure Mailer license must be distributed with this software.
32
/* AUTHOR(S)
33
/* 	Nigel Kukard
34
/* 	E-mail: <nkukard@lbsd.net>
35
/* 
36
/*      Dean C. Strik
37
/*      Department ICT
38
/*      Eindhoven University of Technology
39
/*      P.O. Box 513
40
/*      5600 MB  Eindhoven, Netherlands
41
/*      E-mail: <dean@ipnet6.org>
42
/*--*/
43
(-)postfix-2.3.2/src/smtpd/smtpd_state.c (+7 lines)
Lines 67-72 Link Here
67
#include "smtpd.h"
67
#include "smtpd.h"
68
#include "smtpd_chat.h"
68
#include "smtpd_chat.h"
69
#include "smtpd_sasl_glue.h"
69
#include "smtpd_sasl_glue.h"
70
#include "smtpd_spf.h"
70
71
71
/* smtpd_state_init - initialize after connection establishment */
72
/* smtpd_state_init - initialize after connection establishment */
72
73
Lines 161-166 Link Here
161
    smtpd_peer_init(state);
162
    smtpd_peer_init(state);
162
163
163
    /*
164
    /*
165
     * Initialize SPF connection-specific information.
166
     */
167
    smtpd_spf_init(state);
168
169
    /*
164
     * Initialize xforward information.
170
     * Initialize xforward information.
165
     */
171
     */
166
    smtpd_xforward_init(state);
172
    smtpd_xforward_init(state);
Lines 192-197 Link Here
192
    if (state->protocol)
198
    if (state->protocol)
193
	myfree(state->protocol);
199
	myfree(state->protocol);
194
    smtpd_peer_reset(state);
200
    smtpd_peer_reset(state);
201
    smtpd_spf_sess_reset(state);
195
202
196
    /*
203
    /*
197
     * Buffers that are created on the fly and that may be shared among mail
204
     * Buffers that are created on the fly and that may be shared among mail

Return to bug 165604