libspf2 1.2.11
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
36SPF_response_t *
37SPF_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
52void
53SPF_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
77static SPF_response_t *
78SPF_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 */
89SPF_response_t *
90SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
91{
92 switch (SPF_response_result(main)) {
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
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
119 default:
120 /* If the main is peculiar, including softfail: */
121 switch (SPF_response_result(r2mx)) {
122 case SPF_RESULT_PASS:
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
135SPF_response_result(SPF_response_t *rp)
136{
137 return rp->result;
138}
139
141SPF_response_reason(SPF_response_t *rp)
142{
143 return rp->reason;
144}
145
147SPF_response_errcode(SPF_response_t *rp)
148{
149 return rp->err;
150}
151
152const char *
154{
155 return rp->received_spf;
156}
157
158const char *
160{
161 return rp->received_spf_value;
162}
163
164const char *
166{
167 return rp->header_comment;
168}
169
170const char *
172{
173 return rp->smtp_comment;
174}
175
176const char *
178{
179 return rp->explanation;
180}
181
182/* Error manipulation functions */
183
184#define SPF_ERRMSGSIZE 4096
185
186static SPF_errcode_t
187SPF_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
238SPF_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
247SPF_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
256SPF_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
264SPF_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
273SPF_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
282SPF_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
289int
290SPF_response_messages(SPF_response_t *rp)
291{
292 return rp->errors_length;
293}
294
295int
296SPF_response_errors(SPF_response_t *rp)
297{
298 return rp->num_errors;
299}
300
301int
302SPF_response_warnings(SPF_response_t *rp)
303{
304 return rp->errors_length - rp->num_errors;
305}
306
308SPF_response_message(SPF_response_t *rp, int idx)
309{
310 return &rp->errors[idx];
311}
312
315{
316 return err->code;
317}
318
319const char *
321{
322 return err->message;
323}
324
325char
327{
328 return err->is_error;
329}
SPF_result_t
@ SPF_RESULT_PERMERROR
@ SPF_RESULT_INVALID
@ SPF_RESULT_PASS
@ SPF_RESULT_NEUTRAL
@ SPF_RESULT_TEMPERROR
@ SPF_RESULT_SOFTFAIL
@ SPF_RESULT_FAIL
SPF_reason_t
SPF_errcode_t
const char * SPF_strerror(SPF_errcode_t spf_err)
#define SPF_error(errmsg)
Definition spf_log.h:40
#define NULL
const char * SPF_response_get_explanation(SPF_response_t *rp)
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
const char * SPF_response_get_received_spf(SPF_response_t *rp)
const char * SPF_response_get_header_comment(SPF_response_t *rp)
#define SPF_ERRMSGSIZE
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,...)
SPF_response_t * SPF_response_new(SPF_request_t *spf_request)
SPF_errcode_t SPF_response_add_error_idx(SPF_response_t *rp, SPF_errcode_t code, const char *text, int idx, const char *format,...)
#define SPF_ADD_ERROR(_ise, _txt, _ix)
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,...)
#define SPF_ADD_WARN(_ise, _txt, _ix)
SPF_errcode_t SPF_response_add_warn(SPF_response_t *rp, SPF_errcode_t code, const char *format,...)
int SPF_response_warnings(SPF_response_t *rp)
SPF_errcode_t SPF_response_add_error(SPF_response_t *rp, SPF_errcode_t code, const char *format,...)
SPF_errcode_t SPF_response_add_warn_idx(SPF_response_t *rp, SPF_errcode_t code, const char *text, int idx, const char *format,...)
void SPF_response_free(SPF_response_t *rp)
const char * SPF_error_message(SPF_error_t *err)
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)
int SPF_response_messages(SPF_response_t *rp)
const char * SPF_response_get_received_spf_value(SPF_response_t *rp)
char SPF_error_errorp(SPF_error_t *err)
SPF_errcode_t SPF_error_code(SPF_error_t *err)
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
SPF_result_t SPF_response_result(SPF_response_t *rp)
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
int SPF_response_errors(SPF_response_t *rp)
int main(int argc, char *argv[])
SPF_errcode_t code