*** sendmail-8.13.1/cf/m4/proto.m4	Tue Jul 27 19:32:48 2004
--- sendmail-8.13.1.spf/cf/m4/proto.m4	Sun Aug 22 11:27:37 2004
*************** _OPTION(TLSSrvOptions, `confTLS_SRV_OPTI
*** 640,647 ****
--- 640,675 ----
  
  # Input mail filters
  _OPTION(InputMailFilters, `confINPUT_MAIL_FILTERS', `')
  
+ # SPFAction
+ _OPTION(SPFAction, `confSPFAction', `1')
+ 
+ # SPFHeaderState
+ _OPTION(SPFHeaderState, `confSPFHeaderState', `True')
+ 
+ # SPFBestGuessState
+ _OPTION(SPFBestGuessState, `confSPFBestGuessState', `0')
+ 
+ # SPFTrustedForwarderState
+ _OPTION(SPFTrustedForwarderState, `confSPFTrustedForwarderState', `0')
+ 
+ # SPFExplainState
+ _OPTION(SPFExplainState, `confSPFExplainState', `True')
+ 
+ # SPFBestGuess
+ _OPTION(SPFBestGuess, `confSPFBestGuess', `v=spf1 a/24 mx/24 ptr')
+ 
+ # SPFTrustedForwarder
+ _OPTION(SPFTrustedForwarder, `confSPFTrustedForwarder', `v=spf1 include:spf.trusted-forwarder.org')
+ 
+ # SPFExplain
+ _OPTION(SPFExplain, `confSPFExplain', `See http://spf.pobox.com/why.html?sender=%{S}&ip=%{I}&receiver=%{xR}')
+ 
+ # SPFDebug
+ _OPTION(SPFDebug, `confSPFDebug', `0')
+ 
+ 
  ifelse(len(X`'_MAIL_FILTERS_DEF), `1', `dnl', `dnl
  # Milter options
  _OPTION(Milter.LogLevel, `confMILTER_LOG_LEVEL', `')
  _OPTION(Milter.macros.connect, `confMILTER_MACROS_CONNECT', `')
*************** ifdef(`confTRUSTED_USERS', `T`'confTRUST
*** 701,708 ****
--- 729,737 ----
  
  ifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `$?x$x <$g>$|$g$.')')dnl
  ifdef(`confMESSAGEID_HEADER',, `define(`confMESSAGEID_HEADER', `<$t.$i@$j>')')dnl
  H?P?Return-Path: <$g>
+ H${spfheader}
  HReceived: confRECEIVED_HEADER
  H?D?Resent-Date: $a
  H?D?Date: $a
  H?F?Resent-From: confFROM_HEADER
*************** undivert(8)
*** 1787,1794 ****
--- 1816,1824 ----
  ###  check_mail -- check SMTP ``MAIL FROM:'' command argument
  ######################################################################
  
  SLocal_check_mail
+ undivert(10)
  Scheck`'_U_`'mail
  R$*			$: $1 $| $>"Local_check_mail" $1
  R$* $| $#$*		$#$2
  R$* $| $*		$@ $>"Basic_check_mail" $1
*** sendmail-8.13.1/sendmail/Makefile.m4	Fri Aug  8 22:31:17 2003
--- sendmail-8.13.1.spf/sendmail/Makefile.m4	Tue Aug 10 09:08:18 2004
*************** bldPRODUCT_START(`executable', `sendmail
*** 6,13 ****
--- 6,15 ----
  define(`bldBIN_TYPE', `G')
  define(`bldINSTALL_DIR', `')
  define(`bldSOURCES', `main.c alias.c arpadate.c bf.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c ratectrl.c readcf.c recipient.c sasl.c savemail.c sfsasl.c shmticklib.c sm_resolve.c srvrsmtp.c stab.c stats.c sysexits.c timers.c tls.c trace.c udb.c usersmtp.c util.c version.c ')
  PREPENDDEF(`confENVDEF', `confMAPDEF')
+ APPENDDEF(`confENVDEF', `-DLIBSPF')
+ APPENDDEF(`confLIBS', `-lspf')
  bldPUSH_SMLIB(`sm')
  bldPUSH_SMLIB(`smutil')
  
  dnl hack: /etc/mail is not defined as "location of .cf" in the build system
*** sendmail-8.13.1/sendmail/srvrsmtp.c	Fri Jul  9 01:29:33 2004
--- sendmail-8.13.1.spf/sendmail/srvrsmtp.c	Sun Aug 22 14:41:34 2004
*************** extern void	tls_set_verify __P((SSL_CTX 
*** 41,48 ****
--- 41,52 ----
  # define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \
  				bitset(SRV_VRFY_CLT, features))
  #endif /* STARTTLS */
  
+ #ifdef LIBSPF
+ #include <spf.h>
+ #endif /* LIBSPF */
+ 
  /* server features */
  #define SRV_NONE	0x0000	/* none... */
  #define SRV_OFFER_TLS	0x0001	/* offer STARTTLS */
  #define SRV_VRFY_CLT	0x0002	/* request a cert */
*************** do								\
*** 426,433 ****
--- 430,460 ----
  		sm_setproctitle(true, e, "%s %s: %.80s",	\
  				qid_printname(e), CurSmtpClient, inp);	\
  	}
  
+ #ifdef LIBSPF
+ 
+ #define SPF_FAILED  "554 transaction failed (SPF)\r\n"
+ #define SPF_SYNTAX  "555 syntax error (#5.5.4)\r\n"
+ 
+ #define SPF_DIE_NOIP()                                  \
+ 	sm_syslog(LOG_ERR, e->e_id, "Die no IP (SPF)");          \
+ 	message("421 unable to store remote ip (SPF)\r\n");   \
+ 	disconnect(1, e);
+ 
+ #define SPF_DIE_NOPEER()                                \
+ 	sm_syslog(LOG_ERR, e->e_id, "Invalid peer structure (SPF)"); \
+ 	message("421 invalid peer structure (SPF)\r\n");      \
+ 	disconnect(1, e);
+ 
+ #define SPF_DIE_NOMEM()                                 \
+ 	sm_syslog(LOG_ERR, e->e_id, "Out of Memory (SPF)");      \
+ 	message("421 out of memory (#4.3.0)\r\n");            \
+ 	disconnect(1, e);
+ 
+ peer_info_t   *peer_info    = NULL; /* peer_info structure */
+ 
+ #endif /* LIBSPF */
  
  void
  smtp(nullserver, d_flags, e)
  	char *volatile nullserver;
*************** smtp(nullserver, d_flags, e)
*** 518,525 ****
--- 545,560 ----
  # endif /* _FFR_NO_PIPE */
  #endif /* PIPELINING */
  	volatile time_t log_delay = (time_t) 0;
  
+ #ifdef LIBSPF
+ 	SPF_RESULT    SPF_RES;  /* spf result holder */
+ 	char *spf_r = NULL;     /* spf result response string */
+ 	char *spf_e = NULL;     /* spf result explanation string */
+ 	char *spf_reject = NULL;/* spf reject as string for sendmail.cf */
+ 	char *spf_hdr = NULL;   /* spf header */
+ #endif /* LIBSPF */
+ 
  	save_sevenbitinput = SevenBitInput;
  	smtp.sm_nrcpts = 0;
  #if MILTER
  	smtp.sm_milterize = (nullserver == NULL);
*************** smtp(nullserver, d_flags, e)
*** 879,886 ****
--- 914,938 ----
  		time_t msecs = 0;
  		char **pvp;
  		char pvpbuf[PSBUFSIZE];
  
+ #ifdef LIBSPF
+ 		if (SPFAction > 0)
+ 		{
+ 			if ((peer_info = SPF_init(MyHostName, anynet_ntoa(&RealHostAddr),
+ 				SPFExplain, SPFTrustedForwarder, SPFBestGuess,
+ 				SPFTrustedForwarderState, SPFBestGuessState)) == NULL)
+ 			{
+ 				sm_syslog(LOG_INFO, e->e_id,
+ 					"SPF_init FAILED with args: (%s) (%s)",
+ 					CurSmtpClient, MyHostName);
+ 					disconnect(1, e);
+ 			}
+ 
+ 			confg.level = SPFDebugState;
+ 		}
+ #endif /* LIBSPF */
+ 
  		/* Ask the rulesets how long to pause */
  		pvp = NULL;
  		r = rscap("greet_pause", peerhostname,
  			  anynet_ntoa(&RealHostAddr), e,
*************** smtp(nullserver, d_flags, e)
*** 937,944 ****
--- 989,1011 ----
    greeting:
  
  #endif /* STARTTLS */
  
+ #ifdef LIBSPF
+ 	if (SPFAction > 0)
+ 	{
+ 		if ((peer_info = SPF_init(MyHostName, anynet_ntoa(&RealHostAddr),
+ 			SPFExplain, SPFTrustedForwarder, SPFBestGuess,
+ 			SPFTrustedForwarderState, SPFBestGuessState)) == NULL)
+ 		{
+ 			sm_syslog(LOG_INFO, e->e_id,
+ 			"SPF_init FAILED with args: (%s) (%s)",
+ 			CurSmtpClient, MyHostName);
+ 			disconnect(1, e);
+ 		}
+ 	}
+ #endif /* LIBSPF */
+ 
  	/* output the first line, inserting "ESMTP" as second word */
  	if (*greetcode == '5')
  		(void) sm_snprintf(inp, sizeof inp, "%s not accepting messages",
  				   hostname);
*************** tlsfail:
*** 1903,1911 ****
  					goto doquit;
  			}
  			break;
  #endif /* STARTTLS */
- 
  		  case CMDHELO:		/* hello -- introduce yourself */
  		  case CMDEHLO:		/* extended hello */
  			DELAY_CONN("EHLO");
  			if (c->cmd_code == CMDEHLO)
--- 1970,1977 ----
*************** tlsfail:
*** 1973,1994 ****
  			}
  
  			if (*q == '\0' && ok)
  			{
  				q = "pleased to meet you";
  				sendinghost = sm_strdup_x(p);
  			}
  			else if (!AllowBogusHELO)
  			{
  				usrerr("501 Invalid domain name");
  				if (LogLevel > 9)
  					sm_syslog(LOG_INFO, CurEnv->e_id,
! 						  "invalid domain name (%s) from %.100s",
! 						  p, CurSmtpClient);
  				break;
  			}
  			else
  			{
  				q = "accepting invalid domain name";
  			}
  
  			if (gothello)
--- 2039,2080 ----
  			}
  
  			if (*q == '\0' && ok)
  			{
+ #ifdef LIBSPF
+ 				if (SPFAction > 0)
+ 				{
+ 					if (peer_info == NULL)
+ 					{
+ 						SPF_DIE_NOPEER();
+ 					}
+ 					SPF_smtp_helo(peer_info, p);
+ 				}
+ #endif /* LIBSPF */
  				q = "pleased to meet you";
  				sendinghost = sm_strdup_x(p);
  			}
  			else if (!AllowBogusHELO)
  			{
  				usrerr("501 Invalid domain name");
  				if (LogLevel > 9)
  					sm_syslog(LOG_INFO, CurEnv->e_id,
! 					"invalid domain name (%s) from %.100s",
! 					p, CurSmtpClient);
  				break;
  			}
  			else
  			{
+ #ifdef LIBSPF
+ 				if (SPFAction > 0)
+ 				{ 
+ 					if (peer_info == NULL)
+ 					{ 
+ 						SPF_DIE_NOPEER();
+ 					}
+ 					SPF_smtp_helo(peer_info, p);
+ 				}
+ #endif /* LIBSPF */
  				q = "accepting invalid domain name";
  			}
  
  			if (gothello)
*************** tlsfail:
*** 2218,2225 ****
--- 2304,2401 ----
  				*delimptr++ = '\0';
  			if (Errors > 0)
  				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
  
+ #ifdef LIBSPF
+ 			if ((SPFAction > 0)
+ #if SASL
+ 				&& (authenticating != SASL_IS_AUTH)
+ #endif
+ 			)
+ 			{
+ 				if (peer_info == NULL)
+ 				{
+ 					if ((peer_info = SPF_init(MyHostName, anynet_ntoa(&RealHostAddr),
+ 						SPFExplain, SPFTrustedForwarder, SPFBestGuess,
+ 						SPFTrustedForwarderState, SPFBestGuessState)) == NULL)
+ 					{
+ 						SPF_DIE_NOPEER();
+ 					}
+ 
+ 					confg.level = SPFDebugState;
+ 				}
+ 
+ 				if (SPF_smtp_from(peer_info, p) == FALSE)
+ 				{
+ 					message(SPF_SYNTAX);
+ 					return;
+ 				}
+ 
+ 				/* get Result of SPF-Check */
+ 				SPF_RES = SPF_policy_main(peer_info);
+ 				if ((spf_r = SPF_result(peer_info)) == NULL)
+ 				{
+ 					SPF_DIE_NOMEM();
+ 				}
+ 				else
+ 				{
+ 					macdefine(&e->e_macro, A_TEMP, macid("{spfresult}"), (char *)spf_r);
+ 					free(spf_r);
+ 				}
+ 
+ 				/* define our macros ${spfreject}, ${spfexplain} and ${spfheader} for sendmail.cf */
+ 				spf_reject = malloc(2);
+ 				*(spf_reject + 1) = 0;
+ 
+ 				switch (SPF_RES)
+ 				{
+ 					case SPF_PASS:
+ 						*spf_reject = '0';
+ 						break;
+ 					case SPF_H_FAIL:
+ 						*spf_reject = (SPFAction > 1 ? '1' : '0');
+ 						break;
+ 					case SPF_S_FAIL:
+ 						*spf_reject = (SPFAction > 2 ? '1' : '0');
+ 						break;
+ 					case SPF_NEUTRAL:
+ 						*spf_reject = (SPFAction > 3 ? '1' : '0');
+ 						break;
+ 					case SPF_NONE:
+ 						*spf_reject = (SPFAction > 4 ? '1' : '0');
+ 						break;
+ 					case SPF_ERROR:
+ 						*spf_reject = (SPFAction > 5 ? '1' : '0');
+ 						break;
+ 					case SPF_UNKNOWN:
+ 						*spf_reject = (SPFAction > 6 ? '1' : '0');
+ 						break;
+ 					case SPF_UNMECH:
+ 						break;
+ 				}
+ 
+ 				macdefine(&e->e_macro, A_TEMP, macid("{spfreject}"), (char *)spf_reject);
+ 				free(spf_reject);
+ 
+ 				if (SPFExplainState == true)
+ 				{
+ 					spf_e = SPF_get_explain(peer_info);
+ 					macdefine(&e->e_macro, A_TEMP, macid("{spfexplain}"), (char *)spf_e);
+ 					free(spf_e);
+ 				}
+ 
+ 				if (SPFHeaderState == true)
+ 				{
+ 					if ((spf_hdr = SPF_build_header(peer_info)) != NULL)
+ 					{
+ 						macdefine(&e->e_macro, A_TEMP, macid("{spfheader}"),
+ 						(char *)spf_hdr);
+ 						free(spf_hdr);
+ 					}
+ 				}
+ 			} /* if (SPFAction > 0){} */
+ #endif /* LIBSPF */
+ 
  			/* Successfully set e_from, allow logging */
  			e->e_flags |= EF_LOGSENDER;
  
  			/* put resulting triple from parseaddr() into macros */
*************** smtp_data(smtp, e)
*** 3545,3552 ****
--- 3721,3732 ----
  
  	CurEnv = e;
  	newenvelope(e, e, sm_rpool_new_x(NULL));
  	e->e_flags = BlankEnvelope.e_flags;
+ 
+ #ifdef LIBSPF
+ 	peer_info = SPF_close(peer_info);
+ #endif /* LIBSPF */
  
  	/* restore connection quarantining */
  	if (smtp->sm_quarmsg == NULL)
  	{
*** sendmail-8.13.1/sendmail/readcf.c	Fri Jul 23 22:45:02 2004
--- sendmail-8.13.1.spf/sendmail/readcf.c	Tue Aug 10 09:08:18 2004
*************** static struct optioninfo
*** 2189,2197 ****
  #if _FFR_HELONAME
  # define O_HELONAME 0xd8
  	{ "HeloName",   O_HELONAME,     OI_NONE },
  #endif /* _FFR_HELONAME */
! 
  	{ NULL,				'\0',		OI_NONE	}
  };
  
  # define CANONIFY(val)
--- 2189,2216 ----
  #if _FFR_HELONAME
  # define O_HELONAME 0xd8
  	{ "HeloName",   O_HELONAME,     OI_NONE },
  #endif /* _FFR_HELONAME */
! #ifdef LIBSPF
! #define O_SPF_ACTION                    0xe0
! 	{ "SPFAction",			O_SPF_ACTION,                   OI_NONE },
! #define O_SPF_HEADER_STATE              0xe1
! 	{ "SPFHeaderState",		O_SPF_HEADER_STATE,             OI_NONE },
! #define O_SPF_BEST_GUESS_STATE          0xe2
! 	{ "SPFBestGuessState",		O_SPF_BEST_GUESS_STATE,         OI_NONE },
! #define O_SPF_BEST_GUESS                0xe3
! 	{ "SPFBestGuess",		O_SPF_BEST_GUESS,               OI_NONE },
! #define O_SPF_TRUSTED_FORWARDER_STATE   0xe4
! 	{ "SPFTrustedForwarderState",	O_SPF_TRUSTED_FORWARDER_STATE,  OI_NONE },
! #define O_SPF_TRUSTED_FORWARDER         0xe5
! 	{ "SPFTrustedForwarder",	O_SPF_TRUSTED_FORWARDER,        OI_NONE },
! #define O_SPF_EXPLAIN_STATE             0xe6
! 	{ "SPFExplainState",		O_SPF_EXPLAIN_STATE,            OI_NONE },
! #define O_SPF_EXPLAIN                   0xe7
! 	{ "SPFExplain",			O_SPF_EXPLAIN,                  OI_NONE },
! #define O_SPF_DEBUG_STATE		0xe8
! 	{"SPFDebugState",		O_SPF_DEBUG_STATE,		OI_NONE },	
! #endif /* LIBSPF */
  	{ NULL,				'\0',		OI_NONE	}
  };
  
  # define CANONIFY(val)
*************** setoption(opt, val, safe, sticky, e)
*** 3693,3700 ****
--- 3712,3757 ----
  #else /* REQUIRES_DIR_FSYNC */
  		/* silently ignored... required for cf file option */
  #endif /* REQUIRES_DIR_FSYNC */
  		break;
+ 
+ #ifdef LIBSPF
+ 	  case O_SPF_ACTION:
+ 	  SPFAction = atoi(val);
+ 	  break;
+ 
+ 	  case O_SPF_HEADER_STATE:
+ 	  SPFHeaderState = atobool(val);
+ 	  break;
+ 
+ 	  case O_SPF_BEST_GUESS_STATE:
+ 	  SPFBestGuessState = atoi(val);
+ 	  break;
+ 
+ 	  case O_SPF_BEST_GUESS:
+ 	  SPFBestGuess = newstr(val);
+ 	  break;
+ 
+ 	  case O_SPF_TRUSTED_FORWARDER_STATE:
+ 	  SPFTrustedForwarderState = atoi(val);
+ 	  break;
+ 
+ 	  case O_SPF_TRUSTED_FORWARDER:
+ 	  SPFTrustedForwarder = newstr(val);
+ 	  break;
+ 
+ 	  case O_SPF_EXPLAIN_STATE:
+ 	  SPFExplainState = atobool(val);
+ 	  break;
+ 
+ 	  case O_SPF_EXPLAIN:
+ 	  SPFExplain = newstr(val);
+ 	  break;
+ 
+ 	  case O_SPF_DEBUG_STATE:
+ 	  SPFDebugState = atoi(val);
+ 	  break;
+ #endif /*LIBSPF */
  
  	  case O_CONNECTION_RATE_WINDOW_SIZE:
  		ConnectionRateWindowSize = convtime(val, 's');
  		break;
*** sendmail-8.13.1/sendmail/sendmail.h	Wed Jul 14 23:54:22 2004
--- sendmail-8.13.1.spf/sendmail/sendmail.h	Tue Aug 10 09:08:18 2004
*************** EXTERN bool	SingleLineFromHeader;	/* for
*** 2173,2181 ****
  EXTERN bool	SingleThreadDelivery;	/* single thread hosts on delivery */
  #if _FFR_SOFT_BOUNCE
  EXTERN bool	SoftBounce;	/* replace 5xy by 4xy (for testing) */
  #endif /* _FFR_SOFT_BOUNCE */
! EXTERN bool	volatile StopRequest;	/* stop sending output */
  EXTERN bool	SuprErrs;	/* set if we are suppressing errors */
  EXTERN bool	TryNullMXList;	/* if we are the best MX, try host directly */
  EXTERN bool	UseMSP;		/* mail submission: group writable queue ok? */
  EXTERN bool	WorkAroundBrokenAAAA;	/* some nameservers return SERVFAIL on AAAA queries */
--- 2173,2192 ----
  EXTERN bool	SingleThreadDelivery;	/* single thread hosts on delivery */
  #if _FFR_SOFT_BOUNCE
  EXTERN bool	SoftBounce;	/* replace 5xy by 4xy (for testing) */
  #endif /* _FFR_SOFT_BOUNCE */
! #ifdef LIBSPF
! EXTERN int	SPFAction;		/* type of Action to take based on SPF result */
! EXTERN bool	SPFHeaderState;		/* prepend header 'Received-SPF:' or not */
! EXTERN u_int32_t SPFBestGuessState;	/* best guess support on or off */
! EXTERN char *SPFBestGuess;		/* SPF query to execute as best guess */
! EXTERN u_int32_t SPFTrustedForwarderState; /* trusted forwarder support on or off */
! EXTERN char	*SPFTrustedForwarder;	/* SPF query to execute as trusted forwarder */
! EXTERN bool	SPFExplainState;	/* provide explanations upon failures */
! EXTERN char	*SPFExplain;		/* string to expand on to generate explanations */
! EXTERN int	SPFDebugState;		/* debug level when compiled --enable-debug */
! #endif /* LIBSPF */
! EXTERN bool	volatile StopRequest;   /* stop sending output */
  EXTERN bool	SuprErrs;	/* set if we are suppressing errors */
  EXTERN bool	TryNullMXList;	/* if we are the best MX, try host directly */
  EXTERN bool	UseMSP;		/* mail submission: group writable queue ok? */
  EXTERN bool	WorkAroundBrokenAAAA;	/* some nameservers return SERVFAIL on AAAA queries */
