(1) Last-minute sieve patch (updates to latest spec).
[exim.git] / src / src / spf.c
1 /* $Cambridge: exim/src/src/spf.c,v 1.3 2005/02/17 11:58:26 ph10 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