# James Couzens <jcouzens@6o4.ca>
#diff -rcpN -C 4 sendmail-8.12.11/sendmail/srvrsmtp.c sendmail-8.12.11.spf/sendmail/srvrsmtp.c > sendmail-8.12.11-libspf.0.25.fixed.diff
*** sendmail-8.12.11/sendmail/srvrsmtp.c	Wed Jan 14 11:13:46 2004
--- sendmail-8.12.11.spf/sendmail/srvrsmtp.c	Tue Jun 15 04:01:11 2004
*************** extern void	tls_set_verify __P((SSL_CTX 
*** 38,45 ****
--- 38,49 ----
  # 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 */
*************** static void	smtp_data __P((SMTP_T *, ENV
*** 373,380 ****
--- 377,407 ----
  		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)
*** 465,472 ****
--- 492,506 ----
  	int np_log = 0;
  # 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(nullserver, d_flags, e)
*** 812,819 ****
--- 846,868 ----
  
  # endif /* _FFR_SMTP_SSL */
  #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:
*** 1870,1877 ****
--- 1919,1938 ----
  			}
  
  			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)
*************** tlsfail:
*** 1884,1891 ****
--- 1945,1964 ----
  				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:
*** 2133,2140 ****
--- 2206,2300 ----
  				*delimptr++ = '\0';
  			if (Errors > 0)
  				sm_exc_raisenew_x(&EtypeQuickAbort, 1);
  
+ #ifdef LIBSPF
+ 
+ 			if ((SPFAction > 0)
+ #if SASL
+ 				&& (authenticating != SASL_IS_AUTH)
+ #endif /* SASL */
+ 				)
+ 			{
+ 				if (peer_info == NULL)
+ 				{
+ 					if ((peer_info = SPF_init(MyHostName, anynet_ntoa(&RealHostAddr),
+ 						SPFExplain, SPFTrustedForwarder, SPFBestGuess,
+ 						SPFTrustedForwarderState, SPFBestGuessState)) == NULL)
+ 					{
+ 						SPF_DIE_NOPEER();
+ 					}
+ 				}
+ 
+ 				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)
*** 3325,3332 ****
--- 3485,3496 ----
  	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
+ 
  #if _FFR_QUARANTINE
  	/* restore connection quarantining */
  	if (smtp->sm_quarmsg == NULL)
  	{
