libspf2  1.2.11
spf_get_exp.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 <stdlib.h> /* malloc / free */
20 # include <stdio.h> /* stdin / stdout */
21 #endif
22 
23 #ifdef HAVE_NETDB_H
24 #include <netdb.h>
25 #endif
26 
27 #ifdef HAVE_STRING_H
28 # include <string.h> /* strstr / strdup */
29 #else
30 # ifdef HAVE_STRINGS_H
31 # include <strings.h> /* strstr / strdup */
32 # endif
33 #endif
34 
35 
36 #include "spf.h"
37 #include "spf_dns.h"
38 #include "spf_internal.h"
39 #include "spf_dns_internal.h"
40 
41 
42  /* This never happens. We get SPF_DEFAULT_EXP instead.
43  * This is a panic response which must not contain macros. */
44 #define SPF_LAME_EXP "SPF failure: no explanation available"
45 
46 static SPF_errcode_t
47 SPF_server_get_default_explanation(SPF_server_t *spf_server,
48  SPF_request_t *spf_request,
49  SPF_response_t *spf_response,
50  char **bufp, size_t *buflenp)
51 {
52  SPF_errcode_t err;
53  SPF_macro_t *spf_macro;
54 
55  spf_macro = spf_server->explanation;
56  if (spf_macro != NULL) {
57  err = SPF_record_expand_data(spf_server,
58  spf_request, spf_response,
59  SPF_macro_data(spf_macro), spf_macro->macro_len,
60  bufp, buflenp);
61  return err;
62  }
63  else {
64  size_t len = sizeof(SPF_LAME_EXP) + 1;
65  if (*buflenp < len) {
66  char *tmp = realloc(*bufp, len);
67  if (tmp == NULL)
68  return SPF_E_NO_MEMORY;
69  *bufp = tmp;
70  *buflenp = len;
71  }
72  strcpy(*bufp, SPF_LAME_EXP);
73  return SPF_E_SUCCESS;
74  }
75 }
76 
77 #define RETURN_DEFAULT_EXP() do { \
78  return SPF_server_get_default_explanation(spf_server, \
79  spf_request, spf_response, bufp, buflenp); \
80  } while(0)
81 
83 SPF_request_get_exp(SPF_server_t *spf_server,
84  SPF_request_t *spf_request,
85  SPF_response_t *spf_response,
86  SPF_record_t *spf_record,
87  char **bufp, size_t *buflenp)
88 {
89  SPF_macro_t *spf_macro;
90  SPF_dns_server_t *resolver;
91  SPF_dns_rr_t *rr_txt;
92  SPF_errcode_t err;
93  const char *domain;
94 
95 
96  /*
97  * There are lots of places to look for the explanation message,
98  * some require DNS lookups, some don't.
99  */
100 
101  SPF_ASSERT_NOTNULL(spf_server);
102  SPF_ASSERT_NOTNULL(spf_request);
103  SPF_ASSERT_NOTNULL(spf_response);
104  SPF_ASSERT_NOTNULL(spf_record);
105  SPF_ASSERT_NOTNULL(bufp);
106  SPF_ASSERT_NOTNULL(buflenp);
107 
108  domain = spf_request->cur_dom;
109 
110  if ( domain == NULL )
111  return SPF_response_add_warn(spf_response, SPF_E_NOT_CONFIG,
112  "Could not identify current domain for explanation");
113 
114  /*
115  * start looking... check spfid for exp-text=
116  */
117 
118  err = SPF_record_find_mod_value(spf_server, spf_request,
119  spf_response, spf_record,
120  SPF_EXP_MOD_NAME, bufp, buflenp);
121  if (err == SPF_E_SUCCESS)
122  return err;
123 
124 
125  /*
126  * still looking... check the spfid for exp=
127  */
128 
129  err = SPF_record_find_mod_value(spf_server, spf_request,
130  spf_response, spf_record,
131  "exp", bufp, buflenp );
132  if (err != SPF_E_SUCCESS) {
133  /*
134  * still looking... try to return default exp from spfcid
135  */
137  }
138 
139  if (*bufp == NULL || (*bufp)[0] == '\0') {
140  /*
141  * still looking... try to return default exp from spfcid
142  */
143  SPF_response_add_warn(spf_response, SPF_E_NOT_SPF,
144  "Explanation is blank!");
146  }
147 
148 
149  /*
150  * still looking... try doing a DNS lookup on the exp= name
151  */
152 
153  resolver = spf_server->resolver;
154 
155  if (resolver->get_exp)
156  return resolver->get_exp(spf_server, *bufp, bufp, buflenp);
157 
158  rr_txt = SPF_dns_lookup(resolver, *bufp, ns_t_txt, TRUE);
159  if (rr_txt == NULL) {
160  SPF_dns_rr_free(rr_txt);
162  }
163 
164  switch (rr_txt->herrno) {
165  case HOST_NOT_FOUND:
166  case NO_DATA:
167  SPF_dns_rr_free(rr_txt);
169  break;
170 
171  case TRY_AGAIN:
172  SPF_dns_rr_free(rr_txt);
174  break;
175 
176  case NETDB_SUCCESS:
177  break;
178 
179  default:
180  SPF_warning("Unknown DNS lookup error code");
181  SPF_dns_rr_free(rr_txt);
183  break;
184  }
185 
186  if (rr_txt->num_rr == 0) {
187  SPF_response_add_warn(spf_response, SPF_E_NOT_SPF,
188  "No TXT records returned from DNS lookup");
190  }
191 
192 
193  /*
194  * still looking... try compiling this TXT record
195  */
196 
197  /* FIXME we are supposed to concatenate the TXT records */
198 
199  /* FIXME: If this generates any errors, demote them to warnings. */
200  spf_macro = NULL;
201  err = SPF_record_compile_macro(spf_server, spf_response, &spf_macro,
202  rr_txt->rr[0]->txt);
203  if (err != SPF_E_SUCCESS) {
204  if (spf_macro)
205  SPF_macro_free(spf_macro);
206  SPF_dns_rr_free(rr_txt);
208  }
209 
210  err = SPF_record_expand_data(spf_server,
211  spf_request, spf_response,
212  SPF_macro_data(spf_macro), spf_macro->macro_len,
213  bufp, buflenp);
214  SPF_macro_free(spf_macro);
215  SPF_dns_rr_free(rr_txt);
216 
217  return err;
218 }
#define SPF_EXP_MOD_NAME
Definition: spf.h:64
#define NO_DATA
Definition: spf_dns.h:106
#define HOST_NOT_FOUND
Definition: spf_dns.h:103
#define NETDB_SUCCESS
Definition: spf_dns.h:102
#define TRY_AGAIN
Definition: spf_dns.h:104
SPF_dns_rr_t * SPF_dns_lookup(SPF_dns_server_t *spf_dns_server, const char *domain, ns_type rr_type, int should_cache)
Definition: spf_dns.c:133
void SPF_dns_rr_free(SPF_dns_rr_t *spfrr)
Definition: spf_dns_rr.c:114
#define NULL
Definition: spf_internal.h:28
#define TRUE
Definition: spf_internal.h:23
#define SPF_ASSERT_NOTNULL(x)
Definition: spf_log.h:118
#define SPF_warning(errmsg)
Definition: spf_log.h:45
SPF_errcode_t SPF_record_find_mod_value(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_record_t *spf_record, const char *mod_name, char **bufp, size_t *buflenp)
Definition: spf_record.c:126
void SPF_macro_free(SPF_macro_t *mac)
Definition: spf_record.c:73
SPF_errcode_t SPF_record_expand_data(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_data_t *data, size_t data_len, char **bufp, size_t *buflenp)
Definition: spf_expand.c:81
SPF_errcode_t SPF_record_compile_macro(SPF_server_t *spf_server, SPF_response_t *spf_response, SPF_macro_t **spf_macrop, const char *record)
Definition: spf_compile.c:1499
SPF_errcode_t SPF_response_add_warn(SPF_response_t *rp, SPF_errcode_t code, const char *format,...)
Definition: spf_response.c:282
SPF_errcode_t
Definition: spf_response.h:119
@ SPF_E_NOT_CONFIG
Definition: spf_response.h:145
@ SPF_E_NO_MEMORY
Definition: spf_response.h:121
@ SPF_E_NOT_SPF
Definition: spf_response.h:122
@ SPF_E_SUCCESS
Definition: spf_response.h:120
@ ns_t_txt
Definition: arpa_nameser.h:317
#define RETURN_DEFAULT_EXP()
Definition: spf_get_exp.c:77
#define SPF_LAME_EXP
Definition: spf_get_exp.c:44
SPF_errcode_t SPF_request_get_exp(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_record_t *spf_record, char **bufp, size_t *buflenp)
Definition: spf_get_exp.c:83
SPF_dns_rr_data_t ** rr
Definition: spf_dns_rr.h:60
SPF_dns_stat_t herrno
Definition: spf_dns_rr.h:66