libspf2  1.2.10
spf_interpret.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 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
34 
35 #include <ctype.h>
36 
37 #include "spf.h"
38 #include "spf_dns.h"
39 #include "spf_internal.h"
40 #include "spf_dns_internal.h"
41 #include "spf_server.h"
42 
43 static SPF_errcode_t
44 SPF_i_set_explanation(SPF_response_t *spf_response)
45 {
46  SPF_server_t *spf_server;
47  SPF_request_t *spf_request;
48  SPF_record_t *spf_record;
49  SPF_errcode_t err;
50  char *buf;
51  size_t buflen;
52 
53  SPF_ASSERT_NOTNULL(spf_response);
54  spf_request = spf_response->spf_request;
55  SPF_ASSERT_NOTNULL(spf_request);
56  spf_server = spf_request->spf_server;
57  SPF_ASSERT_NOTNULL(spf_server);
58 
59  spf_record = spf_response->spf_record_exp;
60  SPF_ASSERT_NOTNULL(spf_record);
61 
62  if (spf_response->explanation)
63  free(spf_response->explanation);
64  spf_response->explanation = NULL;
65 
66  buflen = SPF_SMTP_COMMENT_SIZE + 1;
67  buf = malloc(buflen);
68  if (buf == NULL)
69  return SPF_E_NO_MEMORY;
70  memset(buf, '\0', buflen);
71 
72  err = SPF_request_get_exp(spf_server, spf_request,
73  spf_response, spf_record, &buf, &buflen);
74  if (err != SPF_E_SUCCESS) {
75  free(buf);
76  return err;
77  }
78 
79  spf_response->explanation = buf;
80 
81  return SPF_E_SUCCESS;
82 }
83 
84 static SPF_errcode_t
85 SPF_i_set_smtp_comment(SPF_response_t *spf_response)
86 {
87  SPF_server_t *spf_server;
88  SPF_request_t *spf_request;
89  SPF_errcode_t err;
90  char buf[SPF_SMTP_COMMENT_SIZE];
91 
92  SPF_ASSERT_NOTNULL(spf_response);
93  spf_request = spf_response->spf_request;
94  SPF_ASSERT_NOTNULL(spf_request);
95  spf_server = spf_request->spf_server;
96  SPF_ASSERT_NOTNULL(spf_server);
97 
98  if (spf_response->smtp_comment)
99  free(spf_response->smtp_comment);
100  spf_response->smtp_comment = NULL;
101 
102  /* smtp_comment = exp= + <why string> */
103  switch (spf_response->result) {
104  case SPF_RESULT_FAIL:
105  case SPF_RESULT_SOFTFAIL:
106  case SPF_RESULT_NEUTRAL:
107 
108  err = SPF_i_set_explanation(spf_response);
109  if (err != SPF_E_SUCCESS)
110  return err;
111 
112  memset(buf, '\0', sizeof(buf));
113  snprintf(buf, SPF_SMTP_COMMENT_SIZE, "%s : Reason: %s",
114  spf_response->explanation,
115  SPF_strreason(spf_response->reason));
116  buf[SPF_SMTP_COMMENT_SIZE - 1] = '\0';
117 
118  /* It doesn't really hurt much if this fails. */
119  spf_response->smtp_comment = strdup(buf);
120  if (! spf_response->smtp_comment)
121  return SPF_E_NO_MEMORY;
122 
123  break;
124  case SPF_RESULT_INVALID:
125  case SPF_RESULT_PASS:
128  case SPF_RESULT_NONE:
129  default:
130  break;
131  }
132 
133  return SPF_E_SUCCESS;
134 }
135 
136 static SPF_errcode_t
137 SPF_i_set_header_comment(SPF_response_t *spf_response)
138 {
139  SPF_server_t *spf_server;
140  SPF_request_t *spf_request;
141  char *spf_source;
142 
143  size_t len;
144 
145  char ip4_buf[ INET_ADDRSTRLEN ];
146  char ip6_buf[ INET6_ADDRSTRLEN ];
147  const char *ip;
148 
149  char *buf;
150  char *sender_dom;
151  char *p, *p_end;
152 
153  SPF_ASSERT_NOTNULL(spf_response);
154  spf_request = spf_response->spf_request;
155  SPF_ASSERT_NOTNULL(spf_request);
156  spf_server = spf_request->spf_server;
157  SPF_ASSERT_NOTNULL(spf_server);
158 
159  if (spf_response->header_comment)
160  free(spf_response->header_comment);
161  spf_response->header_comment = NULL;
162 
163  /* Is this cur_dom? */
164  sender_dom = spf_request->env_from_dp;
165  if (sender_dom == NULL)
166  sender_dom = spf_request->helo_dom;
167 
168  if ( spf_response->reason == SPF_REASON_LOCAL_POLICY ) {
169  spf_source = strdup( "local policy" );
170  }
171  else if ( spf_response->reason == SPF_REASON_2MX ) {
172  if ( spf_request->rcpt_to_dom == NULL || spf_request->rcpt_to_dom[0] == '\0' )
173  SPF_error( "RCPT TO domain is NULL" );
174 
175  spf_source = strdup( spf_request->rcpt_to_dom );
176  }
177  else if ( sender_dom == NULL ) {
178  spf_source = strdup( "unknown domain" );
179  }
180  else {
181  len = strlen( sender_dom ) + sizeof( "domain of " );
182  spf_source = malloc( len );
183  if ( spf_source )
184  snprintf( spf_source, len, "domain of %s", sender_dom );
185  }
186 
187  if ( spf_source == NULL )
188  return SPF_E_INTERNAL_ERROR;
189 
190  ip = NULL;
191  if ( spf_request->client_ver == AF_INET ) {
192  ip = inet_ntop( AF_INET, &spf_request->ipv4,
193  ip4_buf, sizeof( ip4_buf ) );
194  }
195  else if (spf_request->client_ver == AF_INET6 ) {
196  ip = inet_ntop( AF_INET6, &spf_request->ipv6,
197  ip6_buf, sizeof( ip6_buf ) );
198  }
199  if ( ip == NULL )
200  ip = "(unknown ip address)";
201 
202  len = strlen( SPF_request_get_rec_dom(spf_request) ) + strlen( spf_source ) + strlen( ip ) + 80;
203  buf = malloc( len );
204  if ( buf == NULL ) {
205  free( spf_source );
206  return SPF_E_INTERNAL_ERROR;
207  }
208 
209  p = buf;
210  p_end = p + len;
211 
212  /* create the stock header comment */
213  p += snprintf( p, p_end - p, "%s: ", SPF_request_get_rec_dom(spf_request) );
214 
215  switch(spf_response->result)
216  {
217  case SPF_RESULT_PASS:
218  if ( spf_response->reason == SPF_REASON_LOCALHOST )
219  snprintf( p, p_end - p, "localhost is always allowed." );
220  else if ( spf_response->reason == SPF_REASON_2MX )
221  snprintf( p, p_end - p, "message received from %s which is an MX secondary for %s.",
222  ip, spf_source );
223  else
224  snprintf( p, p_end - p, "%s designates %s as permitted sender",
225  spf_source, ip );
226  break;
227 
228  case SPF_RESULT_FAIL:
229  snprintf( p, p_end - p, "%s does not designate %s as permitted sender",
230  spf_source, ip );
231  break;
232 
233  case SPF_RESULT_SOFTFAIL:
234  snprintf( p, p_end - p, "transitioning %s does not designate %s as permitted sender",
235  spf_source, ip );
236  break;
237 
239  snprintf(p, p_end - p, "error in processing during lookup of %s: %s",
240  spf_source, SPF_strerror(spf_response->err));
241  break;
242 
243  case SPF_RESULT_NEUTRAL:
244  snprintf(p, p_end - p, "%s is neither permitted nor denied by %s",
245  ip, spf_source);
246  break;
247  case SPF_RESULT_NONE:
248  snprintf(p, p_end - p, "%s does not provide an SPF record",
249  spf_source);
250  break;
251 
253  snprintf(p, p_end - p, "encountered temporary error during SPF processing of %s",
254  spf_source );
255  break;
256 
257 
258  default:
259  snprintf( p, p_end - p, "error: unknown SPF result %d encountered while checking %s for %s",
260  spf_response->result, ip, spf_source );
261  break;
262  }
263 
264  if (spf_source)
265  free(spf_source);
266 
267  spf_response->header_comment = SPF_sanitize(spf_server, buf);
268 
269  return SPF_E_SUCCESS;
270 }
271 
272 static SPF_errcode_t
273 SPF_i_set_received_spf(SPF_response_t *spf_response)
274 {
275  SPF_server_t *spf_server;
276  SPF_request_t *spf_request;
277  char ip4_buf[ INET_ADDRSTRLEN ];
278  char ip6_buf[ INET6_ADDRSTRLEN ];
279  const char *ip;
280 
281  char *buf;
282  size_t buflen = SPF_RECEIVED_SPF_SIZE;
283  char *buf_value;
284 
285  char *p, *p_end;
286 
287  SPF_ASSERT_NOTNULL(spf_response);
288  spf_request = spf_response->spf_request;
289  SPF_ASSERT_NOTNULL(spf_request);
290  spf_server = spf_request->spf_server;
291  SPF_ASSERT_NOTNULL(spf_server);
292 
293  if (spf_response->received_spf)
294  free(spf_response->received_spf);
295  spf_response->received_spf = NULL;
296 
297  buf = malloc( buflen );
298  if ( buf == NULL )
299  return SPF_E_INTERNAL_ERROR;
300 
301  p = buf;
302  p_end = p + buflen;
303 
304  /* create the stock Received-SPF: header */
305 
306  p += snprintf( p, p_end - p, "Received-SPF: ");
307  buf_value = p;
308 
309  do { /* A prop for a structured goto called 'break' */
310  p += snprintf( p, p_end - p, "%s (%s)",
311  SPF_strresult( spf_response->result ),
312  spf_response->header_comment );
313  if ( p_end - p <= 0 ) break;
314 
315 
316 
317  /* add in the optional ip address keyword */
318  ip = NULL;
319  if ( spf_request->client_ver == AF_INET ) {
320  ip = inet_ntop( AF_INET, &spf_request->ipv4,
321  ip4_buf, sizeof( ip4_buf ) );
322  }
323  else if (spf_request->client_ver == AF_INET6 ) {
324  ip = inet_ntop( AF_INET6, &spf_request->ipv6,
325  ip6_buf, sizeof( ip6_buf ) );
326  }
327 
328  if ( ip != NULL ) {
329  p += snprintf( p, p_end - p, " client-ip=%s;", ip );
330  if ( p_end - p <= 0 ) break;
331  }
332 
333 
334  /* add in the optional envelope-from keyword */
335  if ( spf_request->env_from != NULL ) {
336  p += snprintf( p, p_end - p, " envelope-from=%s;", spf_request->env_from );
337  if ( p_end - p <= 0 ) break;
338  }
339 
340 
341  /* add in the optional helo domain keyword */
342  if ( spf_request->helo_dom != NULL ) {
343  p += snprintf( p, p_end - p, " helo=%s;", spf_request->helo_dom );
344  if ( p_end - p <= 0 ) break;
345  }
346 
347 
348  /* FIXME: Add in full compiler errors. */
349 #if 0
350  /* add in the optional compiler error keyword */
351  if ( output.err_msg != NULL ) {
352  p += snprintf( p, p_end - p, " problem=%s;", output.err_msg );
353  if ( p_end - p <= 0 ) break;
354  }
355  else if ( c_results.err_msg != NULL ) {
356  p += snprintf( p, p_end - p, " problem=%s;", c_results.err_msg );
357  if ( p_end - p <= 0 ) break;
358  }
359 #endif
360 
361  /* FIXME should the explanation string be included in the header? */
362 
363  /* FIXME should the header be reformated to include line breaks? */
364  } while(0);
365 
366  spf_response->received_spf = SPF_sanitize(spf_server, buf);
367  spf_response->received_spf_value = buf_value;
368 
369  return SPF_E_SUCCESS;
370 }
371 
372 
373 
374 #define DONE(result,reason,err) SPF_i_done(spf_response, result, reason, err)
375 #define DONE_TEMPERR(err) DONE(SPF_RESULT_TEMPERROR,SPF_REASON_NONE,err)
376 #define DONE_PERMERR(err) DONE(SPF_RESULT_PERMERROR,SPF_REASON_NONE,err)
377 #define DONE_MECH(result) DONE(result, SPF_REASON_MECH, SPF_E_SUCCESS)
378 
388 SPF_i_done(SPF_response_t *spf_response,
389  SPF_result_t result, SPF_reason_t reason, SPF_errcode_t err)
390 {
391  SPF_request_t *spf_request;
392  SPF_server_t *spf_server;
393 
394  SPF_ASSERT_NOTNULL(spf_response);
395  spf_request = spf_response->spf_request;
396  SPF_ASSERT_NOTNULL(spf_request);
397  spf_server = spf_request->spf_server;
398  SPF_ASSERT_NOTNULL(spf_server);
399 
400  spf_response->result = result;
401  spf_response->reason = reason;
402  spf_response->err = err;
403 
404  SPF_i_set_smtp_comment(spf_response);
405  SPF_i_set_header_comment(spf_response);
406  SPF_i_set_received_spf(spf_response);
407 
408  return err;
409 }
410 
411 /*
412  * FIXME: Everything before this line could go into a separate file.
413  */
414 
415 
416 
417 
418 #define INET_NTOP(af, src, dst, cnt) do { \
419  if (inet_ntop(af, src, dst, cnt) == NULL) \
420  snprintf(dst, cnt, "ip-error" ); \
421  } while(0)
422 
423 static int
424 SPF_i_mech_cidr(SPF_request_t *spf_request, SPF_mech_t *mech)
425 {
426  SPF_data_t *data;
427 
428  SPF_ASSERT_NOTNULL(mech);
429 
430  switch( mech->mech_type )
431  {
432  case MECH_IP4:
433  case MECH_IP6:
434  return mech->mech_len;
435  break;
436 
437  case MECH_A:
438  case MECH_MX:
439  data = SPF_mech_data( mech );
440  /* XXX this was <= but I think that was wrong. */
441  if ( data < SPF_mech_end_data( mech )
442  && data->dc.parm_type == PARM_CIDR )
443  {
444  if ( spf_request->client_ver == AF_INET )
445  return data->dc.ipv4;
446  else if ( spf_request->client_ver == AF_INET6 )
447  return data->dc.ipv6;
448  }
449  break;
450  }
451 
452  return 0;
453 }
454 
455 
456 
457 static int
458 SPF_i_match_ip4(SPF_server_t *spf_server,
459  SPF_request_t *spf_request,
460  SPF_mech_t *mech,
461  struct in_addr ipv4 )
462 {
463  char src_ip4_buf[ INET_ADDRSTRLEN ];
464  char dst_ip4_buf[ INET_ADDRSTRLEN ];
465  char mask_ip4_buf[ INET_ADDRSTRLEN ];
466 
467  struct in_addr src_ipv4;
468  int cidr, mask;
469 
470 
471  if ( spf_request->client_ver != AF_INET )
472  return FALSE;
473 
474  src_ipv4 = spf_request->ipv4;
475 
476  cidr = SPF_i_mech_cidr( spf_request, mech );
477  if ( cidr == 0 )
478  cidr = 32;
479  mask = 0xffffffff << (32 - cidr);
480  mask = htonl(mask);
481 
482  if (spf_server->debug) {
483  INET_NTOP(AF_INET, &src_ipv4.s_addr,
484  src_ip4_buf, sizeof(src_ip4_buf));
485  INET_NTOP(AF_INET, &ipv4.s_addr,
486  dst_ip4_buf, sizeof(dst_ip4_buf));
487  INET_NTOP(AF_INET, &mask,
488  mask_ip4_buf, sizeof(mask_ip4_buf));
489  SPF_debugf( "ip_match: %s == %s (/%d %s): %d",
490  src_ip4_buf, dst_ip4_buf, cidr, mask_ip4_buf,
491  (src_ipv4.s_addr & mask) == (ipv4.s_addr & mask));
492  }
493 
494  return (src_ipv4.s_addr & mask) == (ipv4.s_addr & mask);
495 }
496 
497 
498 static int
499 SPF_i_match_ip6(SPF_server_t *spf_server,
500  SPF_request_t *spf_request,
501  SPF_mech_t *mech,
502  struct in6_addr ipv6 )
503 {
504  char src_ip6_buf[ INET6_ADDRSTRLEN ];
505  char dst_ip6_buf[ INET6_ADDRSTRLEN ];
506 
507  struct in6_addr src_ipv6;
508  int cidr, cidr_save, mask;
509  int i;
510  int match;
511 
512  if ( spf_request->client_ver != AF_INET6 )
513  return FALSE;
514 
515  src_ipv6 = spf_request->ipv6;
516 
517  cidr = SPF_i_mech_cidr(spf_request, mech);
518  if ( cidr == 0 )
519  cidr = 128;
520  cidr_save = cidr;
521 
522  match = TRUE;
523  for( i = 0; i < array_elem( ipv6.s6_addr ) && match; i++ )
524  {
525  if ( cidr > 8 )
526  mask = 0xff;
527  else if ( cidr > 0 )
528  mask = (0xff << (8 - cidr)) & 0xff;
529  else
530  break;
531  cidr -= 8;
532 
533  match = (src_ipv6.s6_addr[i] & mask) == (ipv6.s6_addr[i] & mask);
534  }
535 
536  if (spf_server->debug) {
537  INET_NTOP(AF_INET6, &src_ipv6.s6_addr,
538  src_ip6_buf, sizeof(src_ip6_buf));
539  INET_NTOP(AF_INET6, &ipv6.s6_addr,
540  dst_ip6_buf, sizeof(dst_ip6_buf));
541  SPF_debugf( "ip_match: %s == %s (/%d): %d",
542  src_ip6_buf, dst_ip6_buf, cidr_save, match );
543  }
544 
545  return match;
546 }
547 
548 static int
549 SPF_i_match_domain(SPF_server_t *spf_server,
550  const char *hostname, const char *domain)
551 {
552  const char *hp;
553  size_t hlen;
554  size_t dlen;
555 
556  if (spf_server->debug)
557  SPF_debugf( "%s ?=? %s", hostname, domain );
558 
559  hlen = strlen(hostname);
560  dlen = strlen(domain);
561 
562  /* A host cannot be a member of a domain longer than it is. */
563  if (dlen > hlen)
564  return 0;
565 
566  /* The two may be equal? */
567  if (dlen == hlen)
568  return (strcasecmp(hostname, domain) == 0);
569 
570  /* The domain may match a trailing portion preceded by a dot. */
571  hp = hostname + (hlen - dlen);
572 
573  if (*(hp - 1) != '.')
574  return 0;
575 
576  return (strcasecmp(hp, domain) == 0);
577 }
578 
579 
580 /*
581  * Set cur_dom (to either sender or or helo_dom) before calling this.
582  */
583 
585 SPF_record_interpret(SPF_record_t *spf_record,
586  SPF_request_t *spf_request, SPF_response_t *spf_response,
587  int depth)
588 {
589  SPF_server_t *spf_server;
590 
591  /* Temporaries */
592  int i, j;
593  int m; /* Mechanism iterator */
594  SPF_mech_t *mech;
595  SPF_data_t *data;
596  SPF_data_t *data_end; /* XXX Replace with size_t data_len */
597 
598  /* Where to insert the local policy (whitelist) */
599  SPF_mech_t *local_policy; /* Not the local policy */
600  int found_all; /* A crappy temporary. */
601 
602  char *buf = NULL;
603  size_t buf_len = 0;
604  ns_type fetch_ns_type;
605  const char *lookup;
606 
607  SPF_dns_rr_t *rr_a;
608  SPF_dns_rr_t *rr_aaaa;
609  SPF_dns_rr_t *rr_ptr;
610  SPF_dns_rr_t *rr_mx;
611 
612  SPF_errcode_t err;
613 
614  SPF_dns_server_t*resolver;
615 
616  /* An SPF record for subrequests - replaces c_results */
617  SPF_record_t *spf_record_subr;
618 
619  SPF_response_t *save_spf_response;
620  SPF_response_t *spf_response_subr;
621  const char *save_cur_dom;
622 
623  struct in_addr addr4;
624  struct in6_addr addr6;
625 
626  int max_ptr;
627  int max_mx;
628  int max_exceeded;
629 
630  char ip4_buf[ INET_ADDRSTRLEN ];
631  char ip6_buf[ INET6_ADDRSTRLEN ];
632 
633 
634  /*
635  * make sure we were passed valid data to work with
636  */
637  SPF_ASSERT_NOTNULL(spf_record);
638  SPF_ASSERT_NOTNULL(spf_request);
639  SPF_ASSERT_NOTNULL(spf_response);
640  spf_server = spf_record->spf_server;
641  SPF_ASSERT_NOTNULL(spf_server);
642 
643  SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
644 
645  if (depth > 20)
647 
648  if ( spf_request->client_ver != AF_INET && spf_request->client_ver != AF_INET6 )
650 
651  if (spf_request->cur_dom == NULL)
653 
654 
655  /*
656  * localhost always gets a free ride
657  */
658 
659 #if 0
660  /* This should have been done already before we got here. */
661  if ( SPF_request_is_loopback( spf_request ) )
663 #endif
664 
665  /*
666  * Do some start up stuff if we haven't recursed yet
667  */
668 
669  local_policy = NULL;
670 
671  if ( spf_request->use_local_policy ) {
672  /*
673  * find the location for the whitelist execution
674  *
675  * Philip Gladstone says:
676  *
677  * I think that the localpolicy should only be inserted if the
678  * final mechanism is '-all', and it should be inserted after
679  * the last mechanism which is not '-'.
680  *
681  * Thus for the case of 'v=spf1 +a +mx -all', this would be
682  * interpreted as 'v=spf1 +a +mx +localpolicy -all'. Whereas
683  * 'v=spf1 -all' would remain the same (no non-'-'
684  * mechanism). 'v=spf1 +a +mx -exists:%stuff -all' would
685  * become 'v=spf1 +a +mx +localpolicy -exists:%stuff -all'.
686  */
687 
688  if ( spf_server->local_policy ) {
689  mech = spf_record->mech_first;
690 
691  found_all = FALSE;
692  for(m = 0; m < spf_record->num_mech; m++)
693  {
694  if ( mech->mech_type == MECH_ALL
695  && (mech->prefix_type == PREFIX_FAIL
696  || mech->prefix_type == PREFIX_UNKNOWN
697  || mech->prefix_type == PREFIX_SOFTFAIL
698  )
699  )
700  found_all = TRUE;
701 
702  if ( mech->prefix_type != PREFIX_FAIL
703  && mech->prefix_type != PREFIX_SOFTFAIL
704  )
705  local_policy = mech;
706 
707  mech = SPF_mech_next( mech );
708  }
709 
710  if ( !found_all )
711  local_policy = NULL;
712  }
713 
714  }
715 
716 
717  /*
718  * evaluate the mechanisms
719  */
720 
721 #define SPF_ADD_DNS_MECH() do { spf_response->num_dns_mech++; } while(0)
722 
723 #define SPF_MAYBE_SKIP_CIDR() \
724  do { \
725  if ( data < data_end && data->dc.parm_type == PARM_CIDR ) \
726  data = SPF_data_next( data ); \
727  } while(0)
728 
729 #define SPF_GET_LOOKUP_DATA() \
730  do { \
731  if ( data == data_end ) \
732  lookup = spf_request->cur_dom; \
733  else { \
734  err = SPF_record_expand_data( spf_server, \
735  spf_request, spf_response, \
736  data, ((char *)data_end - (char *)data), \
737  &buf, &buf_len ); \
738  if (err == SPF_E_NO_MEMORY) { \
739  SPF_FREE_LOOKUP_DATA(); \
740  return DONE_TEMPERR(err); \
741  } \
742  if (err) { \
743  SPF_FREE_LOOKUP_DATA(); \
744  return DONE_PERMERR(err); \
745  } \
746  lookup = buf; \
747  } \
748  } while(0)
749 #define SPF_FREE_LOOKUP_DATA() \
750  do { if (buf != NULL) { free(buf); buf = NULL; } } while(0)
751 
752 
753  resolver = spf_server->resolver;
754 
755  mech = spf_record->mech_first;
756  for (m = 0; m < spf_record->num_mech; m++) {
757 
758  /* This is as good a place as any. */
759  /* XXX Rip this out and put it into a macro which can go into inner loops. */
760  if (spf_response->num_dns_mech > spf_server->max_dns_mech) {
763  }
764 
765  data = SPF_mech_data(mech);
766  data_end = SPF_mech_end_data(mech);
767 
768  switch (mech->mech_type) {
769  case MECH_A:
773 
774  if (spf_request->client_ver == AF_INET)
775  fetch_ns_type = ns_t_a;
776  else
777  fetch_ns_type = ns_t_aaaa;
778 
779  rr_a = SPF_dns_lookup(resolver, lookup, fetch_ns_type, TRUE);
780 
781  if (spf_server->debug)
782  SPF_debugf("found %d A records for %s (herrno: %d)",
783  rr_a->num_rr, lookup, rr_a->herrno);
784 
785  if (rr_a->herrno == TRY_AGAIN) {
786  SPF_dns_rr_free(rr_a);
788  return DONE_TEMPERR(SPF_E_DNS_ERROR); /* REASON_MECH */
789  }
790 
791  for (i = 0; i < rr_a->num_rr; i++) {
792  /* XXX Should this be hoisted? */
793  if (rr_a->rr_type != fetch_ns_type)
794  continue;
795 
796  if (spf_request->client_ver == AF_INET) {
797  if (SPF_i_match_ip4(spf_server, spf_request, mech, rr_a->rr[i]->a)) {
798  SPF_dns_rr_free(rr_a);
800  return DONE_MECH(mech->prefix_type);
801  }
802  }
803  else {
804  if (SPF_i_match_ip6(spf_server, spf_request, mech, rr_a->rr[i]->aaaa)) {
805  SPF_dns_rr_free(rr_a);
807  return DONE_MECH(mech->prefix_type);
808  }
809  }
810  }
811 
812  SPF_dns_rr_free(rr_a);
813  break;
814 
815  case MECH_MX:
819 
820  rr_mx = SPF_dns_lookup(resolver, lookup, ns_t_mx, TRUE);
821 
822  if (spf_server->debug)
823  SPF_debugf("found %d MX records for %s (herrno: %d)",
824  rr_mx->num_rr, lookup, rr_mx->herrno);
825 
826  if (rr_mx->herrno == TRY_AGAIN) {
827  SPF_dns_rr_free(rr_mx);
830  }
831 
832  /* The maximum number of MX records we will inspect. */
833  max_mx = rr_mx->num_rr;
834  max_exceeded = 0;
835  if (max_mx > spf_server->max_dns_mx) {
836  max_exceeded = 1;
837  max_mx = SPF_server_get_max_dns_mx(spf_server);
838  }
839 
840  for (j = 0; j < max_mx; j++) {
841  /* XXX Should this be hoisted? */
842  if (rr_mx->rr_type != ns_t_mx)
843  continue;
844 
845  if (spf_request->client_ver == AF_INET)
846  fetch_ns_type = ns_t_a;
847  else
848  fetch_ns_type = ns_t_aaaa;
849 
850  rr_a = SPF_dns_lookup(resolver, rr_mx->rr[j]->mx,
851  fetch_ns_type, TRUE );
852 
853  if (spf_server->debug)
854  SPF_debugf("%d: found %d A records for %s (herrno: %d)",
855  j, rr_a->num_rr, rr_mx->rr[j]->mx, rr_a->herrno);
856  if (rr_a->herrno == TRY_AGAIN) {
857  SPF_dns_rr_free(rr_mx);
858  SPF_dns_rr_free(rr_a);
861  }
862 
863  for (i = 0; i < rr_a->num_rr; i++) {
864  /* XXX Should this be hoisted? */
865  if (rr_a->rr_type != fetch_ns_type)
866  continue;
867 
868  if (spf_request->client_ver == AF_INET) {
869  if (SPF_i_match_ip4(spf_server, spf_request, mech,
870  rr_a->rr[i]->a)) {
871  SPF_dns_rr_free(rr_mx);
872  SPF_dns_rr_free(rr_a);
874  return DONE(mech->prefix_type, SPF_REASON_MECH,
875  SPF_E_SUCCESS);
876  }
877  }
878  else {
879  if (SPF_i_match_ip6(spf_server, spf_request, mech,
880  rr_a->rr[i]->aaaa)) {
881  SPF_dns_rr_free(rr_mx);
882  SPF_dns_rr_free(rr_a);
884  return DONE(mech->prefix_type, SPF_REASON_MECH,
885  SPF_E_SUCCESS);
886  }
887  }
888  }
889  SPF_dns_rr_free(rr_a);
890  }
891 
892  SPF_dns_rr_free( rr_mx );
893  if (max_exceeded) {
896  }
897  break;
898 
899  case MECH_PTR:
902 
903  if (spf_request->client_ver == AF_INET) {
904  rr_ptr = SPF_dns_rlookup(resolver,
905  spf_request->ipv4, ns_t_ptr, TRUE);
906 
907  if (spf_server->debug) {
908  INET_NTOP(AF_INET, &spf_request->ipv4.s_addr,
909  ip4_buf, sizeof(ip4_buf));
910  SPF_debugf("got %d PTR records for %s (herrno: %d)",
911  rr_ptr->num_rr, ip4_buf, rr_ptr->herrno);
912  }
913 
914  if (rr_ptr->herrno == TRY_AGAIN) {
915  SPF_dns_rr_free(rr_ptr);
918  }
919 
920 
921  /* The maximum number of PTR records we will inspect. */
922  max_ptr = rr_ptr->num_rr;
923  max_exceeded = 0;
924  if (max_ptr > spf_server->max_dns_ptr) {
925  max_exceeded = 1;
926  max_ptr = SPF_server_get_max_dns_ptr(spf_server);
927  }
928 
929  for (i = 0; i < max_ptr; i++) {
930  /* XXX MX has a 'continue' case here which should be hoisted. */
931 
932  rr_a = SPF_dns_lookup(resolver,
933  rr_ptr->rr[i]->ptr, ns_t_a, TRUE);
934 
935  if (spf_server->debug)
936  SPF_debugf( "%d: found %d A records for %s (herrno: %d)",
937  i, rr_a->num_rr, rr_ptr->rr[i]->ptr, rr_a->herrno );
938  if (rr_a->herrno == TRY_AGAIN) {
939  SPF_dns_rr_free(rr_ptr);
940  SPF_dns_rr_free(rr_a);
942  return DONE_TEMPERR( SPF_E_DNS_ERROR );
943  }
944 
945  for (j = 0; j < rr_a->num_rr; j++) {
946  /* XXX MX has a 'continue' case here which should be hoisted. */
947 
948  if (spf_server->debug) {
949  INET_NTOP(AF_INET, &rr_a->rr[j]->a.s_addr,
950  ip4_buf, sizeof(ip4_buf));
951  SPF_debugf("%d: %d: found %s",
952  i, j, ip4_buf);
953  }
954 
955  if (rr_a->rr[j]->a.s_addr ==
956  spf_request->ipv4.s_addr) {
957  if (SPF_i_match_domain(spf_server,
958  rr_ptr->rr[i]->ptr, lookup)) {
959  SPF_dns_rr_free(rr_ptr);
960  SPF_dns_rr_free(rr_a);
962  return DONE_MECH(mech->prefix_type);
963  }
964  }
965  }
966  SPF_dns_rr_free(rr_a);
967  }
968  SPF_dns_rr_free(rr_ptr);
969 
970  if (max_exceeded) {
973  }
974  }
975 
976  else if ( spf_request->client_ver == AF_INET6 ) {
977  rr_ptr = SPF_dns_rlookup6(resolver,
978  spf_request->ipv6, ns_t_ptr, TRUE);
979 
980  if ( spf_server->debug ) {
981  INET_NTOP( AF_INET6, &spf_request->ipv6.s6_addr,
982  ip6_buf, sizeof( ip6_buf ) );
983  SPF_debugf( "found %d PTR records for %s (herrno: %d)",
984  rr_ptr->num_rr, ip6_buf, rr_ptr->herrno );
985  }
986  if( rr_ptr->herrno == TRY_AGAIN ) {
987  SPF_dns_rr_free(rr_ptr);
989  return DONE_TEMPERR( SPF_E_DNS_ERROR );
990  }
991 
992 
993  max_ptr = rr_ptr->num_rr;
994  max_exceeded = 0;
995  if (max_ptr > spf_server->max_dns_ptr) {
996  max_ptr = SPF_server_get_max_dns_ptr(spf_server);
997  max_exceeded = 1;
998  }
999 
1000  for (i = 0; i < max_ptr; i++) {
1001  /* XXX MX has a 'continue' case here which should be hoisted. */
1002 
1003  rr_aaaa = SPF_dns_lookup(resolver,
1004  rr_ptr->rr[i]->ptr, ns_t_aaaa, TRUE);
1005 
1006  if ( spf_server->debug )
1007  SPF_debugf("%d: found %d AAAA records for %s (herrno: %d)",
1008  i, rr_aaaa->num_rr, rr_ptr->rr[i]->ptr, rr_aaaa->herrno);
1009  if( rr_aaaa->herrno == TRY_AGAIN ) {
1010  SPF_dns_rr_free(rr_ptr);
1011  SPF_dns_rr_free(rr_aaaa);
1013  return DONE_TEMPERR( SPF_E_DNS_ERROR );
1014  }
1015 
1016  for( j = 0; j < rr_aaaa->num_rr; j++ ) {
1017  /* XXX MX has a 'continue' case here which should be hoisted. */
1018  if ( spf_server->debug ) {
1019  INET_NTOP(AF_INET6, &rr_aaaa->rr[j]->aaaa.s6_addr,
1020  ip6_buf, sizeof(ip6_buf));
1021  SPF_debugf( "%d: %d: found %s",
1022  i, j, ip6_buf );
1023  }
1024 
1025  if (memcmp(&rr_aaaa->rr[j]->aaaa,
1026  &spf_request->ipv6,
1027  sizeof(spf_request->ipv6)) == 0) {
1028  if (SPF_i_match_domain(spf_server,
1029  rr_ptr->rr[i]->ptr, lookup)) {
1030  SPF_dns_rr_free( rr_ptr );
1031  SPF_dns_rr_free(rr_aaaa);
1033  return DONE_MECH( mech->prefix_type );
1034  }
1035  }
1036  }
1037  SPF_dns_rr_free(rr_aaaa);
1038  }
1039  SPF_dns_rr_free(rr_ptr);
1040 
1041  if (max_exceeded) {
1044  }
1045  }
1046 
1047 
1048  break;
1049 
1050  case MECH_INCLUDE:
1051  case MECH_REDIRECT:
1052  SPF_ADD_DNS_MECH();
1053 
1054  err = SPF_record_expand_data(spf_server,
1055  spf_request, spf_response,
1056  SPF_mech_data(mech), SPF_mech_data_len(mech),
1057  &buf, &buf_len );
1058  if ( err == SPF_E_NO_MEMORY ) {
1060  return DONE_TEMPERR( err );
1061  }
1062  if ( err ) {
1064  return DONE_PERMERR( err );
1065  }
1066  lookup = buf;
1067 
1068  /* XXX Maintain a stack depth here. Limit at 10. */
1069  if (strcmp(lookup, spf_request->cur_dom) == 0) {
1071  return DONE_PERMERR( SPF_E_RECURSIVE );
1072  }
1073 
1074  /*
1075  * get the (compiled) SPF record
1076  */
1077 
1078  spf_record_subr = NULL;
1079  /* Remember to reset this. */
1080  save_cur_dom = spf_request->cur_dom;
1081  spf_request->cur_dom = lookup;
1082  err = SPF_server_get_record(spf_server, spf_request,
1083  spf_response, &spf_record_subr);
1084 
1085  if ( spf_server->debug > 0 )
1086  SPF_debugf( "include/redirect: got SPF record: %s",
1087  SPF_strerror( err ) );
1088 
1089  if (err != SPF_E_SUCCESS) {
1090  spf_request->cur_dom = save_cur_dom;
1091  if (spf_record_subr)
1092  SPF_record_free(spf_record_subr);
1094  if (err == SPF_E_DNS_ERROR)
1095  return DONE_TEMPERR( err );
1096  else
1097  return DONE_PERMERR( err );
1098  }
1099 
1100  SPF_ASSERT_NOTNULL(spf_record_subr);
1101 
1102  /*
1103  * If we are a redirect which is not within the scope
1104  * of any include.
1105  */
1106  if (mech->mech_type == MECH_REDIRECT) {
1107  save_spf_response = NULL;
1108  if (spf_response->spf_record_exp == spf_record)
1109  spf_response->spf_record_exp = spf_record_subr;
1110  SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
1111  }
1112  else {
1113  save_spf_response = spf_response;
1114  spf_response = SPF_response_new(spf_request);
1115  if (! spf_response) {
1116  if (spf_record_subr)
1117  SPF_record_free(spf_record_subr);
1119  return DONE_TEMPERR(SPF_E_NO_MEMORY);
1120  }
1121  spf_response->spf_record_exp = spf_record;
1122  SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
1123  }
1124  /*
1125  * find out whether this configuration passes
1126  */
1127  err = SPF_record_interpret(spf_record_subr,
1128  spf_request, spf_response, depth + 1);
1129  spf_request->cur_dom = save_cur_dom;
1130  /* Now, if we were a redirect, the child called done()
1131  * and used spf_record_exp. In that case, we need not
1132  * worry that spf_record_subr is invalid after the free.
1133  * If we were not a redirect, then spf_record_subr
1134  * is still the record it was in the first place.
1135  * Thus we do not need to reset it now. */
1136  SPF_record_free(spf_record_subr);
1137  spf_record_subr = NULL;
1138 
1139  if ( spf_server->debug > 0 )
1140  SPF_debugf( "include/redirect: executed SPF record: %s result: %s reason: %s",
1141  SPF_strerror( err ),
1142  SPF_strresult( spf_response->result ),
1143  SPF_strreason( spf_response->reason ) );
1144  if (mech->mech_type == MECH_REDIRECT) {
1146  return err; /* One way or the other */
1147  }
1148  else { // if (spf_response->result != SPF_RESULT_INVALID) {
1149  /* Set everything up properly again. */
1150  spf_response_subr = spf_response;
1151  spf_response = save_spf_response;
1152  save_spf_response = NULL;
1153 
1154  /* Rewrite according to prefix of include */
1155  switch (SPF_response_result(spf_response_subr)) {
1156  case SPF_RESULT_PASS:
1157  /* Pass */
1159  SPF_response_free(spf_response_subr);
1160  return DONE_MECH( mech->prefix_type );
1161 
1162  case SPF_RESULT_FAIL:
1163  case SPF_RESULT_SOFTFAIL:
1164  case SPF_RESULT_NEUTRAL:
1165  /* No match */
1166  SPF_response_free(spf_response_subr);
1167  break;
1168 
1169  case SPF_RESULT_TEMPERROR:
1170  /* Generate TempError */
1171  err = SPF_response_errcode(spf_response_subr);
1173  SPF_response_free(spf_response_subr);
1174  return DONE_TEMPERR( err );
1175 
1176  case SPF_RESULT_NONE:
1177  /* Generate PermError */
1179  SPF_response_free(spf_response_subr);
1181  case SPF_RESULT_PERMERROR:
1182  case SPF_RESULT_INVALID:
1183  /* Generate PermError */
1184  err = SPF_response_errcode(spf_response_subr);
1186  SPF_response_free(spf_response_subr);
1187  return DONE_PERMERR( err );
1188 
1189  }
1190 #if 0
1192  return err; /* The sub-interpret called done() */
1193 #endif
1194  }
1195 
1196  break;
1197 
1198  case MECH_IP4:
1199  memcpy(&addr4, SPF_mech_ip4_data(mech), sizeof(addr4));
1200  if ( SPF_i_match_ip4( spf_server, spf_request, mech, addr4 ) ) {
1202  return DONE_MECH( mech->prefix_type );
1203  }
1204  break;
1205 
1206  case MECH_IP6:
1207  memcpy(&addr6, SPF_mech_ip6_data(mech), sizeof(addr6));
1208  if ( SPF_i_match_ip6( spf_server, spf_request, mech, addr6 ) ) {
1210  return DONE_MECH( mech->prefix_type );
1211  }
1212  break;
1213 
1214  case MECH_EXISTS:
1215  SPF_ADD_DNS_MECH();
1216 
1217  err = SPF_record_expand_data(spf_server,
1218  spf_request, spf_response,
1219  SPF_mech_data(mech),SPF_mech_data_len(mech),
1220  &buf, &buf_len);
1221  if (err != SPF_E_SUCCESS) {
1223  return DONE_TEMPERR( err );
1224  }
1225  lookup = buf;
1226 
1227  rr_a = SPF_dns_lookup(resolver, lookup, ns_t_a, FALSE );
1228 
1229  if ( spf_server->debug )
1230  SPF_debugf( "found %d A records for %s (herrno: %d)",
1231  rr_a->num_rr, lookup, rr_a->herrno );
1232 
1233  if( rr_a->herrno == TRY_AGAIN ) {
1234  SPF_dns_rr_free(rr_a);
1236  return DONE_TEMPERR(SPF_E_DNS_ERROR);
1237  }
1238  if ( rr_a->num_rr > 0 ) {
1239  SPF_dns_rr_free(rr_a);
1241  return DONE_MECH(mech->prefix_type);
1242  }
1243 
1244  SPF_dns_rr_free(rr_a);
1245  break;
1246 
1247  case MECH_ALL:
1249  if (mech->prefix_type == PREFIX_UNKNOWN)
1251  return DONE_MECH(mech->prefix_type);
1252  break;
1253 
1254  default:
1257  break;
1258  }
1259 
1260  /*
1261  * execute the local policy
1262  */
1263 
1264  if ( mech == local_policy ) {
1265  err = SPF_record_interpret(spf_server->local_policy,
1266  spf_request, spf_response, depth + 1);
1267 
1268  if ( spf_server->debug > 0 )
1269  SPF_debugf( "local_policy: executed SPF record: %s result: %s reason: %s",
1270  SPF_strerror( err ),
1271  SPF_strresult( spf_response->result ),
1272  SPF_strreason( spf_response->reason ) );
1273 
1274  if (spf_response->result != SPF_RESULT_INVALID) {
1276  return err;
1277  }
1278  }
1279 
1280  mech = SPF_mech_next( mech );
1281  }
1282 
1284  /* falling off the end is the same as ?all */
1286 }
SPF_response_new
SPF_response_t * SPF_response_new(SPF_request_t *spf_request)
Definition: spf_response.c:37
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_E_RECURSIVE
@ SPF_E_RECURSIVE
Definition: spf_response.h:152
SPF_REASON_NONE
@ SPF_REASON_NONE
Definition: spf_response.h:101
SPF_response_result
SPF_result_t SPF_response_result(SPF_response_t *rp)
Definition: spf_response.c:135
SPF_request_is_loopback
int SPF_request_is_loopback(SPF_request_t *sr)
Definition: spf_request.c:212
PARM_CIDR
#define PARM_CIDR
Definition: spf_record.h:99
ns_type
ns_type
Definition: arpa_nameser.h:300
SPF_server_get_record
SPF_errcode_t SPF_server_get_record(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_record_t **spf_recordp)
Definition: spf_server.c:316
MECH_MX
#define MECH_MX
Definition: spf_record.h:164
SPF_E_INCLUDE_RETURNED_NONE
@ SPF_E_INCLUDE_RETURNED_NONE
Definition: spf_response.h:151
SPF_errcode_t
SPF_errcode_t
Definition: spf_response.h:119
SPF_RECEIVED_SPF_SIZE
#define SPF_RECEIVED_SPF_SIZE
Definition: spf.h:48
ns_t_aaaa
@ ns_t_aaaa
Definition: arpa_nameser.h:329
SPF_RESULT_PERMERROR
@ SPF_RESULT_PERMERROR
Definition: spf_response.h:88
TRY_AGAIN
#define TRY_AGAIN
Definition: spf_dns.h:104
SPF_strreason
const char * SPF_strreason(SPF_reason_t reason)
Definition: spf_utils.c:128
SPF_dns_rr_free
void SPF_dns_rr_free(SPF_dns_rr_t *spfrr)
Definition: spf_dns_rr.c:114
SPF_RESULT_SOFTFAIL
@ SPF_RESULT_SOFTFAIL
Definition: spf_response.h:84
SPF_mech_t
Definition: spf_record.h:175
SPF_dns_rr_data_t::mx
char mx[1]
Definition: spf_dns_rr.h:35
SPF_reason_t
SPF_reason_t
Definition: spf_response.h:100
SPF_request_get_rec_dom
const char * SPF_request_get_rec_dom(SPF_request_t *sr)
Definition: spf_request.c:131
SPF_dns_lookup
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
SPF_mech_t::mech_type
unsigned char mech_type
Definition: spf_record.h:177
SPF_RESULT_NONE
@ SPF_RESULT_NONE
Definition: spf_response.h:86
spf.h
SPF_debugf
#define SPF_debugf
Definition: spf_log.h:80
SPF_dns_rr_t
Definition: spf_dns_rr.h:51
SPF_dns_rlookup
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
SPF_E_DNS_ERROR
@ SPF_E_DNS_ERROR
Definition: spf_response.h:146
MECH_IP4
#define MECH_IP4
Definition: spf_record.h:167
SPF_dns_rr_data_t::ptr
char ptr[1]
Definition: spf_dns_rr.h:34
PREFIX_UNKNOWN
#define PREFIX_UNKNOWN
Definition: spf_record.h:157
MECH_REDIRECT
#define MECH_REDIRECT
Definition: spf_record.h:171
ns_t_ptr
@ ns_t_ptr
Definition: arpa_nameser.h:313
SPF_i_done
SPF_errcode_t SPF_i_done(SPF_response_t *spf_response, SPF_result_t result, SPF_reason_t reason, SPF_errcode_t err)
Definition: spf_interpret.c:388
SPF_E_SUCCESS
@ SPF_E_SUCCESS
Definition: spf_response.h:120
spf_dns_internal.h
SPF_error
#define SPF_error(errmsg)
Definition: spf_log.h:40
SPF_sanitize
char * SPF_sanitize(SPF_server_t *spf_server, char *str)
Definition: spf_utils.c:54
SPF_RESULT_NEUTRAL
@ SPF_RESULT_NEUTRAL
Definition: spf_response.h:81
MECH_INCLUDE
#define MECH_INCLUDE
Definition: spf_record.h:166
SPF_SMTP_COMMENT_SIZE
#define SPF_SMTP_COMMENT_SIZE
Definition: spf.h:47
TRUE
#define TRUE
Definition: spf_internal.h:23
array_elem
#define array_elem(x)
Definition: spf_internal.h:31
SPF_response_free
void SPF_response_free(SPF_response_t *rp)
Definition: spf_response.c:53
spf_dns.h
SPF_result_t
SPF_result_t
Definition: spf_response.h:79
SPF_data_t
Definition: spf_record.h:142
SPF_REASON_LOCALHOST
@ SPF_REASON_LOCALHOST
Definition: spf_response.h:103
SPF_dns_rr_t::num_rr
int num_rr
Definition: spf_dns_rr.h:59
DONE
#define DONE(result, reason, err)
Definition: spf_interpret.c:374
FALSE
#define FALSE
Definition: spf_internal.h:24
SPF_REASON_DEFAULT
@ SPF_REASON_DEFAULT
Definition: spf_response.h:106
spf_internal.h
SPF_dns_rr_data_t::a
struct in_addr a
Definition: spf_dns_rr.h:33
SPF_REASON_2MX
@ SPF_REASON_2MX
Definition: spf_response.h:107
SPF_REASON_LOCAL_POLICY
@ SPF_REASON_LOCAL_POLICY
Definition: spf_response.h:104
SPF_RESULT_FAIL
@ SPF_RESULT_FAIL
Definition: spf_response.h:83
SPF_E_NO_MEMORY
@ SPF_E_NO_MEMORY
Definition: spf_response.h:121
PREFIX_FAIL
#define PREFIX_FAIL
Definition: spf_record.h:154
DONE_MECH
#define DONE_MECH(result)
Definition: spf_interpret.c:377
SPF_E_INTERNAL_ERROR
@ SPF_E_INTERNAL_ERROR
Definition: spf_response.h:130
MECH_EXISTS
#define MECH_EXISTS
Definition: spf_record.h:169
SPF_response_errcode
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
Definition: spf_response.c:147
DONE_TEMPERR
#define DONE_TEMPERR(err)
Definition: spf_interpret.c:375
SPF_record_interpret
SPF_errcode_t SPF_record_interpret(SPF_record_t *spf_record, SPF_request_t *spf_request, SPF_response_t *spf_response, int depth)
Definition: spf_interpret.c:585
SPF_REASON_MECH
@ SPF_REASON_MECH
Definition: spf_response.h:105
ns_t_mx
@ ns_t_mx
Definition: arpa_nameser.h:316
SPF_strresult
const char * SPF_strresult(SPF_result_t result)
Definition: spf_utils.c:81
SPF_E_UNKNOWN_MECH
@ SPF_E_UNKNOWN_MECH
Definition: spf_response.h:126
SPF_data_t::dc
SPF_data_cidr_t dc
Definition: spf_record.h:145
SPF_mech_t::prefix_type
unsigned char prefix_type
Definition: spf_record.h:176
SPF_dns_rr_t::rr
SPF_dns_rr_data_t ** rr
Definition: spf_dns_rr.h:60
SPF_dns_rr_t::rr_type
ns_type rr_type
Definition: spf_dns_rr.h:56
NULL
#define NULL
Definition: spf_internal.h:28
SPF_request_get_exp
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_server.h
SPF_record_free
void SPF_record_free(SPF_record_t *rp)
Definition: spf_record.c:63
MECH_IP6
#define MECH_IP6
Definition: spf_record.h:168
MECH_ALL
#define MECH_ALL
Definition: spf_record.h:170
SPF_data_cidr_t::ipv6
unsigned char ipv6
Definition: spf_record.h:134
SPF_ASSERT_NOTNULL
#define SPF_ASSERT_NOTNULL(x)
Definition: spf_log.h:118
SPF_RESULT_TEMPERROR
@ SPF_RESULT_TEMPERROR
Definition: spf_response.h:87
MECH_A
#define MECH_A
Definition: spf_record.h:163
MECH_PTR
#define MECH_PTR
Definition: spf_record.h:165
SPF_E_BIG_DNS
@ SPF_E_BIG_DNS
Definition: spf_response.h:138
SPF_GET_LOOKUP_DATA
#define SPF_GET_LOOKUP_DATA()
SPF_dns_rr_data_t::aaaa
struct in6_addr aaaa
Definition: spf_dns_rr.h:37
DONE_PERMERR
#define DONE_PERMERR(err)
Definition: spf_interpret.c:376
SPF_E_NOT_CONFIG
@ SPF_E_NOT_CONFIG
Definition: spf_response.h:145
INET_NTOP
#define INET_NTOP(af, src, dst, cnt)
Definition: spf_interpret.c:418
SPF_mech_t::mech_len
unsigned short mech_len
Definition: spf_record.h:178
SPF_ADD_DNS_MECH
#define SPF_ADD_DNS_MECH()
spf_sys_config.h
SPF_RESULT_PASS
@ SPF_RESULT_PASS
Definition: spf_response.h:82
SPF_FREE_LOOKUP_DATA
#define SPF_FREE_LOOKUP_DATA()
SPF_dns_rr_t::herrno
SPF_dns_stat_t herrno
Definition: spf_dns_rr.h:66
PREFIX_SOFTFAIL
#define PREFIX_SOFTFAIL
Definition: spf_record.h:155
SPF_data_cidr_t::ipv4
unsigned char ipv4
Definition: spf_record.h:133
SPF_dns_rlookup6
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_data_cidr_t::parm_type
unsigned char parm_type
Definition: spf_record.h:132
SPF_MAYBE_SKIP_CIDR
#define SPF_MAYBE_SKIP_CIDR()
ns_t_a
@ ns_t_a
Definition: arpa_nameser.h:302
SPF_record_expand_data
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