1 /* $Cambridge: exim/src/src/spf.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
7 /* Experimental SPF support.
8 Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
11 /* Code for calling spf checks via libspf-alt. Called from acl.c. */
14 #ifdef EXPERIMENTAL_SPF
16 /* #include "spf.h" */
18 SPF_config_t spfcid = NULL;
19 SPF_dns_config_t spfdcid_resolv = NULL;
20 SPF_dns_config_t spfdcid = NULL;
23 /* spf_init sets up a context that can be re-used for several
24 messages on the same SMTP connection (that come from the
25 same host with the same HELO string) */
27 int spf_init(uschar *spf_helo_domain, uschar *spf_remote_addr) {
32 spfdcid_resolv = NULL;
35 spfcid = SPF_create_config();
36 if ( spfcid == NULL ) {
37 debug_printf("spf: SPF_create_config() failed.\n");
42 spfdcid_resolv = SPF_dns_create_config_resolv(NULL, 0);
43 spfdcid = SPF_dns_create_config_cache(spfdcid_resolv, 8, 0);
45 if (spfdcid == NULL) {
46 debug_printf("spf: SPF_dns_create_config_cache() failed.\n");
48 spfdcid_resolv = NULL;
52 if (SPF_set_ip_str(spfcid, spf_remote_addr)) {
53 debug_printf("spf: SPF_set_ip_str() failed.\n");
55 spfdcid_resolv = NULL;
59 if (SPF_set_helo_dom(spfcid, spf_helo_domain)) {
60 debug_printf("spf: SPF_set_helo_dom() failed.\n");
62 spfdcid_resolv = NULL;
70 /* spf_process adds the envelope sender address to the existing
71 context (if any), retrieves the result, sets up expansion
72 strings and evaluates the condition outcome. */
74 int spf_process(uschar **listptr, uschar *spf_envelope_sender) {
76 uschar *list = *listptr;
77 uschar *spf_result_id;
78 uschar spf_result_id_buffer[128];
79 SPF_output_t spf_output;
80 int rc = SPF_RESULT_ERROR;
82 if (!(spfcid && spfdcid)) {
83 /* no global context, assume temp error and skip to evaluation */
84 rc = SPF_RESULT_ERROR;
88 if (SPF_set_env_from(spfcid, spf_envelope_sender)) {
89 /* Invalid sender address. This should be a real rare occurence */
90 rc = SPF_RESULT_ERROR;
95 spf_output = SPF_result(spfcid, spfdcid);
97 /* set up expansion items */
98 spf_header_comment = spf_output.header_comment ? (uschar *)spf_output.header_comment : NULL;
99 spf_received = spf_output.received_spf ? (uschar *)spf_output.received_spf : NULL;
100 spf_result = (uschar *)SPF_strresult(spf_output.result);
101 spf_smtp_comment = spf_output.smtp_comment ? (uschar *)spf_output.smtp_comment : NULL;
103 rc = spf_output.result;
105 /* We got a result. Now see if we should return OK or FAIL for it */
107 debug_printf("SPF result is %s (%d)\n", SPF_strresult(rc), rc);
108 while ((spf_result_id = string_nextinlist(&list, &sep,
109 spf_result_id_buffer,
110 sizeof(spf_result_id_buffer))) != NULL) {
114 /* Check for negation */
115 if (spf_result_id[0] == '!') {
120 /* Check the result identifier */
121 result = Ustrcmp(spf_result_id, spf_result_id_list[rc].name);
122 if (!negate && result==0) return OK;
123 if (negate && result!=0) return OK;