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
46static SPF_errcode_t
47SPF_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 (*bufp == NULL || *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
83SPF_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 */
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) {
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 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 ns_t_txt
Definition spf_dns.h:80
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
#define TRY_AGAIN
Definition spf_dns.h:104
SPF_errcode_t SPF_response_add_warn(SPF_response_t *rp, SPF_errcode_t code, const char *format,...)
SPF_errcode_t
@ SPF_E_NOT_CONFIG
@ SPF_E_NO_MEMORY
@ SPF_E_NOT_SPF
@ SPF_E_SUCCESS
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)
#define SPF_EXP_MOD_NAME
Definition spf.h:64
void SPF_dns_rr_free(SPF_dns_rr_t *spfrr)
Definition spf_dns_rr.c:114
#define SPF_ASSERT_NOTNULL(x)
Definition spf_log.h:118
#define SPF_warning(errmsg)
Definition spf_log.h:45
#define NULL
#define TRUE
#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