diff -Pur postfix-2.3.2/README_FILES/SPF_README postfix-2.3.2_patched/README_FILES/SPF_README --- postfix-2.3.2/README_FILES/SPF_README 1970-01-01 01:00:00.000000000 +0100 +++ postfix-2.3.2_patched/README_FILES/SPF_README 2006-08-19 03:26:21.000000000 +0200 @@ -0,0 +1,88 @@ +Postfix SPF readme +------------------- + +SPF patch for libspf2 >= 1.2.0 by Nigel Kukard, partly based on work +by Dean Strik's and Jef Poskanzer's spfmilter + +Official site: http://www.linuxrulz.org/nkukard/postfix/ +License: Secure Mailer License (Postfix License) + +---- + +This document describes how to configure Postfix to use SPF ("Sender +Policy Framework") validation. It does not describe the function or +design of SPF itself. Refer to one or more of the websites listed at +the end of this text for more information. + +The actual SPF validation is offloaded to a special library called +libspf2. It is therefore necessary that you install libspf2 on your +system. You can find libspf2 either in your usual package repository or +at http://www.libspf2.org/. + +To build Postfix, after installing libspf2, use something like: + + % make tidy + % make makefiles CCARGS="-I/usr/local/include -DHAVE_NS_TYPE" \ + AUXLIBS="-L/usr/local/lib -lspf2" + % make + +-DHAVE_NS_TYPE is only needed if your system complains about ns_type +conflicting. + +The pathnames here are the default pathnames used by libspf2's +installation procedure, which is not documented here. + +SPF sender validation is implemented using a standard Postfix +restriction, called "reject_spf_invalid_sender". This means that you +can put this restriction in e.g. your smtpd_recipient_restrictions. +For more information on how to do this, consult your Postfix +documentation. + +Postfix will by default add a mail header, Received-SPF:, to any mail +passing the SPF validation. This information can be useful for the +recipient of the message. You can disable this behaviour by setting +'spf_received_header = no'. + +By default, Postfix will reject mail with invalid sender credentials. +You can however choose to prevent this from happening, and let the mail +pass, by setting 'spf_mark_only = yes'. The Received-SPF: header +(if enabled, see above) will show that the mail failed the test. + +You can set the numerical SMTP response code when rejecting mails +due to SPF rule violations by changing the value of the +'spf_reject_code' variable (default: 550). + +If a site does provide SPF DNS records yet no explanation, a generic +explanation will be used, with a URL to visit for more information. +You can override this generic explanation by setting the spf_explanation +setting, e.g.: + + spf_explanation = "%{h} [%{i}] is not allowed to send mail for %{s}" + +See the SPF reference sites for information about the format used. + +It is also possible to set a local policy using the spf_local_policy +setting. Currently the format is not documented here. + +There exists a global SPF whitelist on trusted-forwarder.org. You can +enable use of this global whitelist by setting the variable +'spf_global_whitelist = yes'. + +---- + +Bugs/problems/reports: the author of this patch, Nigel Kukard, can be +contacted at . If reporting a problem, please send +the output of + postconf -d spf_patch_version spf_libspf2_version +with your report. + +Downloads and information with regard to this patch can be found at +http://www.lbsd.net/~nkukard/postfix/ + +Links: + http://www.ipnet6.org/postfix/spf/ - Original patch home + http://spf.pobox.com/ - SPF background + http://www.libspf2.org/ - LibSPF2 site + http://www.trusted-forwarder.org/ - Global whitelist + http://www.postfix.org/ - Postfix home page + diff -Pur postfix-2.3.2/conf/postfix-files postfix-2.3.2_patched/conf/postfix-files --- postfix-2.3.2/conf/postfix-files 2006-07-20 03:01:07.000000000 +0200 +++ postfix-2.3.2_patched/conf/postfix-files 2006-08-19 03:26:21.000000000 +0200 @@ -262,6 +262,7 @@ $readme_directory/SMTPD_ACCESS_README:f:root:-:644 $readme_directory/SMTPD_POLICY_README:f:root:-:644 $readme_directory/SMTPD_PROXY_README:f:root:-:644 +$readme_directory/SPF_README:f:root:-:644 $readme_directory/STANDARD_CONFIGURATION_README:f:root:-:644 $readme_directory/TLS_README:f:root:-:644 $readme_directory/TUNING_README:f:root:-:644 diff -Pur postfix-2.3.2/src/global/mail_params.h postfix-2.3.2_patched/src/global/mail_params.h --- postfix-2.3.2/src/global/mail_params.h 2006-07-27 02:59:10.000000000 +0200 +++ postfix-2.3.2_patched/src/global/mail_params.h 2006-08-19 03:26:21.000000000 +0200 @@ -2505,6 +2505,39 @@ #define CHECK_POLICY_SERVICE "check_policy_service" /* + * SPF support. + */ +#define REJECT_ILL_SPF_SENDER "reject_spf_invalid_sender" + +#define VAR_SPF_REJECT_CODE "spf_reject_code" +#define DEF_SPF_REJECT_CODE 550 +extern int var_spf_reject_code; + +#define VAR_SPF_REJECT_DSN "spf_reject_dsn" +#define DEF_SPF_REJECT_DSN "5.7.1" +extern char *var_spf_reject_dsn; + +#define VAR_SPF_MARK_ONLY "spf_mark_only" +#define DEF_SPF_MARK_ONLY 0 +extern bool var_spf_mark_only; + +#define VAR_SPF_RCVD_HEADER "spf_received_header" +#define DEF_SPF_RCVD_HEADER 1 +extern bool var_spf_rcvd_header; + +#define VAR_SPF_LOCAL_POLICY "spf_local_policy" +#define DEF_SPF_LOCAL_POLICY "" +extern char *var_spf_local_policy; + +#define VAR_SPF_EXPLANATION "spf_explanation" +#define DEF_SPF_EXPLANATION "" +extern char *var_spf_explanation; + +#define VAR_SPF_GLOBAL_WHITELIST "spf_global_whitelist" +#define DEF_SPF_GLOBAL_WHITELIST 0 +extern bool var_spf_global_whitelist; + + /* * Client rate control. */ #define VAR_SMTPD_CRATE_LIMIT "smtpd_client_connection_rate_limit" diff -Pur postfix-2.3.2/src/global/mail_version.h postfix-2.3.2_patched/src/global/mail_version.h --- postfix-2.3.2/src/global/mail_version.h 2006-07-27 18:46:58.000000000 +0200 +++ postfix-2.3.2_patched/src/global/mail_version.h 2006-08-19 03:26:21.000000000 +0200 @@ -47,6 +47,13 @@ #define DEF_MAIL_RELEASE MAIL_RELEASE_DATE extern char *var_mail_release; +/* + * SPF patch version. + */ +#define VAR_SPF_PVERSION "spf_patch_version" +#define DEF_SPF_PVERSION "1.0.0" +extern char *var_spf_version; + /* LICENSE /* .ad /* .fi diff -Pur postfix-2.3.2/src/smtpd/Makefile.in postfix-2.3.2_patched/src/smtpd/Makefile.in --- postfix-2.3.2/src/smtpd/Makefile.in 2006-07-09 19:45:31.000000000 +0200 +++ postfix-2.3.2_patched/src/smtpd/Makefile.in 2006-08-19 03:26:21.000000000 +0200 @@ -1,12 +1,13 @@ SHELL = /bin/sh SRCS = smtpd.c smtpd_token.c smtpd_check.c smtpd_chat.c smtpd_state.c \ smtpd_peer.c smtpd_sasl_proto.c smtpd_sasl_glue.c smtpd_proxy.c \ - smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c + smtpd_xforward.c smtpd_dsn_fix.c smtpd_milter.c smtpd_spf.c OBJS = smtpd.o smtpd_token.o smtpd_check.o smtpd_chat.o smtpd_state.o \ smtpd_peer.o smtpd_sasl_proto.o smtpd_sasl_glue.o smtpd_proxy.o \ - smtpd_xforward.o smtpd_dsn_fix.o smtpd_milter.o + smtpd_xforward.o smtpd_dsn_fix.o smtpd_milter.o smtpd_spf.o HDRS = smtpd_token.h smtpd_check.h smtpd_chat.h smtpd_sasl_proto.h \ - smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h smtpd_milter.h + smtpd_sasl_glue.h smtpd_proxy.h smtpd_dsn_fix.h smtpd_milter.h \ + smtpd_spf.h TESTSRC = smtpd_token_test.c DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) diff -Pur postfix-2.3.2/src/smtpd/smtpd.c postfix-2.3.2_patched/src/smtpd/smtpd.c --- postfix-2.3.2/src/smtpd/smtpd.c 2006-07-27 02:47:39.000000000 +0200 +++ postfix-2.3.2_patched/src/smtpd/smtpd.c 2006-08-19 03:27:16.000000000 +0200 @@ -948,6 +948,7 @@ #include #include #include +#include #include #include @@ -1052,6 +1053,15 @@ char *var_smtpd_ehlo_dis_words; char *var_smtpd_ehlo_dis_maps; +bool var_spf_mark_only; +int var_spf_reject_code; +char *var_spf_reject_dsn; +bool var_spf_rcvd_header; + +char *var_spf_local_policy; +char *var_spf_explanation; +bool var_spf_global_whitelist; + char *var_smtpd_tls_level; bool var_smtpd_use_tls; bool var_smtpd_enforce_tls; @@ -2130,6 +2140,7 @@ #ifdef DELAY_ACTION state->saved_delay = 0; #endif + smtpd_spf_sess_reset(state); #ifdef USE_SASL_AUTH if (var_smtpd_sasl_enable) smtpd_sasl_mail_reset(state); @@ -2531,6 +2542,14 @@ out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp); /* + * Prepend Received-SPF header. The header (name,value) has been + * constructed before in the SPF handler (if SPF is enabled). + */ + if (var_spf_rcvd_header && state->spf_sess_data != NULL + && state->spf_header) + out_fprintf(out_stream, REC_TYPE_NORM, "%s", state->spf_header); + + /* * Suppress our own Received: header in the unlikely case that we are an * intermediate proxy. */ @@ -4415,6 +4434,7 @@ VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0, VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0, VAR_SMTPD_CNTLS_LIMIT, DEF_SMTPD_CNTLS_LIMIT, &var_smtpd_cntls_limit, 0, 0, + VAR_SPF_REJECT_CODE, DEF_SPF_REJECT_CODE, &var_spf_reject_code, 0, 0, #ifdef USE_TLS VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0, VAR_SMTPD_TLS_LOGLEVEL, DEF_SMTPD_TLS_LOGLEVEL, &var_smtpd_tls_loglevel, 0, 0, @@ -4454,6 +4474,9 @@ VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls, VAR_SMTPD_ENFORCE_TLS, DEF_SMTPD_ENFORCE_TLS, &var_smtpd_enforce_tls, VAR_SMTPD_TLS_WRAPPER, DEF_SMTPD_TLS_WRAPPER, &var_smtpd_tls_wrappermode, + VAR_SPF_MARK_ONLY, DEF_SPF_MARK_ONLY, &var_spf_mark_only, + VAR_SPF_RCVD_HEADER, DEF_SPF_RCVD_HEADER, &var_spf_rcvd_header, + VAR_SPF_GLOBAL_WHITELIST, DEF_SPF_GLOBAL_WHITELIST, &var_spf_global_whitelist, #ifdef USE_TLS VAR_SMTPD_TLS_AUTH_ONLY, DEF_SMTPD_TLS_AUTH_ONLY, &var_smtpd_tls_auth_only, VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert, @@ -4507,6 +4530,9 @@ VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients, 0, 0, VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0, VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0, + VAR_SPF_LOCAL_POLICY, DEF_SPF_LOCAL_POLICY, &var_spf_local_policy, 0, 0, + VAR_SPF_EXPLANATION, DEF_SPF_EXPLANATION, &var_spf_explanation, 0, 0, + VAR_SPF_REJECT_DSN, DEF_SPF_REJECT_DSN, &var_spf_reject_dsn, 0, 0, #ifdef USE_TLS VAR_RELAY_CCERTS, DEF_RELAY_CCERTS, &var_smtpd_relay_ccerts, 0, 0, VAR_SMTPD_SASL_TLS_OPTS, DEF_SMTPD_SASL_TLS_OPTS, &var_smtpd_sasl_tls_opts, 0, 0, diff -Pur postfix-2.3.2/src/smtpd/smtpd.h postfix-2.3.2_patched/src/smtpd/smtpd.h --- postfix-2.3.2/src/smtpd/smtpd.h 2006-07-22 02:47:28.000000000 +0200 +++ postfix-2.3.2_patched/src/smtpd/smtpd.h 2006-08-19 03:26:21.000000000 +0200 @@ -13,6 +13,10 @@ */ #include #include +#include /* for spf2/spf.h */ +#include /* for spf2/spf.h */ +#include /* for spf2/spf.h */ +#include /* * Utility library. @@ -148,6 +152,12 @@ VSTRING *dsn_orcpt_buf; /* scratch space for ORCPT parsing */ /* + * SPF. + */ + SPF_request_t *spf_sess_data; /* session specific SPF data */ + char *spf_header; /* SPF header to insert */ + + /* * Pass-through proxy client. */ VSTREAM *proxy; /* proxy handle */ diff -Pur postfix-2.3.2/src/smtpd/smtpd_check.c postfix-2.3.2_patched/src/smtpd/smtpd_check.c --- postfix-2.3.2/src/smtpd/smtpd_check.c 2006-07-07 22:32:43.000000000 +0200 +++ postfix-2.3.2_patched/src/smtpd/smtpd_check.c 2006-08-19 03:26:21.000000000 +0200 @@ -244,6 +244,7 @@ #include "smtpd_sasl_glue.h" #include "smtpd_check.h" #include "smtpd_dsn_fix.h" +#include "smtpd_spf.h" #define RESTRICTION_SEPARATORS ", \t\r\n" @@ -1725,6 +1726,67 @@ return (stat); } +/* reject_spf_invalid_sender - check sender validity using SPF records */ + +static int reject_spf_invalid_sender(SMTPD_STATE *state, const char *addr, + const char *reply_name, const char *reply_class) +{ + char *myname = "reject_spf_invalid_sender"; + char *comment; + int action, stat; + + /* + * Currently, this is the only place where SPF routines are used. + * It therefore makes little sense to initialize the SPF data + * before now. + */ + smtpd_spf_sess_init(state); + smtpd_spf_set_helo(state, state->helo_name); + smtpd_spf_set_from(state, state->sender); + + /* + * Obtain SPF result. + */ + comment = NULL; + action = smtpd_spf_result(state, + (var_spf_rcvd_header ? &state->spf_header : NULL), + &comment); + + /* + * Perform actions. + */ + stat = SMTPD_CHECK_DUNNO; + switch (action) { + case SPF_ACTION_REJECT: + stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, + var_spf_reject_code, var_spf_reject_dsn, + "<%s>: %s rejected: %s", + reply_name, reply_class, + (comment ? comment : "SPF policy violation")); + break; + + case SPF_ACTION_TEMPFAIL: + /* XXX log error? */ + DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY, + 450, "4.7.1", + "<%s>: %s rejected: Unable to look up SPF information", + reply_name, reply_class); + break; + + default: + break; + } + + + /* + * Cleanup. + */ + if (comment != NULL) + myfree(comment); + + return (stat); +} + /* reject_unknown_address - fail if address does not resolve */ static int reject_unknown_address(SMTPD_STATE *state, const char *addr, @@ -3670,6 +3732,10 @@ if (state->sender && *state->sender) status = reject_non_fqdn_address(state, state->sender, state->sender, SMTPD_NAME_SENDER); + } else if (strcasecmp(name, REJECT_ILL_SPF_SENDER) == 0) { + if (state->sender && *state->sender) + status = reject_spf_invalid_sender(state, state->sender, + state->sender, SMTPD_NAME_SENDER); } else if (strcasecmp(name, REJECT_AUTH_SENDER_LOGIN_MISMATCH) == 0) { #ifdef USE_SASL_AUTH if (var_smtpd_sasl_enable) { diff -Pur postfix-2.3.2/src/smtpd/smtpd_spf.c postfix-2.3.2_patched/src/smtpd/smtpd_spf.c --- postfix-2.3.2/src/smtpd/smtpd_spf.c 1970-01-01 01:00:00.000000000 +0100 +++ postfix-2.3.2_patched/src/smtpd/smtpd_spf.c 2006-08-19 03:26:21.000000000 +0200 @@ -0,0 +1,332 @@ +/*++ +/* NAME +/* smtpd_spf 3 +/* SUMMARY +/* SMTP server SPF support +/* SYNOPSIS +/* #include +/* #include +/* +/* void smtpd_spf_init(state) +/* SMTPD_STATE *state; +/* +/* int smtpd_spf_sess_init(state) +/* SMTPD_STATE *state; +/* +/* void smtpd_spf_sess_reset(state) +/* SMTPD_STATE *state; +/* +/* int smtpd_spf_set_helo(state, name) +/* SMTPD_STATE *state; +/* char *name; +/* +/* int smtpd_spf_set_from(state, name) +/* SMTPD_STATE *state; +/* char *name; +/* +/* int smtpd_spf_result(state, *header, *comment) +/* SMTPD_STATE *state; +/* char **header; +/* char **comment; +/* +/* DESCRIPTION +/* This modules provides SPF state management functions, +/* making the other SMTP components independent on the +/* actual SPF routines used. +/* +/* smtpd_spf_init() initializes global SPF context. +/* +/* smtpd_spf_sess_init() initializes SPF session context. +/* +/* smtpd_spf_sess_reset() cleans up SPF session context. +/* +/* smtpd_spf_set_helo() passes the client HELO name to +/* the underlying libspf2 context. +/* +/* smtpd_spf_set_from() passes the SMTP envelope sender +/* to the underlying libspf2 context. +/* +/* smtpd_spf_result() performs (via libspf2) the SPF lookups +/* and handling, and creates a Received-SPF header. +/* +/* Arguments: +/* .IP state +/* Session context. +/* .IP name +/* The value to set in the low-level SPF context. +/* DIAGNOSTICS +/* Panic: interface violations. Fatal errors: out of memory. +/* internal protocol errors. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Nigel Kukard +/* E-mail: +/* +/* Dean C. Strik +/* Department ICT +/* Eindhoven University of Technology +/* P.O. Box 513 +/* 5600 MB Eindhoven, Netherlands +/* E-mail: +/*--*/ + + +/* System library. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global library */ +#include +#include +#include + +/* Application library */ +#include "smtpd.h" +#include "smtpd_spf.h" + +#define SPF_DNS_CACHE_BITS 8 + +//static SPF_config_t spf_global_data; /* common SPF configuration data */ +//static SPF_dns_config_t spf_resolv_data; /* SPF DNS resolver data */ +//static SPF_dns_config_t spf_resolv_cache; /* SPF DNS resolver cache */ +//static SPF_c_results_t spf_local_policy; /* compiled local policy */ +//static SPF_c_results_t spf_explanation; /* custom explanation */ + +static SPF_server_t *spf_global_server; + + +/* Initialize global SPF context */ +void smtpd_spf_init(SMTPD_STATE *state) +{ + char *myname = "smtpd_spf_global_init"; + SPF_response_t *spf_response; + int res; + + + /* + * Initialize libspf2 server + */ + spf_global_server = SPF_server_new(SPF_DNS_CACHE, 0); + if (spf_global_server == NULL) + msg_fatal("%s: unable to create SPF server", myname); + + if (SPF_server_set_rec_dom(spf_global_server, var_myhostname) != 0) + msg_fatal("%s: can't set SPF hostname", myname); + + if (var_spf_explanation != NULL && *var_spf_explanation != 0) + { + res = SPF_server_set_explanation(spf_global_server, var_spf_explanation, + &spf_response); + SPF_response_free(spf_response); + if (res != 0) + { + msg_fatal("%s: can't set SPF explanation", myname); + } + } + + if (var_spf_local_policy != NULL && *var_spf_local_policy != 0) + { + res = SPF_server_set_localpolicy(spf_global_server, var_spf_local_policy, 0, + &spf_response); + SPF_response_free(spf_response); + if (res != 0) + { + msg_fatal("%s: can't set SPF local policy", myname); + } + } + + /* + * Clear session-specific data (session init is on-demand) + */ + state->spf_sess_data = NULL; + state->spf_header = NULL; +} + + +/* Initialize session dependent SPF context */ +int smtpd_spf_sess_init(SMTPD_STATE *state) +{ + char *myname = "smtpd_spf_init_sess_data"; + + + /* + * Sanity checks. + */ + if (state->addr == 0) + msg_panic("%s: client address not initialized", myname); + if (spf_global_server == NULL) + msg_panic("%s: spf_global_server not initialized", myname); + + /* + * This code is recipient-independent. SPF session data is + * already initialized if there have been earlier RCPT TO + * commands in this transaction, and we're done. + * XXX: make the code recipient-dependent (restriction classes) + */ + if (state->spf_sess_data != NULL) + return 0; + + /* + * Initialize session-specific SPF data. + */ + state->spf_sess_data = SPF_request_new(spf_global_server); + if (state->spf_sess_data == NULL) + msg_fatal("%s: failed to create SPF session data structure", + myname); + + state->spf_header = NULL; + + /* + * Pass client address to libspf2. + */ + if (SPF_request_set_ipv4_str(state->spf_sess_data, state->addr) != 0) + msg_fatal("%s: SPF_request_set_ipv4 failure", myname); + + + return 0; +} + + +/* Cleanup after disconnect */ +void smtpd_spf_sess_reset(SMTPD_STATE *state) +{ + char *myname = "smtpd_spf_sess_reset"; + + /* + * Sanity checks. + */ + if (spf_global_server == NULL) + msg_panic("%s: no global SPF data initialized", myname); + + if (state->spf_sess_data == NULL) + return; /* initialisation is only on demand */ + + /* + * Cleanup SPF session data. + */ + if (state->spf_header != NULL) + myfree(state->spf_header); + + state->spf_header = NULL; + + SPF_request_free(state->spf_sess_data); + + state->spf_sess_data = NULL; +} + + +/* Pass HELO/EHLO name to libspf2 */ +int smtpd_spf_set_helo(SMTPD_STATE *state, const char *name) +{ + char *myname = "smtpd_spf_set_helo"; + + /* + * Sanity checks. + * + * 'name' may be NULL, to unset registered HELO. This may + * even happen when SPF is not initialized yet (SPF init + * is only on demand). + */ + if (state->spf_sess_data == NULL && name == NULL) + return 0; + + if (state->spf_sess_data == NULL) + msg_panic("%s: setting SPF HELO with null session", + myname); + + /* + * Pass the HELO name to libspf2. + */ + if (SPF_request_set_helo_dom(state->spf_sess_data, name) != 0) + msg_fatal("%s: error in SPF_request_set_helo_dom", myname); + + + return 0; +} + + +/* Pass sender (env.from) name to libspf2 */ +int smtpd_spf_set_from(SMTPD_STATE *state, const char *name) +{ + char *myname = "smtpd_spf_set_from"; + + /* + * Pass the envelope sender to libspf2. + */ + if (SPF_request_set_env_from(state->spf_sess_data, state->sender) != 0) + msg_fatal("%s: error in SPF_request_set_env_from", myname); + + return 0; +} + + +/* Obtain SPF result */ +int smtpd_spf_result(SMTPD_STATE *state, char **headerp, char **commentp) +{ + char *myname = "smtpd_spf_result"; + int action = SPF_ACTION_UNKNOWN; + SPF_response_t *spf_response = NULL; + int res; + char *res_received_spf; + char *res_smtp_comment; + + /* + * Obtain SPF result. + */ + res = SPF_request_query_mailfrom(state->spf_sess_data, &spf_response); + if (res != 0) + goto clean_end; + + res = SPF_response_result(spf_response); + switch (res) { + case SPF_RESULT_PASS: + case SPF_RESULT_SOFTFAIL: + case SPF_RESULT_NEUTRAL: + case SPF_RESULT_NONE: + action = SPF_ACTION_MARK; + break; + + case SPF_RESULT_FAIL: + action = var_spf_mark_only ? SPF_ACTION_MARK : SPF_ACTION_REJECT; + break; + + default: + msg_warn("%s: unknown SPF result %d (%s)", myname, res, + SPF_strresult(res)); + action = SPF_ACTION_ACCEPT; + break; + } + + /* + * Save the output header/comment. + */ + res_received_spf = SPF_response_get_received_spf(spf_response); + res_smtp_comment = SPF_response_get_smtp_comment(spf_response); + + if (headerp != NULL && res_received_spf != NULL) + *headerp = mystrdup(res_received_spf); + + if (commentp != NULL && res_smtp_comment != NULL) + *commentp = mystrdup(res_smtp_comment); + + /* + * Cleanup. + */ +clean_end: + SPF_response_free(spf_response); + + return (action); +} + diff -Pur postfix-2.3.2/src/smtpd/smtpd_spf.h postfix-2.3.2_patched/src/smtpd/smtpd_spf.h --- postfix-2.3.2/src/smtpd/smtpd_spf.h 1970-01-01 01:00:00.000000000 +0100 +++ postfix-2.3.2_patched/src/smtpd/smtpd_spf.h 2006-08-19 03:26:21.000000000 +0200 @@ -0,0 +1,43 @@ +/*++ +/* NAME +/* smtpd_spf 3h +/* SUMMARY +/* SMTP server SPF support +/* SYNOPSIS +/* #include +/* #include +/* DESCRIPTION +/* .nf + + /* + * External interface. + */ +extern void smtpd_spf_init(SMTPD_STATE *); +extern int smtpd_spf_sess_init(SMTPD_STATE *); +extern void smtpd_spf_sess_reset(SMTPD_STATE *); +extern int smtpd_spf_set_helo(SMTPD_STATE *, const char *); +extern int smtpd_spf_set_from(SMTPD_STATE *, const char *); +extern int smtpd_spf_result(SMTPD_STATE *, char **, char **); + +#define SPF_ACTION_UNKNOWN 0 +#define SPF_ACTION_ACCEPT 1 +#define SPF_ACTION_REJECT 2 +#define SPF_ACTION_MARK 3 +#define SPF_ACTION_TEMPFAIL 4 + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Nigel Kukard +/* E-mail: +/* +/* Dean C. Strik +/* Department ICT +/* Eindhoven University of Technology +/* P.O. Box 513 +/* 5600 MB Eindhoven, Netherlands +/* E-mail: +/*--*/ + diff -Pur postfix-2.3.2/src/smtpd/smtpd_state.c postfix-2.3.2_patched/src/smtpd/smtpd_state.c --- postfix-2.3.2/src/smtpd/smtpd_state.c 2006-07-22 03:50:42.000000000 +0200 +++ postfix-2.3.2_patched/src/smtpd/smtpd_state.c 2006-08-19 03:26:21.000000000 +0200 @@ -67,6 +67,7 @@ #include "smtpd.h" #include "smtpd_chat.h" #include "smtpd_sasl_glue.h" +#include "smtpd_spf.h" /* smtpd_state_init - initialize after connection establishment */ @@ -161,6 +162,11 @@ smtpd_peer_init(state); /* + * Initialize SPF connection-specific information. + */ + smtpd_spf_init(state); + + /* * Initialize xforward information. */ smtpd_xforward_init(state); @@ -192,6 +198,7 @@ if (state->protocol) myfree(state->protocol); smtpd_peer_reset(state); + smtpd_spf_sess_reset(state); /* * Buffers that are created on the fly and that may be shared among mail