1 /* 2 ** Copyright (c) 2012-2015, 2018, 2021, The Trusted Domain Project. 3 ** All rights reserved. 4 */ 5 6 #ifndef OPENDMARC_INTERNAL_H 7 #define OPENDMARC_INTERNAL_H 8 9 #if HAVE_CONFIG_H 10 # include "build-config.h" 11 #endif 12 13 # if HAVE_CTYPE_H 14 # include <ctype.h> 15 # endif 16 # if HAVE_ERRNO_H 17 # include <errno.h> 18 # endif 19 # if HAVE_POLL_H 20 # include <poll.h> 21 # endif 22 # if HAVE_FCNTL_H 23 # include <fcntl.h> 24 # endif 25 # ifdef sun 26 # include <libgen.h> 27 # endif 28 # if HAVE_MEMORY_H 29 # include <memory.h> 30 # endif 31 # if HAVE_STDIO_H 32 # include <stdio.h> 33 # endif 34 # if HAVE_STDLIB_H 35 # include <stdlib.h> 36 # endif 37 # if HAVE_STRING_H 38 # include <string.h> 39 # endif 40 # if HAVE_SYS_SOCKET_H 41 # include <sys/socket.h> 42 # endif 43 # if HAVE_SYS_STAT_H 44 # include <sys/stat.h> 45 # endif 46 # if HAVE_SYS_TYPES_H 47 # include <sys/types.h> 48 # endif 49 # if HAVE_SYSEXITS_H 50 # include <sysexits.h> 51 # endif 52 # if HAVE_SYSLOG_H 53 # include <syslog.h> 54 # endif 55 # if TM_IN_SYS_TIME 56 # include <sys/time.h> 57 # else 58 # include <time.h> 59 # endif 60 # if TIME_WITH_SYS_TIME && TM_IN_SYS_TIME 61 # include <time.h> 62 # endif 63 # if HAVE_UNISTD_H 64 # include <unistd.h> 65 # endif 66 # if HAVE_NETDB_H 67 # include <netdb.h> 68 # endif 69 # if HAVE_NETINET_IN_H 70 # include <netinet/in.h> 71 # endif 72 # if HAVE_SYS_PARAM_H 73 # include <sys/param.h> 74 # endif 75 # if HAVE_ARPA_INET_H 76 # include <arpa/inet.h> 77 # endif 78 # if HAVE_ARPA_NAMESER_H 79 # include <arpa/nameser.h> 80 # endif 81 # if HAVE_ARPA_NAMESER_COMPAT_H 82 # include <arpa/nameser_compat.h> 83 # endif 84 # if HAVE_RESOLV_H 85 # include <resolv.h> 86 # endif 87 # if HAVE_SIGNAL_H 88 # include <signal.h> 89 # endif 90 # if HAVE_PTHREAD_H || HAVE_PTHREAD 91 # include <pthread.h> 92 # endif 93 94 # ifndef UNDEFINED 95 # define UNDEFINED (-1) 96 # endif 97 # ifndef TRUE 98 # define TRUE (1) 99 # endif 100 # ifndef FALSE 101 # define FALSE (0) 102 # endif 103 # ifndef MAYBE 104 # define MAYBE (2) 105 # endif 106 # define bool int 107 108 #ifndef NETDB_INTERNAL 109 # define NETDB_INTERNAL (-1) 110 #endif 111 112 #ifndef NETDB_SUCCESS 113 # define NETDB_SUCCESS (0) 114 #endif 115 116 /* 117 ** Beware that some Linux versions incorrectly define 118 ** MAXHOSTNAMELEN as 64, but DNS lookups require a length 119 ** of 255. So we don't use MAXHOSTNAMELEN here. Instead 120 ** we use our own MAXDNSHOSTNAME. 121 */ 122 #define MAXDNSHOSTNAME 256 123 124 /* 125 ** Maximum number of DNS retries when resolving CNAMES, etc. 126 */ 127 128 #define DNS_MAX_RETRIES 6 129 130 /***************************************************************************** 131 ** DMARC_POLICY_T -- The opaque context for the library. 132 ** Memory needs to be allocated and freed. 133 *****************************************************************************/ 134 135 typedef struct dmarc_policy_t { 136 /* 137 * Supplied information 138 */ 139 u_char * ip_addr; /* Input: connected IPV4 or IPV6 address */ 140 int ip_type; /* Input: IPv4 or IPv6 */ 141 u_char * spf_domain; /* Input: Domain used to verify SPF */ 142 int spf_origin; /* Input: was domain MAIL From: or HELO for SPF check */ 143 int spf_outcome; /* Input: What was the outcome of the SPF check */ 144 u_char * spf_human_outcome; /* Input: What was the outcome of the SPF check in human readable form */ 145 int dkim_final; /* This is the best record found */ 146 u_char * dkim_domain; /* Input: The d= domain */ 147 u_char * dkim_selector; /* Input: The s= selector */ 148 int dkim_outcome; /* Input: What was the outcome of the DKIM check */ 149 u_char * dkim_human_outcome; /* Input: What was the outcome of the DKIM check in human readable form */ 150 151 /* 152 * Computed outcomes 153 */ 154 int dkim_alignment; 155 int spf_alignment; 156 157 /* 158 * Computed Organizational domain, if subdomain lacked a record. 159 */ 160 u_char * from_domain; /* Input: From: header domain */ 161 u_char * organizational_domain; 162 163 /* 164 * Found in the _dmarc record or supplied to us. 165 */ 166 int h_error; /* Zero if found, else DNS error */ 167 int adkim; 168 int aspf; 169 int p; 170 int sp; 171 int pct; 172 int rf; 173 uint32_t ri; 174 int rua_cnt; 175 u_char ** rua_list; 176 int ruf_cnt; 177 u_char ** ruf_list; 178 int fo; 179 } DMARC_POLICY_T; 180 #ifndef OPENDMARC_POLICY_C 181 # define OPENDMARC_POLICY_C 1 182 #endif /* ! OPENDMARC_POLICY_C */ 183 184 185 /* dmarc_dns.c */ 186 char * dmarc_dns_get_record(char *domain, int *reply, char *got_txtbuf, size_t got_txtlen); 187 188 /* opendmarc_hash.c */ 189 typedef struct entry_bucket { 190 struct entry_bucket *previous; 191 struct entry_bucket *next; 192 char *key; 193 void *data; 194 time_t timestamp; 195 } OPENDMARC_HASH_BUCKET; 196 197 typedef struct { 198 OPENDMARC_HASH_BUCKET *bucket; 199 # if HAVE_PTHREAD_H || HAVE_PTHREAD 200 pthread_mutex_t mutex; 201 # endif 202 } OPENDMARC_HASH_SHELF; 203 204 #define OPENDMARC_MIN_SHELVES_LG2 4 205 #define OPENDMARC_MIN_SHELVES (1 << OPENDMARC_MIN_SHELVES_LG2) 206 207 /* 208 * max * sizeof internal_entry must fit into size_t. 209 * assumes internal_entry is <= 32 (2^5) bytes. 210 */ 211 #define OPENDMARC_MAX_SHELVES_LG2 (sizeof (size_t) * 8 - 1 - 5) 212 #define OPENDMARC_MAX_SHELVES ((size_t)1 << OPENDMARC_MAX_SHELVES_LG2) 213 214 typedef struct { 215 OPENDMARC_HASH_SHELF *table; 216 size_t tablesize; 217 void (*freefunct)(void *); 218 } OPENDMARC_HASH_CTX; 219 220 #define OPENDMARC_DEFAULT_HASH_TABLESIZE (2048) 221 222 OPENDMARC_HASH_CTX * opendmarc_hash_init(size_t tablesize); 223 OPENDMARC_HASH_CTX * opendmarc_hash_shutdown(OPENDMARC_HASH_CTX *hctx); 224 void opendmarc_hash_set_callback(OPENDMARC_HASH_CTX *hctx, void (*callback)(void *)); 225 void * opendmarc_hash_lookup(OPENDMARC_HASH_CTX *hctx, char *string, void *data, size_t datalen); 226 int opendmarc_hash_drop(OPENDMARC_HASH_CTX *hctx, char *string); 227 int opendmarc_hash_expire(OPENDMARC_HASH_CTX *hctx, time_t age); 228 229 /* opendmarc_tld.c */ 230 int opendmarc_tld_read_file(char *path_fname, char *commentstring, char *drop, char *except); 231 int opendmarc_get_tld(u_char *domain, u_char *tld, size_t tld_len); 232 int opendmarc_reverse_domain(u_char *domain, u_char *buf, size_t buflen); 233 void opendmarc_tld_shutdown(void); 234 235 /* opendmarc_util.c */ 236 u_char ** opendmarc_util_pushargv(u_char *str, u_char **ary, int *cnt); 237 u_char ** opendmarc_util_clearargv(u_char **ary); 238 u_char ** opendmarc_util_dupe_argv(u_char **ary); 239 u_char * opendmarc_util_cleanup(u_char *str, u_char *buf, size_t buflen); 240 u_char * opendmarc_util_finddomain(u_char *raw, u_char *buf, size_t buflen); 241 char ** opendmarc_util_freenargv(char **ary, int *num); 242 char ** opendmarc_util_pushnargv(char *str, char **ary, int *num); 243 char * opendmarc_util_ultoa(unsigned long val, char *buffer, size_t bufferlen); 244 245 /* opendmarc_policy.c */ 246 void opendmarc_policy_library_dns_hook(int *nscountp, struct sockaddr_in *nsaddr_list); 247 248 #if WITH_SPF 249 250 #if HAVE_SPF2_H 251 #include "spf.h" 252 typedef struct spf_context_struct { 253 SPF_server_t * spf_server; 254 SPF_request_t * spf_request; 255 SPF_response_t * spf_response; 256 SPF_result_t spf_result; 257 char mailfrom_addr[512]; 258 char mailfrom_domain[256]; 259 char helo_domain[256]; 260 } SPF_CTX_T; 261 int opendmarc_spf2_test(char *ip_address, char *mail_from_domain, char *helo_domain, char *spf_record, int softfail_okay_flag, char *human_readable, size_t human_readable_len, int *used_mfrom); 262 263 #else /* not HAVE_SPF2_H */ 264 265 /* opendmarc_spf.c and opendmarc_spf_dns.c */ 266 #define MAX_SPF_RECURSION (10) 267 typedef struct spf_context_struct { 268 int nlines; 269 char * lines[MAX_SPF_RECURSION+2]; 270 int status; 271 int in_token; 272 char mailfrom_addr[512]; 273 char helo_domain[256]; 274 char mailfrom_domain[256]; 275 char validated_domain[256]; 276 char ip_address[32]; 277 char spf_record[BUFSIZ *2]; 278 char ** iplist; 279 int ipcount; 280 char exp_buf[512]; 281 int did_get_exp; 282 } SPF_CTX_T; 283 int opendmarc_spf_test(char *ip_address, char *mail_from_domain, char *helo_domain, char *spf_record, int softfail_okay_flag, char *human_readable, size_t human_readable_len, int *used_mfrom); 284 char ** opendmarc_spf_dns_lookup_a(char *domain, char **ary, int *cnt); 285 char ** opendmarc_spf_dns_lookup_mx(char *domain, char **ary, int *cnt); 286 char ** opendmarc_spf_dns_lookup_mx_domain(char *domain, char **ary, int *cnt); 287 char ** opendmarc_spf_dns_lookup_ptr(char *ip, char **ary, int *cnt); 288 int opendmarc_spf_dns_cidr_address(char *addr, u_long *hi, u_long *lo); 289 int opendmarc_spf_dns_does_domain_exist(char *domain, int *reply); 290 char * opendmarc_spf_dns_get_record(char *domain, int *reply, char *txt, size_t txtlen, char *cname, size_t cnamelen, int spfcheck); 291 int opendmarc_spf_dns_does_domain_exist(char *domain, int *reply); 292 char * opendmarc_spf_dns_get_record(char *domain, int *reply, char *txt, size_t txtlen, char *cname, size_t cnamelen, int spfcheck); 293 int opendmarc_spf_ipv6_cidr_check(char *ipv6_str, char *cidr_string); 294 int opendmarc_spf_cidr_address(uint32_t ip, char *cidr_addr); 295 SPF_CTX_T * opendmarc_spf_alloc_ctx(); 296 SPF_CTX_T * opendmarc_spf_free_ctx(SPF_CTX_T *spfctx); 297 int opendmarc_spf_status_to_pass(int status, int none_pass); 298 int opendmarc_spf_specify_mailfrom(SPF_CTX_T *spfctx, char *mailfrom, size_t mailfrom_len, int *use_domain); 299 int opendmarc_spf_specify_helo_domain(SPF_CTX_T *spfctx, char *helo_domain, size_t helo_domain_len); 300 int opendmarc_spf_specify_ip_address(SPF_CTX_T *spfctx, char *ip_address, size_t ip_address_len); 301 int opendmarc_spf_specify_record(SPF_CTX_T *spfctx, char *spf_record, size_t spf_record_length); 302 int opendmarc_spf_parse(SPF_CTX_T *spfctx, int dns_count, char *xbuf, size_t xbuf_len); 303 const char * opendmarc_spf_status_to_msg(SPF_CTX_T *spfctx, int status); 304 #endif /* HAVE_SPF2_H */ 305 306 #endif /* WITH_SPF */ 307 308 #endif /* OPENDMARC_INTERNAL_H */ 309