libspf2  1.2.10
spf_response.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_response.h"
35 
36 SPF_response_t *
37 SPF_response_new(SPF_request_t *spf_request)
38 {
39  SPF_response_t *rp;
40 
41  rp = (SPF_response_t *)malloc(sizeof(SPF_response_t));
42  if (! rp)
43  return rp;
44  memset(rp, 0, sizeof(SPF_response_t));
45 
46  rp->spf_request = spf_request;
47  rp->result = SPF_RESULT_INVALID;
48 
49  return rp;
50 }
51 
52 void
53 SPF_response_free(SPF_response_t *rp)
54 {
55  int i;
56 
57  if (rp->received_spf)
58  free(rp->received_spf);
59  /* Don't free received_spf_value - it points into received_spf */
60  if (rp->header_comment)
61  free(rp->header_comment);
62  if (rp->smtp_comment)
63  free(rp->smtp_comment);
64  if (rp->explanation)
65  free(rp->explanation);
66 
67  if (rp->errors) {
68  for (i = 0; i < rp->errors_length; i++) {
69  free(rp->errors[i].message);
70  }
71  free(rp->errors);
72  }
73 
74  free(rp);
75 }
76 
77 static SPF_response_t *
78 SPF_response_choose(SPF_response_t *yes, SPF_response_t *no)
79 {
81  return yes;
82 }
83 
84 /*
85  * This is rather a guess-and-fiddle routine which tries to pick
86  * the best of both worlds. It doesn't currently deal with error
87  * messages at all.
88  */
89 SPF_response_t *
90 SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
91 {
92  switch (SPF_response_result(main)) {
93  case SPF_RESULT_INVALID:
94  /* If the main failed entirely, use the secondary */
95  return SPF_response_choose(r2mx, main);
96 
97  case SPF_RESULT_PASS:
98  /* If the main passed, use main */
99  return SPF_response_choose(main, r2mx);
100 
101  case SPF_RESULT_NEUTRAL:
102  /* If the main is neutral: */
103  switch (SPF_response_result(r2mx)) {
104  case SPF_RESULT_PASS:
105  /* Use the secondary if it passed */
106  return SPF_response_choose(r2mx, main);
107  default:
108  /* Otherwise just use the main */
109  return SPF_response_choose(main, r2mx);
110  }
111 
112  case SPF_RESULT_FAIL:
113  /* If the main failed, use the secondary */
114  return SPF_response_choose(r2mx, main);
115 
118  case SPF_RESULT_SOFTFAIL:
119  default:
120  /* If the main is peculiar, including softfail: */
121  switch (SPF_response_result(r2mx)) {
122  case SPF_RESULT_PASS:
123  case SPF_RESULT_NEUTRAL:
124  case SPF_RESULT_SOFTFAIL:
125  /* Use the secondary if it didn't fail */
126  return SPF_response_choose(r2mx, main);
127  default:
128  /* Otherwise just use the main */
129  return SPF_response_choose(main, r2mx);
130  }
131  }
132 }
133 
135 SPF_response_result(SPF_response_t *rp)
136 {
137  return rp->result;
138 }
139 
141 SPF_response_reason(SPF_response_t *rp)
142 {
143  return rp->reason;
144 }
145 
147 SPF_response_errcode(SPF_response_t *rp)
148 {
149  return rp->err;
150 }
151 
152 const char *
153 SPF_response_get_received_spf(SPF_response_t *rp)
154 {
155  return rp->received_spf;
156 }
157 
158 const char *
160 {
161  return rp->received_spf_value;
162 }
163 
164 const char *
166 {
167  return rp->header_comment;
168 }
169 
170 const char *
171 SPF_response_get_smtp_comment(SPF_response_t *rp)
172 {
173  return rp->smtp_comment;
174 }
175 
176 const char *
177 SPF_response_get_explanation(SPF_response_t *rp)
178 {
179  return rp->explanation;
180 }
181 
182 /* Error manipulation functions */
183 
184 #define SPF_ERRMSGSIZE 4096
185 
186 static SPF_errcode_t
187 SPF_response_add_error_v(SPF_response_t *rp,
188  SPF_errcode_t code, int is_error,
189  const char *text, int idx,
190  const char *format, va_list ap)
191 {
192  SPF_error_t *tmp;
193  char buf[SPF_ERRMSGSIZE];
194  int size;
195 
196  /* TODO: Use text and idx */
197 
198  if (!format)
199  format = SPF_strerror(code);
200  size = vsnprintf(buf, sizeof(buf), format, ap);
201  if (text != NULL) {
202  snprintf(&buf[size], sizeof(buf) - size,
203  " near '%.12s'", &text[idx]);
204  }
205  buf[SPF_ERRMSGSIZE - 1] = '\0';
206 
207  if (rp->errors_length == rp->errors_size) {
208  size = rp->errors_size + (rp->errors_size / 4) + 4;
209  tmp = (SPF_error_t *)realloc(rp->errors, size * sizeof(SPF_error_t));
210  if (! tmp) {
211  SPF_error("Failed to allocate memory for extra response error");
212  return code;
213  }
214  rp->errors = tmp;
215  rp->errors_size = size;
216  }
217 
218  rp->errors[rp->errors_length].code = code;
219  rp->errors[rp->errors_length].is_error = is_error;
220  /* If we are a memory error, this might fail. */
221  rp->errors[rp->errors_length].message = strdup(buf);
222  rp->errors_length++;
223 
224  return code;
225 }
226 
227 #define SPF_ADD_ERROR(_ise, _txt, _ix) \
228  va_list ap; va_start(ap, format); \
229  SPF_response_add_error_v(rp, code, _ise, _txt, _ix, format, ap); \
230  rp->num_errors++; \
231  va_end(ap); return code;
232 #define SPF_ADD_WARN(_ise, _txt, _ix) \
233  va_list ap; va_start(ap, format); \
234  SPF_response_add_error_v(rp, code, _ise, _txt, _ix, format, ap); \
235  va_end(ap); return code;
236 
238 SPF_response_add_error_ptr(SPF_response_t *rp,
239  SPF_errcode_t code,
240  const char *text, const char *tptr,
241  const char *format, ...)
242 {
243  SPF_ADD_ERROR(1, text ? text : tptr, text ? (tptr - text) : 0);
244 }
245 
247 SPF_response_add_error_idx(SPF_response_t *rp,
248  SPF_errcode_t code,
249  const char *text, int idx,
250  const char *format, ...)
251 {
252  SPF_ADD_ERROR(1, text, idx);
253 }
254 
256 SPF_response_add_error(SPF_response_t *rp,
257  SPF_errcode_t code,
258  const char *format, ...)
259 {
260  SPF_ADD_ERROR(1, NULL, 0);
261 }
262 
264 SPF_response_add_warn_ptr(SPF_response_t *rp,
265  SPF_errcode_t code,
266  const char *text, const char *tptr,
267  const char *format, ...)
268 {
269  SPF_ADD_WARN(0, text ? text : tptr, text ? (tptr - text) : 0);
270 }
271 
273 SPF_response_add_warn_idx(SPF_response_t *rp,
274  SPF_errcode_t code,
275  const char *text, int idx,
276  const char *format, ...)
277 {
278  SPF_ADD_WARN(0, text, idx);
279 }
280 
282 SPF_response_add_warn(SPF_response_t *rp,
283  SPF_errcode_t code,
284  const char *format, ...)
285 {
286  SPF_ADD_WARN(0, NULL, 0);
287 }
288 
289 int
290 SPF_response_messages(SPF_response_t *rp)
291 {
292  return rp->errors_length;
293 }
294 
295 int
296 SPF_response_errors(SPF_response_t *rp)
297 {
298  return rp->num_errors;
299 }
300 
301 int
302 SPF_response_warnings(SPF_response_t *rp)
303 {
304  return rp->errors_length - rp->num_errors;
305 }
306 
307 SPF_error_t *
308 SPF_response_message(SPF_response_t *rp, int idx)
309 {
310  return &rp->errors[idx];
311 }
312 
315 {
316  return err->code;
317 }
318 
319 const char *
321 {
322  return err->message;
323 }
324 
325 char
327 {
328  return err->is_error;
329 }
SPF_strerror
const char * SPF_strerror(SPF_errcode_t spf_err)
Definition: spf_strerror.c:33
SPF_RESULT_INVALID
@ SPF_RESULT_INVALID
Definition: spf_response.h:80
SPF_error_code
SPF_errcode_t SPF_error_code(SPF_error_t *err)
Definition: spf_response.c:314
SPF_error_t
Definition: spf_response.h:158
SPF_errcode_t
SPF_errcode_t
Definition: spf_response.h:119
SPF_response_get_header_comment
const char * SPF_response_get_header_comment(SPF_response_t *rp)
Definition: spf_response.c:165
SPF_ADD_WARN
#define SPF_ADD_WARN(_ise, _txt, _ix)
Definition: spf_response.c:232
SPF_response_new
SPF_response_t * SPF_response_new(SPF_request_t *spf_request)
Definition: spf_response.c:37
SPF_RESULT_PERMERROR
@ SPF_RESULT_PERMERROR
Definition: spf_response.h:88
SPF_response_add_error
SPF_errcode_t SPF_response_add_error(SPF_response_t *rp, SPF_errcode_t code, const char *format,...)
Definition: spf_response.c:256
SPF_response_errors
int SPF_response_errors(SPF_response_t *rp)
Definition: spf_response.c:296
SPF_RESULT_SOFTFAIL
@ SPF_RESULT_SOFTFAIL
Definition: spf_response.h:84
SPF_response_message
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)
Definition: spf_response.c:308
SPF_reason_t
SPF_reason_t
Definition: spf_response.h:100
SPF_ADD_ERROR
#define SPF_ADD_ERROR(_ise, _txt, _ix)
Definition: spf_response.c:227
SPF_response_add_warn_ptr
SPF_errcode_t SPF_response_add_warn_ptr(SPF_response_t *rp, SPF_errcode_t code, const char *text, const char *tptr, const char *format,...)
Definition: spf_response.c:264
spf.h
SPF_response_reason
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
Definition: spf_response.c:141
SPF_response_warnings
int SPF_response_warnings(SPF_response_t *rp)
Definition: spf_response.c:302
SPF_error_t::code
SPF_errcode_t code
Definition: spf_response.h:159
SPF_response_get_explanation
const char * SPF_response_get_explanation(SPF_response_t *rp)
Definition: spf_response.c:177
SPF_response_get_received_spf
const char * SPF_response_get_received_spf(SPF_response_t *rp)
Definition: spf_response.c:153
SPF_error
#define SPF_error(errmsg)
Definition: spf_log.h:40
SPF_error_message
const char * SPF_error_message(SPF_error_t *err)
Definition: spf_response.c:320
SPF_RESULT_NEUTRAL
@ SPF_RESULT_NEUTRAL
Definition: spf_response.h:81
SPF_error_errorp
char SPF_error_errorp(SPF_error_t *err)
Definition: spf_response.c:326
spf_dns.h
SPF_result_t
SPF_result_t
Definition: spf_response.h:79
SPF_ERRMSGSIZE
#define SPF_ERRMSGSIZE
Definition: spf_response.c:184
SPF_response_get_smtp_comment
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
Definition: spf_response.c:171
SPF_response_add_error_idx
SPF_errcode_t SPF_response_add_error_idx(SPF_response_t *rp, SPF_errcode_t code, const char *text, int idx, const char *format,...)
Definition: spf_response.c:247
SPF_response_get_received_spf_value
const char * SPF_response_get_received_spf_value(SPF_response_t *rp)
Definition: spf_response.c:159
SPF_RESULT_FAIL
@ SPF_RESULT_FAIL
Definition: spf_response.h:83
SPF_response_result
SPF_result_t SPF_response_result(SPF_response_t *rp)
Definition: spf_response.c:135
SPF_response_combine
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
Definition: spf_response.c:90
main
int main(int argc, char *argv[])
Definition: spf_example.c:114
SPF_response_add_error_ptr
SPF_errcode_t SPF_response_add_error_ptr(SPF_response_t *rp, SPF_errcode_t code, const char *text, const char *tptr, const char *format,...)
Definition: spf_response.c:238
SPF_response_errcode
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
Definition: spf_response.c:147
spf_response.h
SPF_response_add_warn
SPF_errcode_t SPF_response_add_warn(SPF_response_t *rp, SPF_errcode_t code, const char *format,...)
Definition: spf_response.c:282
NULL
#define NULL
Definition: spf_internal.h:28
SPF_response_free
void SPF_response_free(SPF_response_t *rp)
Definition: spf_response.c:53
SPF_RESULT_TEMPERROR
@ SPF_RESULT_TEMPERROR
Definition: spf_response.h:87
SPF_error_t::is_error
char is_error
Definition: spf_response.h:161
SPF_response_messages
int SPF_response_messages(SPF_response_t *rp)
Definition: spf_response.c:290
SPF_response_add_warn_idx
SPF_errcode_t SPF_response_add_warn_idx(SPF_response_t *rp, SPF_errcode_t code, const char *text, int idx, const char *format,...)
Definition: spf_response.c:273
SPF_error_t::message
char * message
Definition: spf_response.h:160
spf_sys_config.h
SPF_RESULT_PASS
@ SPF_RESULT_PASS
Definition: spf_response.h:82