f3f8d7b56ce5ee419e30e897f6fc33917032f54b
[exim.git] / src / src / spf.c
1 /* $Cambridge: exim/src/src/spf.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6  
7 /* Experimental SPF support.
8    Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004
9    License: GPL */
10    
11 /* Code for calling spf checks via libspf-alt. Called from acl.c. */
12
13 #include "exim.h"
14 #ifdef EXPERIMENTAL_SPF
15
16 /* #include "spf.h" */
17
18 SPF_config_t        spfcid = NULL;
19 SPF_dns_config_t    spfdcid_resolv = NULL;
20 SPF_dns_config_t    spfdcid = NULL;
21
22
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) */
26    
27 int spf_init(uschar *spf_helo_domain, uschar *spf_remote_addr) {
28   uschar *p;
29   
30   /* paranoia */
31   spfcid = NULL;
32   spfdcid_resolv = NULL;
33   spfdcid = NULL;
34   
35   spfcid = SPF_create_config();
36   if ( spfcid == NULL ) {
37     debug_printf("spf: SPF_create_config() failed.\n");
38           return 0;
39   }
40
41   /* set up resolver */
42   spfdcid_resolv = SPF_dns_create_config_resolv(NULL, 0);
43   spfdcid = SPF_dns_create_config_cache(spfdcid_resolv, 8, 0);
44
45   if (spfdcid == NULL) {
46     debug_printf("spf: SPF_dns_create_config_cache() failed.\n");
47     spfcid = NULL;
48     spfdcid_resolv = NULL;
49           return 0;
50   }
51
52   if (SPF_set_ip_str(spfcid, spf_remote_addr)) {
53     debug_printf("spf: SPF_set_ip_str() failed.\n");
54     spfcid = NULL;
55     spfdcid_resolv = NULL;
56           return 0;
57   }
58
59   if (SPF_set_helo_dom(spfcid, spf_helo_domain)) {
60     debug_printf("spf: SPF_set_helo_dom() failed.\n");
61     spfcid = NULL;
62     spfdcid_resolv = NULL;
63           return 0;
64   }
65   
66   return 1;
67 }
68
69
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. */
73
74 int spf_process(uschar **listptr, uschar *spf_envelope_sender) {
75   int sep = 0;
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;
81  
82   if (!(spfcid && spfdcid)) {
83     /* no global context, assume temp error and skip to evaluation */
84     rc = SPF_RESULT_ERROR;
85     goto SPF_EVALUATE;
86   };
87
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;
91     goto SPF_EVALUATE;
92   } 
93
94   /* get SPF result */
95   spf_output = SPF_result(spfcid, spfdcid);
96
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;
102
103   rc = spf_output.result;
104
105   /* We got a result. Now see if we should return OK or FAIL for it */
106   SPF_EVALUATE:
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) {
111     int negate = 0;
112     int result = 0;
113
114     /* Check for negation */
115     if (spf_result_id[0] == '!') {
116       negate = 1;
117       spf_result_id++;
118     };
119
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;
124   };
125
126   /* no match */
127   return FAIL;
128 }
129
130 #endif
131