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
18
19 #ifndef INC_SPF_INTERNAL
20 #define INC_SPF_INTERNAL
21
22 #ifndef TRUE
23 #define TRUE 1
24 #define FALSE 0
25 #endif
26
27 #ifndef NULL
28 #define NULL ((void *)0)
29 #endif
30
31 #define array_elem(x) ((long int)(sizeof( x ) / sizeof( *x )))
32
33
34 /*
35 * misc macros to make the code look cleaner than it really is
36 */
37
38 #ifndef SPF_MAX_DNS_MECH
39 /**
40 * It is a bad idea to change this for two reasons.
41 *
42 * First, the obvious reason is the delays caused on the mail server
43 * you are running. DNS lookups that timeout can be *very* time
44 * consuming, and even successful DNS lookups can take 200-500ms.
45 * Many MTAs can't afford to wait long and even 2sec is pretty bad.
46 *
47 * The second, and more important reason, is the SPF records come from
48 * a third party which may be malicious. This third party can direct
49 * DNS lookups to be sent to anyone. If there isn't a limit, then it
50 * is easy for someone to create a distributed denial of service
51 * attack simply by sending a bunch of emails. Unlike the delays on
52 * your system caused by many DNS lookups, you might not even notice
53 * that you are being used as part of a DDoS attack.
54 */
55 #define SPF_MAX_DNS_MECH 10
56 #endif
57 #ifndef SPF_MAX_DNS_PTR
58 /**
59 * It is a bad idea to change this for the same reasons as mentioned
60 * above for SPF_MAX_DNS_MECH
61 */
62 #define SPF_MAX_DNS_PTR 10
63 #endif
64 #ifndef SPF_MAX_DNS_MX
65 /**
66 * It is a bad idea to change this for the same reasons as mentioned
67 * above for SPF_MAX_DNS_MECH
68 */
69 #define SPF_MAX_DNS_MX 10
70 #endif
71
72 #if 1
73 #define _ALIGN_SZ 4
_align_sz(size_t s)74 static inline size_t _align_sz(size_t s)
75 { return (s + (_ALIGN_SZ - 1 - (((s - 1) & (_ALIGN_SZ - 1))))); }
_align_ptr(char * s)76 static inline char * _align_ptr(char *s)
77 { return (s + (_ALIGN_SZ - 1 - ((((size_t)s - 1) & (_ALIGN_SZ - 1))))); }
78 #else
_align_sz(size_t s)79 static inline size_t _align_sz(size_t s) { return s; }
_align_ptr(char * s)80 static inline char * _align_ptr(char *s) { return s; }
81 #endif
82
83 #include "spf_record.h"
84
85 /* FIXME: need to make these network/compiler portable */
86 /* FIXME: Several of these duplicate each other. Bad. */
SPF_mech_data_len(SPF_mech_t * mech)87 static inline size_t SPF_mech_data_len( SPF_mech_t * mech )
88 { return (mech->mech_type == MECH_IP4)
89 ? sizeof( struct in_addr )
90 : (mech->mech_type == MECH_IP6)
91 ? sizeof( struct in6_addr )
92 : mech->mech_len; }
SPF_mech_next(SPF_mech_t * mech)93 static inline SPF_mech_t *SPF_mech_next( SPF_mech_t * mech )
94 { return (SPF_mech_t *)_align_ptr(
95 (char *)mech + sizeof(SPF_mech_t) + SPF_mech_data_len( mech )
96 ); }
SPF_mech_data(SPF_mech_t * mech)97 static inline SPF_data_t *SPF_mech_data( SPF_mech_t *mech )
98 { return (SPF_data_t *)( (char *)mech + sizeof(SPF_mech_t)); }
SPF_mech_end_data(SPF_mech_t * mech)99 static inline SPF_data_t *SPF_mech_end_data( SPF_mech_t *mech )
100 { return (SPF_data_t *)( (char *)SPF_mech_data(mech) +
101 SPF_mech_data_len( mech ));}
SPF_mech_ip4_data(SPF_mech_t * mech)102 static inline struct in_addr *SPF_mech_ip4_data( SPF_mech_t *mech )
103 { return (struct in_addr *)( (char *)mech + sizeof(SPF_mech_t)); }
SPF_mech_ip6_data(SPF_mech_t * mech)104 static inline struct in6_addr *SPF_mech_ip6_data( SPF_mech_t *mech )
105 { return (struct in6_addr *)( (char *)mech + sizeof(SPF_mech_t)); }
106
SPF_data_len(SPF_data_t * data)107 static inline size_t SPF_data_len( SPF_data_t *data )
108 { return sizeof(SPF_data_t) +
109 (data->ds.parm_type == PARM_STRING ? data->ds.len : 0); }
SPF_data_next(SPF_data_t * data)110 static inline SPF_data_t *SPF_data_next( SPF_data_t *data )
111 { return (SPF_data_t *)_align_ptr(
112 (char *)data + SPF_data_len(data)
113 ); }
SPF_data_str(SPF_data_t * data)114 static inline char *SPF_data_str( SPF_data_t *data )
115 { return (char *)data + sizeof(SPF_data_t); }
116
SPF_mod_len(SPF_mod_t * mod)117 static inline size_t SPF_mod_len( SPF_mod_t *mod )
118 { return _align_sz(sizeof(SPF_mod_t) + mod->name_len) + mod->data_len; }
SPF_mod_next(SPF_mod_t * mod)119 static inline SPF_mod_t *SPF_mod_next( SPF_mod_t *mod )
120 { return (SPF_mod_t *)_align_ptr(
121 (char *)mod + SPF_mod_len(mod)
122 ); }
SPF_mod_name(SPF_mod_t * mod)123 static inline char *SPF_mod_name( SPF_mod_t *mod )
124 { return (char *)mod + sizeof(SPF_mod_t); }
SPF_mod_data(SPF_mod_t * mod)125 static inline SPF_data_t *SPF_mod_data( SPF_mod_t *mod )
126 { return (SPF_data_t *)_align_ptr(
127 (char *)mod + sizeof(SPF_mod_t) + mod->name_len
128 ); }
SPF_mod_end_data(SPF_mod_t * mod)129 static inline SPF_data_t *SPF_mod_end_data( SPF_mod_t *mod )
130 { return (SPF_data_t *)((char *)SPF_mod_data(mod) + mod->data_len); }
131
SPF_macro_data_len(SPF_macro_t * mac)132 static inline size_t SPF_macro_data_len( SPF_macro_t * mac )
133 { return mac->macro_len; }
SPF_macro_data(SPF_macro_t * mac)134 static inline SPF_data_t *SPF_macro_data( SPF_macro_t * mac )
135 { return (SPF_data_t *)( (char *)mac + sizeof(SPF_macro_t)); }
136
137
138 char *SPF_sanitize( SPF_server_t *spf_server, char *str );
139
140 void SPF_print_sizeof(void);
141
142 /**
143 * A special purpose realloc for text buffers.
144 *
145 * It will allocate at least 64 bytes of storage, and memset the RAM
146 * to 0.
147 */
148 SPF_errcode_t SPF_recalloc(char **bufp, size_t *buflenp, size_t buflen) __attribute__((warn_unused_result));
149
150
151 /**
152 * A wrapper for reporting errors from sub-functions.
153 * SPF_errcode_t foo(int a) { ... }
154 * becomes:
155 * SPF_WRAP_FUNCTION(SPF_foo, (int a), (a)) { .... }
156 * As yet unused.
157 */
158 #define SPF_WRAP_FUNCTION(name, proto, args) \
159 SPF_errcode_t name proto { \
160 SPF_errcode_t err = name ## _real args; \
161 SPF_debug(#name " returns %d\n", err); \
162 return err; \
163 } \
164 SPF_errcode_t name ## _real proto
165
166 #endif
167