libspf2  1.2.11
spf_dns.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 
17 #include "spf_sys_config.h"
18 
19 #ifdef STDC_HEADERS
20 # include <stdio.h> /* stdin / stdout */
21 # include <stdlib.h> /* malloc / free */
22 #endif
23 
24 #ifdef HAVE_STRING_H
25 # include <string.h> /* strstr / strdup */
26 #else
27 # ifdef HAVE_STRINGS_H
28 # include <strings.h> /* strstr / strdup */
29 # endif
30 #endif
31 
32 #ifdef HAVE_NETDB_H
33 #include <netdb.h>
34 #endif
35 
36 
37 #include "spf.h"
38 #include "spf_dns.h"
39 #include "spf_internal.h"
40 #include "spf_dns_internal.h"
41 
42 
43 /*
44  * helper functions
45  */
46 
47 static void
48 SPF_dns_debug_pre(SPF_dns_server_t *spf_dns_server, const char *domain,
49  ns_type rr_type, int should_cache)
50 {
51  if (spf_dns_server->debug) {
52  SPF_debugf("DNS[%s] lookup: %s %s (%d)",
53  spf_dns_server->name, domain,
54  SPF_strrrtype(rr_type), rr_type);
55  }
56 }
57 
58 static void
59 SPF_dns_debug_post(SPF_dns_server_t *spf_dns_server, SPF_dns_rr_t *spfrr)
60 {
61  if (spf_dns_server->debug) {
62  char ip4_buf[ INET_ADDRSTRLEN ];
63  char ip6_buf[ INET6_ADDRSTRLEN ];
64  int i;
65 
66  SPF_debugf("DNS[%s] found record", spf_dns_server->name);
67  SPF_debugf(" DOMAIN: %s TYPE: %s (%d)",
68  spfrr->domain,
69  SPF_strrrtype(spfrr->rr_type), spfrr->rr_type);
70  SPF_debugf(" TTL: %ld RR found: %d herrno: %d source: %s",
71  (long)spfrr->ttl, spfrr->num_rr, spfrr->herrno,
72  (spfrr->source
73  ? (spfrr->source->name
74  ? spfrr->source->name
75  : "(unnamed source)")
76  : "(null source)"));
77  for (i = 0; i < spfrr->num_rr; i++) {
78  switch (spfrr->rr_type) {
79  case ns_t_a:
80  SPF_debugf(" - A: %s",
81  inet_ntop(AF_INET, &(spfrr->rr[i]->a),
82  ip4_buf, sizeof(ip4_buf)));
83  break;
84 
85  case ns_t_ptr:
86  SPF_debugf(" - PTR: %s", spfrr->rr[i]->ptr);
87  break;
88 
89  case ns_t_mx:
90  SPF_debugf(" - MX: %s", spfrr->rr[i]->mx);
91  break;
92 
93  case ns_t_txt:
94  SPF_debugf(" - TXT: %s", spfrr->rr[i]->txt);
95  break;
96 
97  case ns_t_spf:
98  SPF_debugf(" - SPF: %s", spfrr->rr[i]->txt);
99  break;
100 
101  case ns_t_aaaa:
102  SPF_debugf(" - AAAA: %s",
103  inet_ntop(AF_INET6, &(spfrr->rr[i]->aaaa),
104  ip6_buf, sizeof(ip6_buf)));
105  break;
106 
107  default:
108  SPF_debugf(" - Unknown RR type");
109  break;
110  }
111  }
112  }
113 }
114 
115 void
116 SPF_dns_free(SPF_dns_server_t *spf_dns_server)
117 {
118  SPF_dns_server_t *layer_below;
119 
120  SPF_ASSERT_NOTNULL(spf_dns_server);
121  // SPF_ASSERT_NOTNULL(spf_dns_server->destroy);
122  layer_below = spf_dns_server->layer_below;
123 
124  /* If this is not set, we assume someone else knows, and will destroy it. */
125  if (spf_dns_server->destroy) {
126  spf_dns_server->destroy(spf_dns_server);
127  if (layer_below != NULL)
128  SPF_dns_free(layer_below);
129  }
130 }
131 
132 SPF_dns_rr_t *
133 SPF_dns_lookup(SPF_dns_server_t *spf_dns_server, const char *domain,
134  ns_type rr_type, int should_cache)
135 {
136  SPF_dns_rr_t *spfrr;
137 
138  SPF_ASSERT_NOTNULL(spf_dns_server);
139  SPF_dns_debug_pre(spf_dns_server, domain, rr_type, should_cache);
140  SPF_ASSERT_NOTNULL(spf_dns_server->lookup);
141  spfrr = spf_dns_server->lookup(spf_dns_server,
142  domain, rr_type, should_cache);
143  if (spfrr == NULL)
144  SPF_error( "SPF DNS layer return NULL during a lookup." );
145  SPF_dns_debug_post(spf_dns_server, spfrr);
146  return spfrr;
147 }
148 
149 SPF_dns_rr_t *
150 SPF_dns_rlookup(SPF_dns_server_t *spf_dns_server, struct in_addr ipv4,
151  ns_type rr_type, int should_cache)
152 {
153  char domain[ sizeof("111.222.333.444.in-addr.arpa") ];
154  union {
155  struct in_addr ipv4;
156  unsigned char x[4];
157  } tmp;
158 
159  /*
160  * make sure the scratch buffer is big enough
161  */
162  tmp.ipv4 = ipv4;
163 
164  snprintf(domain, sizeof(domain), "%d.%d.%d.%d.in-addr.arpa",
165  tmp.x[3], tmp.x[2], tmp.x[1], tmp.x[0]);
166 
167  return SPF_dns_lookup(spf_dns_server, domain, rr_type,should_cache);
168 }
169 
170 SPF_dns_rr_t *
171 SPF_dns_rlookup6(SPF_dns_server_t *spf_dns_server,
172  struct in6_addr ipv6, ns_type rr_type, int should_cache)
173 {
174  char domain[ sizeof(struct in6_addr) * 4 + sizeof(".ip6.arpa" ) + 1]; /* nibbles */
175  char *p, *p_end;
176  int i;
177 
178  p = domain;
179  p_end = p + sizeof( domain );
180 
181  for (i = sizeof(struct in6_addr) - 1; i >= 0; i--) {
182  p += snprintf(p, p_end - p, "%.1x.%.1x.",
183  ipv6.s6_addr[i] & 0xf,
184  ipv6.s6_addr[i] >> 4);
185  }
186 
187  /* squash the final '.' */
188  p += snprintf(p, p_end - p, "ip6.arpa");
189 
190  return SPF_dns_lookup(spf_dns_server, domain, rr_type, should_cache);
191 }
192 
193 
194 
195 /* XXX FIXME */
196 /*
197  * Set the SMTP client domain name
198  */
199 
205 char *
206 SPF_dns_get_client_dom( SPF_dns_server_t *spf_dns_server,
207  SPF_request_t *sr )
208 {
209  char *client_dom;
210  SPF_dns_rr_t *rr_ptr;
211  SPF_dns_rr_t *rr_a;
212  SPF_dns_rr_t *rr_aaaa;
213 
214  int i, j;
215 
216  int max_ptr;
217 
218  SPF_ASSERT_NOTNULL(spf_dns_server);
219  SPF_ASSERT_NOTNULL(sr);
220 
221 
222 /*
223  * The "p" macro expands to the validated domain name of the SMTP
224  * client. The validation procedure is described in section 5.4. If
225  * there are no validated domain names, the word "unknown" is
226  * substituted. If multiple validated domain names exist, the first one
227  * returned in the PTR result is chosen.
228  *
229  *
230  * sending-host_names := ptr_lookup(sending-host_IP);
231  * for each name in (sending-host_names) {
232  * IP_addresses := a_lookup(name);
233  * if the sending-host_IP is one of the IP_addresses {
234  * validated_sending-host_names += name;
235  * } }
236  */
237 
238  if ( sr->client_ver == AF_INET ) {
239  rr_ptr = SPF_dns_rlookup( spf_dns_server, sr->ipv4, ns_t_ptr, FALSE );
240 
241  max_ptr = rr_ptr->num_rr;
242  /* XXX TODO? Or irrelevant?
243  if (max_ptr > sr->max_dns_ptr)
244  max_ptr = sr->max_dns_ptr;
245  */
246  /* XXX do we want to report if this is exceeded and we
247  * might've missed a validated name because of that?
248  */
249  if (max_ptr > SPF_MAX_DNS_PTR)
250  max_ptr = SPF_MAX_DNS_PTR;
251 
252  for (i = 0; i < max_ptr; i++) {
253  rr_a = SPF_dns_lookup(spf_dns_server, rr_ptr->rr[i]->ptr, ns_t_a, FALSE);
254 
255  for (j = 0; j < rr_a->num_rr; j++) {
256  if (rr_a->rr[j]->a.s_addr == sr->ipv4.s_addr) {
257  client_dom = strdup(rr_ptr->rr[i]->ptr);
258  SPF_dns_rr_free(rr_ptr);
259  SPF_dns_rr_free(rr_a);
260  return client_dom;
261  }
262  }
263  SPF_dns_rr_free(rr_a);
264  }
265  SPF_dns_rr_free(rr_ptr);
266  }
267 
268  else if ( sr->client_ver == AF_INET6 ) {
269  rr_ptr = SPF_dns_rlookup6( spf_dns_server, sr->ipv6, ns_t_ptr, FALSE );
270 
271  max_ptr = rr_ptr->num_rr;
272  /*
273  if ( max_ptr > sr->max_dns_ptr )
274  max_ptr = sr->max_dns_ptr;
275  */
276  /* XXX do we want to report if this is exceeded and we
277  * might've missed a validated name because of that?
278  */
279  if ( max_ptr > SPF_MAX_DNS_PTR )
280  max_ptr = SPF_MAX_DNS_PTR;
281 
282  for( i = 0; i < max_ptr; i++ ) {
283  rr_aaaa = SPF_dns_lookup( spf_dns_server, rr_ptr->rr[i]->ptr, ns_t_aaaa, FALSE );
284 
285  for( j = 0; j < rr_aaaa->num_rr; j++ ) {
286  if ( memcmp( &rr_aaaa->rr[j]->aaaa, &sr->ipv6,
287  sizeof( sr->ipv6 ) ) == 0 ) {
288  client_dom = strdup( rr_ptr->rr[i]->ptr );
289  SPF_dns_rr_free( rr_ptr );
290  SPF_dns_rr_free( rr_aaaa );
291  return client_dom;
292  }
293  }
294  SPF_dns_rr_free( rr_aaaa );
295  }
296  SPF_dns_rr_free( rr_ptr );
297  }
298 
299  return strdup( "unknown" );
300 }
const char * SPF_strrrtype(ns_type rr_type)
Definition: spf_utils.c:163
#define ns_t_spf
Definition: spf_dns.h:89
void SPF_dns_rr_free(SPF_dns_rr_t *spfrr)
Definition: spf_dns_rr.c:114
#define NULL
Definition: spf_internal.h:28
#define FALSE
Definition: spf_internal.h:24
#define SPF_MAX_DNS_PTR
Definition: spf_internal.h:62
#define SPF_ASSERT_NOTNULL(x)
Definition: spf_log.h:118
#define SPF_error(errmsg)
Definition: spf_log.h:40
#define SPF_debugf
Definition: spf_log.h:80
ns_type
Definition: arpa_nameser.h:300
@ ns_t_ptr
Definition: arpa_nameser.h:313
@ ns_t_mx
Definition: arpa_nameser.h:316
@ ns_t_a
Definition: arpa_nameser.h:302
@ ns_t_txt
Definition: arpa_nameser.h:317
@ ns_t_aaaa
Definition: arpa_nameser.h:329
SPF_dns_rr_t * SPF_dns_rlookup6(SPF_dns_server_t *spf_dns_server, struct in6_addr ipv6, ns_type rr_type, int should_cache)
Definition: spf_dns.c:171
SPF_dns_rr_t * SPF_dns_rlookup(SPF_dns_server_t *spf_dns_server, struct in_addr ipv4, ns_type rr_type, int should_cache)
Definition: spf_dns.c:150
char * SPF_dns_get_client_dom(SPF_dns_server_t *spf_dns_server, SPF_request_t *sr)
Definition: spf_dns.c:206
void SPF_dns_free(SPF_dns_server_t *spf_dns_server)
Definition: spf_dns.c:116
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
struct in_addr a
Definition: spf_dns_rr.h:33
struct in6_addr aaaa
Definition: spf_dns_rr.h:37
SPF_dns_server_t * source
Definition: spf_dns_rr.h:70
SPF_dns_rr_data_t ** rr
Definition: spf_dns_rr.h:60
char * domain
Definition: spf_dns_rr.h:53
ns_type rr_type
Definition: spf_dns_rr.h:56
time_t ttl
Definition: spf_dns_rr.h:64
SPF_dns_stat_t herrno
Definition: spf_dns_rr.h:66