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