libspf2  1.2.11
spf_request.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of either:
4  *
5  * a) The GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 2.1, or (at your option) any
7  * later version,
8  *
9  * OR
10  *
11  * b) The two-clause BSD license.
12  *
13  * These licenses can be found with the distribution in the file LICENSES
14  */
15 
16 #include "spf_sys_config.h"
17 
18 #ifdef STDC_HEADERS
19 # include <stdio.h> /* stdin / stdout */
20 # include <stdlib.h> /* malloc / free */
21 #endif
22 
23 #ifdef HAVE_STRING_H
24 # include <string.h> /* strstr / strdup */
25 #else
26 # ifdef HAVE_STRINGS_H
27 # include <strings.h> /* strstr / strdup */
28 # endif
29 #endif
30 
31 
32 #include "spf.h"
33 #include "spf_dns.h"
34 #include "spf_request.h"
35 #include "spf_internal.h"
36 
37 #define SPF_FREE(x) \
38  do { if (x) free(x); (x) = NULL; } while(0)
39 
40 SPF_request_t *
41 SPF_request_new(SPF_server_t *spf_server)
42 {
43  SPF_request_t *sr;
44 
45  sr = (SPF_request_t *)malloc(sizeof(SPF_request_t));
46  if (! sr)
47  return sr;
48  memset(sr, 0, sizeof(SPF_request_t));
49 
50  sr->spf_server = spf_server;
51  sr->client_ver = AF_UNSPEC;
52  sr->ipv4.s_addr = htonl(INADDR_ANY);
53  sr->ipv6 = in6addr_any;
54 
55  return sr;
56 }
57 
58 void
59 SPF_request_free(SPF_request_t *sr)
60 {
62  SPF_FREE(sr->client_dom);
63  SPF_FREE(sr->helo_dom);
64  SPF_FREE(sr->env_from);
65  SPF_FREE(sr->env_from_lp);
66  SPF_FREE(sr->env_from_dp);
67  free(sr);
68 }
69 
71 SPF_request_set_ipv4(SPF_request_t *sr, struct in_addr addr)
72 {
73  if (sr->client_dom) {
74  free(sr->client_dom);
75  sr->client_dom = NULL;
76  }
77  sr->client_ver = AF_INET;
78  sr->ipv4 = addr;
79  return SPF_E_SUCCESS;
80 }
81 
83 SPF_request_set_ipv6(SPF_request_t *sr, struct in6_addr addr)
84 {
85  if (sr->client_dom) {
86  free(sr->client_dom);
87  sr->client_dom = NULL;
88  }
89  sr->client_ver = AF_INET6;
90  sr->ipv6 = addr;
91  return SPF_E_SUCCESS;
92 }
93 
95 SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
96 {
97  struct in_addr addr;
98  if (astr == NULL)
99  astr = "0.0.0.0";
100  if (inet_pton(AF_INET, astr, &addr) <= 0)
101  return SPF_E_INVALID_IP4;
102  return SPF_request_set_ipv4(sr, addr);
103 }
104 
106 SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
107 {
108  struct in6_addr addr;
109  if (astr == NULL)
110  astr = "::";
111  if (inet_pton(AF_INET6, astr, &addr) <= 0)
112  return SPF_E_INVALID_IP6;
113  return SPF_request_set_ipv6(sr, addr);
114 }
115 
117 SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
118 {
119  SPF_ASSERT_NOTNULL(dom);
120  SPF_FREE(sr->helo_dom);
121  sr->helo_dom = strdup(dom);
122  if (! sr->helo_dom)
123  return SPF_E_NO_MEMORY;
124  /* set cur_dom and env_from? */
125  if (sr->env_from == NULL)
126  return SPF_request_set_env_from(sr, dom);
127  return SPF_E_SUCCESS;
128 }
129 
130 const char *
131 SPF_request_get_rec_dom(SPF_request_t *sr)
132 {
133  SPF_server_t *spf_server;
134  spf_server = sr->spf_server;
135  return spf_server->rec_dom;
136 }
137 
138 int
139 SPF_request_set_env_from(SPF_request_t *sr, const char *from)
140 {
141  char *cp;
142  size_t len;
143 
144  SPF_ASSERT_NOTNULL(from);
145  SPF_FREE(sr->env_from);
146  SPF_FREE(sr->env_from_lp);
147  SPF_FREE(sr->env_from_dp);
148 
149  if (*from == '\0' && sr->helo_dom != NULL)
150  from = sr->helo_dom;
151  cp = strrchr(from, '@');
152  if (cp && (cp != from)) {
153  sr->env_from = strdup(from);
154  if (! sr->env_from)
155  return SPF_E_NO_MEMORY;
156 
157  len = cp - from;
158  sr->env_from_lp = malloc(len + 1);
159  if (!sr->env_from_lp) {
160  SPF_FREE(sr->env_from);
161  return SPF_E_NO_MEMORY;
162  }
163  strncpy(sr->env_from_lp, from, len);
164  sr->env_from_lp[len] = '\0';
165  sr->env_from_dp = strdup(cp + 1);
166  if (!sr->env_from_dp) {
167  SPF_FREE(sr->env_from);
168  SPF_FREE(sr->env_from_lp);
169  return SPF_E_NO_MEMORY;
170  }
171  }
172  else {
173  if (cp == from) from++; /* "@domain.example" */
174  len = sizeof("postmaster@") + strlen(from);
175  sr->env_from = malloc(len + 1); /* sizeof("") == 1? */
176  if (! sr->env_from)
177  return SPF_E_NO_MEMORY;
178  sprintf(sr->env_from, "postmaster@%s", from);
179  sr->env_from_lp = strdup("postmaster");
180  if (!sr->env_from_lp) {
181  SPF_FREE(sr->env_from);
182  return SPF_E_NO_MEMORY;
183  }
184  sr->env_from_dp = strdup(from);
185  if (!sr->env_from_dp) {
186  SPF_FREE(sr->env_from);
187  SPF_FREE(sr->env_from_lp);
188  return SPF_E_NO_MEMORY;
189  }
190  }
191 
192  return 0; // SPF_E_SUCCESS
193 }
194 
195 const char *
196 SPF_request_get_client_dom(SPF_request_t *sr)
197 {
198  SPF_server_t *spf_server;
199 
200  SPF_ASSERT_NOTNULL(sr);
201  spf_server = sr->spf_server;
202  SPF_ASSERT_NOTNULL(spf_server);
203 
204  if (sr->client_dom == NULL) {
205  sr->client_dom = SPF_dns_get_client_dom(spf_server->resolver,
206  sr);
207  }
208  return sr->client_dom;
209 }
210 
211 int
212 SPF_request_is_loopback(SPF_request_t *sr)
213 {
214  if (sr->client_ver == AF_INET) {
215  if ((ntohl(sr->ipv4.s_addr) & IN_CLASSA_NET) ==
216  (IN_LOOPBACKNET << 24)) {
217  return TRUE;
218  }
219  }
220  else if (sr->client_ver == AF_INET6) {
221  if (IN6_IS_ADDR_LOOPBACK(&sr->ipv6))
222  return TRUE;
223  }
224  return FALSE;
225 }
226 
227 static SPF_errcode_t
228 SPF_request_prepare(SPF_request_t *sr)
229 {
230  if (sr->use_helo)
231  sr->cur_dom = sr->helo_dom;
232  else
233  sr->cur_dom = sr->env_from_dp;
234  return SPF_E_SUCCESS;
235 }
236 
240 static SPF_errcode_t
241 SPF_request_query_record(SPF_request_t *spf_request,
242  SPF_response_t *spf_response,
243  SPF_record_t *spf_record,
244  SPF_errcode_t err)
245 {
246  if (err != SPF_E_SUCCESS) {
247  if (spf_record)
248  SPF_record_free(spf_record);
249  SPF_i_done(spf_response, spf_response->result, spf_response->reason, spf_response->err);
250  return err;
251  }
252  /* Now, in theory, SPF_response_errors(spf_response) == 0 */
253  if (SPF_response_errors(spf_response) > 0)
254  SPF_infof("Warning: %d errors in response, "
255  "but no error code. Evaluating.",
256  SPF_response_errors(spf_response));
257  /* If we get here, spf_record better not be NULL */
258  spf_response->spf_record_exp = spf_record;
259  err = SPF_record_interpret(spf_record,
260  spf_request, spf_response, 0);
261  SPF_record_free(spf_record);
262 
263  return err;
264 }
265 
270 SPF_request_query_mailfrom(SPF_request_t *spf_request,
271  SPF_response_t **spf_responsep)
272 {
273  SPF_server_t *spf_server;
274  SPF_record_t *spf_record;
275  SPF_errcode_t err;
276 
277  SPF_ASSERT_NOTNULL(spf_request);
278  spf_server = spf_request->spf_server;
279  SPF_ASSERT_NOTNULL(spf_server);
280 
281  *spf_responsep = SPF_response_new(spf_request);
282  if (! *spf_responsep)
283  return SPF_E_NO_MEMORY;
284 
285  /* Give localhost a free ride */
286  if (SPF_request_is_loopback(spf_request))
287  return SPF_i_done(*spf_responsep, SPF_RESULT_PASS,
289 
290  SPF_request_prepare(spf_request);
291 
292  err = SPF_server_get_record(spf_server, spf_request,
293  *spf_responsep, &spf_record);
294  return SPF_request_query_record(spf_request, *spf_responsep,
295  spf_record, err);
296 }
297 
298 /* This interface isn't finalised. */
300 SPF_request_query_fallback(SPF_request_t *spf_request,
301  SPF_response_t **spf_responsep,
302  const char *record)
303 {
304  SPF_server_t *spf_server;
305  SPF_record_t *spf_record;
306  SPF_errcode_t err;
307 
308  SPF_ASSERT_NOTNULL(spf_request);
309  spf_server = spf_request->spf_server;
310  SPF_ASSERT_NOTNULL(spf_server);
311 
312  *spf_responsep = SPF_response_new(spf_request);
313  if (! *spf_responsep)
314  return SPF_E_NO_MEMORY;
315 
316  /* Give localhost a free ride */
317  if (SPF_request_is_loopback(spf_request))
318  return SPF_i_done(*spf_responsep, SPF_RESULT_PASS,
320 
321  SPF_request_prepare(spf_request);
322 
323  err = SPF_record_compile(spf_server,
324  *spf_responsep, &spf_record,
325  record);
326  return SPF_request_query_record(spf_request, *spf_responsep,
327  spf_record, err);
328 }
329 
338 /* FIXME: Check the implementation of this. */
340 SPF_request_query_rcptto(SPF_request_t *spf_request,
341  SPF_response_t **spf_responsep,
342  const char *rcpt_to)
343 {
344  SPF_server_t *spf_server;
345  SPF_record_t *spf_record;
346  SPF_errcode_t err;
347  const char *rcpt_to_dom;
348  char *record;
349  size_t len;
350 
351  SPF_ASSERT_NOTNULL(spf_request);
352  spf_server = spf_request->spf_server;
353  SPF_ASSERT_NOTNULL(spf_server);
354 
355  *spf_responsep = SPF_response_new(spf_request);
356  if (! *spf_responsep)
357  return SPF_E_NO_MEMORY;
358 
359  /* Give localhost a free ride */
360  if (SPF_request_is_loopback(spf_request))
361  return SPF_i_done(*spf_responsep, SPF_RESULT_PASS,
363 
364  rcpt_to_dom = strchr(rcpt_to, '@');
365  if (rcpt_to_dom == NULL)
366  rcpt_to_dom = rcpt_to;
367  else
368  rcpt_to_dom++;
369  spf_request->cur_dom = rcpt_to_dom;
370 
371  len = sizeof(SPF_VER_STR) + 64 + strlen(rcpt_to_dom);
372  record = malloc(len);
373  if (! record)
374  return SPF_E_NO_MEMORY;
375  snprintf(record, len, SPF_VER_STR " mx:%s", rcpt_to_dom);
376  err = SPF_record_compile(spf_server,
377  *spf_responsep, &spf_record,
378  record);
379  free(record);
380  return SPF_request_query_record(spf_request, *spf_responsep,
381  spf_record, err);
382 }
SPF_response_new
SPF_response_t * SPF_response_new(SPF_request_t *spf_request)
Definition: spf_response.c:37
SPF_request_query_rcptto
SPF_errcode_t SPF_request_query_rcptto(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *rcpt_to)
Definition: spf_request.c:340
SPF_E_INVALID_IP6
@ SPF_E_INVALID_IP6
Definition: spf_response.h:140
spf_request.h
SPF_server_get_record
SPF_errcode_t SPF_server_get_record(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_record_t **spf_recordp)
Definition: spf_server.c:316
SPF_errcode_t
SPF_errcode_t
Definition: spf_response.h:119
SPF_request_set_env_from
int SPF_request_set_env_from(SPF_request_t *sr, const char *from)
Definition: spf_request.c:139
SPF_infof
#define SPF_infof
Definition: spf_log.h:79
SPF_request_set_ipv6
SPF_errcode_t SPF_request_set_ipv6(SPF_request_t *sr, struct in6_addr addr)
Definition: spf_request.c:83
spf.h
SPF_request_get_rec_dom
const char * SPF_request_get_rec_dom(SPF_request_t *sr)
Definition: spf_request.c:131
SPF_record_compile
SPF_errcode_t SPF_record_compile(SPF_server_t *spf_server, SPF_response_t *spf_response, SPF_record_t **spf_recordp, const char *record)
Definition: spf_compile.c:1180
SPF_E_SUCCESS
@ SPF_E_SUCCESS
Definition: spf_response.h:120
SPF_request_query_fallback
SPF_errcode_t SPF_request_query_fallback(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *record)
Definition: spf_request.c:300
TRUE
#define TRUE
Definition: spf_internal.h:23
spf_dns.h
SPF_request_set_helo_dom
SPF_errcode_t SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
Definition: spf_request.c:117
SPF_REASON_LOCALHOST
@ SPF_REASON_LOCALHOST
Definition: spf_response.h:103
FALSE
#define FALSE
Definition: spf_internal.h:24
spf_internal.h
SPF_request_is_loopback
int SPF_request_is_loopback(SPF_request_t *sr)
Definition: spf_request.c:212
SPF_record_interpret
SPF_errcode_t SPF_record_interpret(SPF_record_t *spf_record, SPF_request_t *spf_request, SPF_response_t *spf_response, int depth)
Definition: spf_interpret.c:585
SPF_E_NO_MEMORY
@ SPF_E_NO_MEMORY
Definition: spf_response.h:121
SPF_request_get_client_dom
const char * SPF_request_get_client_dom(SPF_request_t *sr)
Definition: spf_request.c:196
SPF_request_new
SPF_request_t * SPF_request_new(SPF_server_t *spf_server)
Definition: spf_request.c:41
SPF_request_query_mailfrom
SPF_errcode_t SPF_request_query_mailfrom(SPF_request_t *spf_request, SPF_response_t **spf_responsep)
Definition: spf_request.c:270
SPF_i_done
SPF_errcode_t SPF_i_done(SPF_response_t *spf_response, SPF_result_t result, SPF_reason_t reason, SPF_errcode_t err)
Definition: spf_interpret.c:388
SPF_request_set_ipv4
SPF_errcode_t SPF_request_set_ipv4(SPF_request_t *sr, struct in_addr addr)
Definition: spf_request.c:71
SPF_VER_STR
#define SPF_VER_STR
Definition: spf.h:35
SPF_request_set_ipv4_str
SPF_errcode_t SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
Definition: spf_request.c:95
SPF_response_errors
int SPF_response_errors(SPF_response_t *rp)
Definition: spf_response.c:296
NULL
#define NULL
Definition: spf_internal.h:28
SPF_record_free
void SPF_record_free(SPF_record_t *rp)
Definition: spf_record.c:63
SPF_ASSERT_NOTNULL
#define SPF_ASSERT_NOTNULL(x)
Definition: spf_log.h:118
SPF_request_set_ipv6_str
SPF_errcode_t SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
Definition: spf_request.c:106
SPF_FREE
#define SPF_FREE(x)
Definition: spf_request.c:37
SPF_E_INVALID_IP4
@ SPF_E_INVALID_IP4
Definition: spf_response.h:139
spf_sys_config.h
SPF_RESULT_PASS
@ SPF_RESULT_PASS
Definition: spf_response.h:82
SPF_request_free
void SPF_request_free(SPF_request_t *sr)
Definition: spf_request.c:59
SPF_dns_get_client_dom
char * SPF_dns_get_client_dom(SPF_dns_server_t *spf_dns_server, SPF_request_t *sr)
Definition: spf_dns.c:206