<%text> diff -Pur postfix-2.1.3/README_FILES/SPF_README postfix-2.1.3+spf2/README_FILES/SPF_README --- postfix-2.1.3/README_FILES/SPF_README Thu Jan 1 01:00:00 1970 +++ postfix-2.1.3+spf2/README_FILES/SPF_README Mon Jul 5 01:26:01 2004 @@ -0,0 +1,78 @@ +Postfix SPF readme +------------------- + +SPF patch by Dean Strik, partly based on Shevek's spfmilter code. +Official site: http://www.ipnet6.org/postfix/spf/ +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.com/. + +To build Postfix, after installing libspf2, use something like: + + % make tidy + % make makefiles CCARGS="-I/usr/local/include" \ + AUXLIBS="-L/usr/local/lib -lspf2" + % make + +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 will invalid sender credentials. +You can however choose to prevent this from happening, and let the mail +pass. 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, Dean Strik, can be +contacted at . + +Site address: downloads and information with regard to this patch can +be found at http://www.ipnet6.org/postfix/spf/ + +Links: + http://spf.pobox.com/ + http://www.libspf2.org/ + +[Dean Strik , 5 Jul 2004] diff -Pur postfix-2.1.3/SPF-ChangeLog postfix-2.1.3+spf2/SPF-ChangeLog --- postfix-2.1.3/SPF-ChangeLog Thu Jan 1 01:00:00 1970 +++ postfix-2.1.3+spf2/SPF-ChangeLog Mon Jul 5 01:35:47 2004 @@ -0,0 +1,10 @@ +ChangeLog for Dean Strik's SPF patch for Postfix (using libspf2). + + http://www.ipnet6.org/postfix/spf/ + +--------------------------------------------------------------------- + +Version 1.0 Postfix version 2.1.3 (LibSPF2 version 1.0.3) + + Initial release. (AKA spf-v016). + diff -Pur postfix-2.1.3/conf/postfix-files postfix-2.1.3+spf2/conf/postfix-files --- postfix-2.1.3/conf/postfix-files Thu Apr 22 19:20:50 2004 +++ postfix-2.1.3+spf2/conf/postfix-files Mon Jul 5 00:38:22 2004 @@ -235,6 +235,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/TUNING_README:f:root:-:644 $readme_directory/ULTRIX_README:f:root:-:644 diff -Pur postfix-2.1.3/src/global/mail_params.h postfix-2.1.3+spf2/src/global/mail_params.h --- postfix-2.1.3/src/global/mail_params.h Wed Apr 21 20:56:04 2004 +++ postfix-2.1.3+spf2/src/global/mail_params.h Mon Jul 5 01:51:09 2004 @@ -1961,6 +1961,35 @@ #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_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.1.3/src/smtpd/Makefile.in postfix-2.1.3+spf2/src/smtpd/Makefile.in --- postfix-2.1.3/src/smtpd/Makefile.in Thu Apr 22 21:37:39 2004 +++ postfix-2.1.3+spf2/src/smtpd/Makefile.in Fri Jul 2 16:50:41 2004 @@ -1,12 +1,12 @@ 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_xforward.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_xforward.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_sasl_glue.h smtpd_proxy.h smtpd_spf.h TESTSRC = smtpd_token_test.c DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) diff -Pur postfix-2.1.3/src/smtpd/smtpd.c postfix-2.1.3+spf2/src/smtpd/smtpd.c --- postfix-2.1.3/src/smtpd/smtpd.c Thu Jun 17 00:40:36 2004 +++ postfix-2.1.3+spf2/src/smtpd/smtpd.c Mon Jul 5 01:24:01 2004 @@ -754,6 +754,12 @@ char *var_xforward_hosts; bool var_smtpd_rej_unl_from; bool var_smtpd_rej_unl_rcpt; +int var_spf_reject_code; +bool var_spf_mark_only; +bool var_spf_rcvd_header; +char *var_spf_local_policy; +char *var_spf_explanation; +bool var_spf_global_whitelist; #ifdef SNAPSHOT int var_smtpd_crate_limit; @@ -886,6 +892,7 @@ chat_reset(state, var_smtpd_hist_thrsh); mail_reset(state); rcpt_reset(state); + smtpd_spf_sess_reset(state); state->helo_name = mystrdup(printable(argv[1].strval, '?')); neuter(state->helo_name, NEUTER_CHARACTERS, '?'); /* Downgrading the protocol name breaks the unauthorized pipelining test. */ @@ -927,6 +934,7 @@ chat_reset(state, var_smtpd_hist_thrsh); mail_reset(state); rcpt_reset(state); + smtpd_spf_sess_reset(state); state->helo_name = mystrdup(printable(argv[1].strval, '?')); neuter(state->helo_name, NEUTER_CHARACTERS, '?'); if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0) { @@ -972,6 +980,7 @@ if (state->helo_name) myfree(state->helo_name); state->helo_name = 0; + smtpd_spf_set_helo(state, NULL); } /* mail_open_stream - open mail queue file or IPC stream */ @@ -1596,6 +1605,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 != (SPF_config_t)0 + && 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. */ @@ -1762,6 +1779,7 @@ saved_err = state->err; chat_reset(state, var_smtpd_hist_thrsh); mail_reset(state); + smtpd_spf_sess_reset(state); rcpt_reset(state); if (why) vstring_free(why); @@ -1788,6 +1806,7 @@ chat_reset(state, var_smtpd_hist_thrsh); mail_reset(state); rcpt_reset(state); + smtpd_spf_sess_reset(state); smtpd_chat_reply(state, "250 Ok"); return (0); } @@ -2707,6 +2726,7 @@ VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0, VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0, VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0, + VAR_SPF_REJECT_CODE, DEF_SPF_REJECT_CODE, &var_spf_reject_code, 0, 0, #ifdef SNAPSHOT VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0, VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0, @@ -2734,6 +2754,9 @@ VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table, VAR_SMTPD_REJ_UNL_FROM, DEF_SMTPD_REJ_UNL_FROM, &var_smtpd_rej_unl_from, VAR_SMTPD_REJ_UNL_RCPT, DEF_SMTPD_REJ_UNL_RCPT, &var_smtpd_rej_unl_rcpt, + 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, 0, }; static CONFIG_STR_TABLE str_table[] = { @@ -2772,6 +2795,8 @@ VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, VAR_XCLIENT_HOSTS, DEF_XCLIENT_HOSTS, &var_xclient_hosts, 0, 0, VAR_XFORWARD_HOSTS, DEF_XFORWARD_HOSTS, &var_xforward_hosts, 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, #ifdef SNAPSHOT VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0, #endif diff -Pur postfix-2.1.3/src/smtpd/smtpd.h postfix-2.1.3+spf2/src/smtpd/smtpd.h --- postfix-2.1.3/src/smtpd/smtpd.h Wed Apr 21 20:23:33 2004 +++ postfix-2.1.3+spf2/src/smtpd/smtpd.h Sun Jul 4 23:00:47 2004 @@ -12,6 +12,9 @@ * System library. */ #include +#include /* for spf2/spf.h */ +#include /* for spf2/spf.h */ +#include /* * SASL library. @@ -123,6 +126,12 @@ ARGV *prepend; /* prepended headers */ VSTRING *instance; /* policy query correlation */ int seqno; /* policy query correlation */ + + /* + * SPF. + */ + SPF_config_t spf_sess_data; /* session specific SPF data */ + char *spf_header; /* SPF header to insert */ /* * Pass-through proxy client. diff -Pur postfix-2.1.3/src/smtpd/smtpd_check.c postfix-2.1.3+spf2/src/smtpd/smtpd_check.c --- postfix-2.1.3/src/smtpd/smtpd_check.c Mon May 3 17:40:13 2004 +++ postfix-2.1.3+spf2/src/smtpd/smtpd_check.c Sun Jul 4 21:21:24 2004 @@ -211,6 +211,7 @@ #include "smtpd.h" #include "smtpd_sasl_glue.h" #include "smtpd_check.h" +#include "smtpd_spf.h" #define RESTRICTION_SEPARATORS ", \t\r\n" @@ -1511,6 +1512,61 @@ return (stat); } +/* reject_ill_spf_sender - check sender validity using SPF records */ + +static int reject_spf_ill_sender(SMTPD_STATE *state, const char *addr, + const char *reply_name, const char *reply_class) +{ + char *myname = "reject_spf_ill_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, + "%d <%s>: %s rejected: %s", + var_spf_reject_code/* XXX: 550 */, 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 <%s>: %s rejected: Unable to look up SPF information", + reply_name, reply_class); + break; + default: + } + + /* + * 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, @@ -3160,6 +3216,10 @@ } else if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) { 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_ill_sender(state, state->sender, state->sender, SMTPD_NAME_SENDER); } else if (strcasecmp(name, REJECT_AUTH_SENDER_LOGIN_MISMATCH) == 0) { #ifdef USE_SASL_AUTH diff -Pur postfix-2.1.3/src/smtpd/smtpd_spf.c postfix-2.1.3+spf2/src/smtpd/smtpd_spf.c --- postfix-2.1.3/src/smtpd/smtpd_spf.c Thu Jan 1 01:00:00 1970 +++ postfix-2.1.3+spf2/src/smtpd/smtpd_spf.c Mon Jul 5 01:52:12 2004 @@ -0,0 +1,333 @@ +/*++ +/* 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) +/* 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 + +/* 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 */ + +/* smtpd_spf_init - initialize global SPF contexts */ + +void smtpd_spf_init(SMTPD_STATE *state) +{ + char *myname = "smtpd_spf_global_init"; + char *policy = NULL; + + /* + * Initialize libspf2 global data. + */ + spf_global_data = SPF_create_config(); + if (spf_global_data == (SPF_config_t)0) + msg_fatal("%s: unable to create SPF configuration data", myname); + if (SPF_set_rec_dom(spf_global_data, var_myhostname) != 0) + msg_fatal("%s: can't set SPF hostname (SPF_set_rec_dom)", myname); + + /* + * Set SPF local policy, if any. + */ + if (var_spf_local_policy != NULL && *var_spf_local_policy != 0) + policy = var_spf_local_policy; + if (policy || var_spf_global_whitelist) { + if (msg_verbose) { + msg_info("%s: setting SPF local policy - %s", + myname, policy ? policy : "(null)"); + msg_info("%s: %sabling global whitelist %s", + myname, var_spf_global_whitelist ? "en" : "dis", + SPF_DEFAULT_WHITELIST); + } + SPF_init_c_results(&spf_local_policy); + if (SPF_compile_local_policy(spf_global_data, policy, + var_spf_global_whitelist, &spf_local_policy)) + msg_fatal("%s: error compiling SPF local policy: %s", + myname, spf_local_policy.err_msg); + SPF_set_local_policy(spf_global_data, spf_local_policy); + } + + /* + * Set custom SPF explanation, if any. + */ + if (var_spf_explanation != NULL && *var_spf_explanation != 0) { + if (msg_verbose) + msg_info("%s: setting SPF explanation string - %s", + myname, var_spf_explanation); + SPF_init_c_results(&spf_explanation); + if (SPF_compile_exp(spf_global_data, var_spf_explanation, + &spf_explanation)) + msg_fatal("%s: error compiling SPF explanation (%s): %s", + myname, VAR_SPF_EXPLANATION, + spf_explanation.err_msg); + SPF_set_exp(spf_global_data, spf_explanation); + } + + /* + * Clear session-specific data (session init is on-demand) + */ + state->spf_sess_data = (SPF_config_t)0; + state->spf_header = NULL; + + /* XXX spf set debug */ + + /* + * Create persistent DNS objects. + */ + spf_resolv_data = SPF_dns_create_config_resolv((SPF_dns_config_t)0, 0); + if (spf_resolv_data == (SPF_dns_config_t)0) + msg_fatal("%s: SPF_dns_create_config_resolv failed", + myname); + spf_resolv_cache = SPF_dns_create_config_cache(spf_resolv_data, + SPF_DNS_CACHE_BITS, /* debug= */ 0); + if (spf_resolv_cache == (SPF_dns_config_t)0) + msg_fatal("%s: SPF_dns_create_config_cache failed", myname); +} + +/* smtpd_spf_sess_init - initialize session dependent SPF context */ + +/* XXX tempfail instead of _fatal? */ +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); /* XXX */ + if (spf_global_data == (SPF_config_t)0) + msg_panic("%s: spf_global_data not initialized", myname); + if (state->spf_sess_data != (SPF_config_t)0) + msg_panic("%s: spf_sess_data non-NULL before allocation", myname); + + /* + * Initialize session-specific SPF data. + */ + state->spf_sess_data = SPF_dup_config(spf_global_data); + if (state->spf_sess_data == (SPF_config_t)0) + msg_fatal("%s: failed to create SPF session data structure", + myname); + state->spf_header = NULL; + + /* + * Pass client address to libspf2. + */ +#ifdef INET6 + /* XXX This isn't very nice... */ + if (SPF_set_ipv6_str(state->spf_sess_data, state->addr)) + /* FALLTHROUGH */ +#endif + if (SPF_set_ipv4_str(state->spf_sess_data, state->addr)) + msg_fatal("%s: SPF_set_ipv4(6) failure", myname); + + return (0); +} + +/* smtpd_spf_sess_reset - cleanup after disconnect */ + +void smtpd_spf_sess_reset(SMTPD_STATE *state) +{ + char *myname = "smtpd_spf_sess_reset"; + + /* + * Sanity checks. + */ + if (spf_global_data == (SPF_config_t)0) + msg_panic("%s: no global SPF data initialized", myname); + if (state->spf_sess_data == (SPF_config_t)0) + return; /* initialisation is only on demand */ + + /* + * Cleanup SPF session data. + */ + if (state->spf_header != NULL) + myfree(state->spf_header); + state->spf_header = 0; + SPF_destroy_config(state->spf_sess_data); + state->spf_sess_data = (SPF_config_t)0; +} + +/* smtpd_spf_set_helo - 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 == (SPF_config_t)0 && name == NULL) + return; + if (state->spf_sess_data == (SPF_config_t)0) + msg_panic("%s: setting SPF HELO with null session", + myname); + + /* + * Pass the HELO name to libspf2. + */ + if (SPF_set_helo_dom(state->spf_sess_data, name) != 0) + msg_fatal("%s: error in SPF_set_helo_dom", myname); /* XXX */ + + return (0); +} + +/* smtpd_spf_set_from - 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_set_env_from(state->spf_sess_data, state->sender) != 0) + msg_fatal("%s: error in SPF_set_env_from", myname); + + return (0); +} + +/* smtpd_spf_result - obtain SPF result */ + +int smtpd_spf_result(SMTPD_STATE *state, char **headerp, char **commentp) +{ + char *myname = "smtpd_spf_result"; + int action; + SPF_output_t spf_out; + + /* + * Obtain SPF result. + */ + spf_out = SPF_result(state->spf_sess_data, spf_resolv_cache); + if (msg_verbose) + msg_info("%s: SPF result type %d: %s", myname, + spf_out.result, + SPF_strresult(spf_out.result)); + switch (spf_out.result) { + 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, spf_out.result, + SPF_strresult(spf_out.result)); + action = SPF_ACTION_ACCEPT; + } + + /* + * Save the output header/comment. + */ + if (headerp != NULL && spf_out.received_spf != NULL) + *headerp = mystrdup(spf_out.received_spf); + if (commentp != NULL && spf_out.smtp_comment != NULL) + *commentp = mystrdup(spf_out.smtp_comment); + + /* + * Cleanup. + */ + SPF_free_output(&spf_out); + + return (action); +} + diff -Pur postfix-2.1.3/src/smtpd/smtpd_spf.h postfix-2.1.3+spf2/src/smtpd/smtpd_spf.h --- postfix-2.1.3/src/smtpd/smtpd_spf.h Thu Jan 1 01:00:00 1970 +++ postfix-2.1.3+spf2/src/smtpd/smtpd_spf.h Sat Jul 3 04:07:17 2004 @@ -0,0 +1,40 @@ +/*++ +/* 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) +/* Dean C. Strik +/* Department ICT +/* Eindhoven University of Technology +/* P.O. Box 513 +/* 5600 MB Eindhoven, Netherlands +/* E-mail: +/*--*/ + diff -Pur postfix-2.1.3/src/smtpd/smtpd_state.c postfix-2.1.3+spf2/src/smtpd/smtpd_state.c --- postfix-2.1.3/src/smtpd/smtpd_state.c Wed Apr 21 20:23:49 2004 +++ postfix-2.1.3+spf2/src/smtpd/smtpd_state.c Fri Jul 2 18:36:25 2004 @@ -59,6 +59,7 @@ #include "smtpd.h" #include "smtpd_chat.h" #include "smtpd_sasl_glue.h" +#include "smtpd_spf.h" /* smtpd_state_init - initialize after connection establishment */ @@ -125,6 +126,11 @@ smtpd_peer_init(state); /* + * Initialize SPF connection-specific information. + */ + smtpd_spf_init(state); + + /* * Initialize xforward information. */ smtpd_xforward_init(state); @@ -150,6 +156,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