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 #ifndef INC_SPF_RESPONSE 17 #define INC_SPF_RESPONSE 18 19 /** 20 * @file 21 * 22 * Results from an SPF check 23 * 24 * The results of the SPF check (as defined by the official SPF spec) 25 * 26 * To quote from doc/draft-mengwong-spf-00.txt Section 3: 27 * 28 * 3. SPF Record Evaluation 29 * 30 * An SPF client evaluates an SPF record and produces one of seven 31 * results: 32 * 33 * None: The domain does not publish SPF data. 34 * 35 * Neutral (?): The SPF client MUST proceed as if a domain did not 36 * publish SPF data. This result occurs if the domain explicitly 37 * specifies a "?" value, or if processing "falls off the end" of 38 * the SPF record. 39 * 40 * Pass (+): the message meets the publishing domain's definition of 41 * legitimacy. MTAs proceed to apply local policy and MAY accept or 42 * reject the message accordingly. 43 * 44 * Fail (-): the message does not meet a domain's definition of 45 * legitimacy. MTAs MAY reject the message using a permanent 46 * failure reply code. (Code 550 is RECOMMENDED. See RFC2821 47 * section 7.1.) 48 * 49 * Softfail (~): the message does not meet a domain's strict 50 * definition of legitimacy, but the domain cannot confidently state 51 * that the message is a forgery. MTAs SHOULD accept the message 52 * but MAY subject it to a higher transaction cost, deeper scrutiny, 53 * or an unfavourable score. 54 * 55 * There are two error conditions, one temporary and one permanent. 56 * 57 * Error: indicates an error during lookup; an MTA MAY reject the 58 * message using a transient failure code, such as 450. 59 * 60 * Unknown: indicates incomplete processing: an MTA MUST proceed as 61 * if a domain did not publish SPF data. 62 * 63 * When SPF-aware SMTP receivers accept a message, they SHOULD prepend a 64 * Received-SPF header. See section 6. 65 * 66 * SPF clients MUST use the algorithm described in this section 67 * or its functional equivalent. 68 * 69 * If an SPF client encounters a syntax error in an 70 * SPF record, it must terminate processing and return a result 71 * of "unknown". 72 * 73 * 74 * note: SPF_RESULT_* values are constrained by the internal PREFIX_* values 75 */ 76 77 78 typedef 79 enum SPF_result_enum { 80 SPF_RESULT_INVALID = 0, /**< We should never return this. */ 81 SPF_RESULT_NEUTRAL, 82 SPF_RESULT_PASS, 83 SPF_RESULT_FAIL, 84 SPF_RESULT_SOFTFAIL, 85 86 SPF_RESULT_NONE, 87 SPF_RESULT_TEMPERROR, 88 SPF_RESULT_PERMERROR 89 } SPF_result_t; 90 91 /** 92 * The reason that the result was returned 93 * 94 * This is what triggered the SPF result. Usually, it is a mechanism in the 95 * SPF record that causes the result, but if it was something else, the 96 * calling program will often want to take a different action or issue 97 * a different message. 98 */ 99 typedef 100 enum SPF_reason_enum { 101 SPF_REASON_NONE = 0 102 , SPF_REASON_FAILURE 103 , SPF_REASON_LOCALHOST /**< localhost always gets a free ride */ 104 , SPF_REASON_LOCAL_POLICY /**< local policy caused the match */ 105 , SPF_REASON_MECH /**< mechanism caused the match */ 106 , SPF_REASON_DEFAULT /**< ran off the end of the rec */ 107 , SPF_REASON_2MX /**< sent from a secondary MX */ 108 } SPF_reason_t; 109 110 /** 111 * error codes returned by various SPF functions. (including SPF_compile() 112 * and SPF_id2str(), spf_result(), etc.). 113 * 114 * The function SPF_strerror() will return a longer explanation of these 115 * errors. 116 */ 117 118 typedef 119 enum SPF_errcode_t { 120 SPF_E_SUCCESS = 0 /**< No errors */ 121 , SPF_E_NO_MEMORY /**< Out of memory */ 122 , SPF_E_NOT_SPF /**< Could not find a valid SPF record */ 123 , SPF_E_SYNTAX /**< Syntax error */ 124 , SPF_E_MOD_W_PREF /**< Modifiers can not have prefixes */ 125 , SPF_E_INVALID_CHAR /**< Invalid character found */ 126 , SPF_E_UNKNOWN_MECH /**< Unknown mechanism found */ 127 , SPF_E_INVALID_OPT /**< Invalid option found */ 128 , SPF_E_INVALID_CIDR /**< Invalid CIDR length */ 129 , SPF_E_MISSING_OPT /**< Required option is missing */ 130 , SPF_E_INTERNAL_ERROR /**< Internal programming error */ 131 , SPF_E_INVALID_ESC /**< Invalid %-escape character */ 132 , SPF_E_INVALID_VAR /**< Invalid macro variable */ 133 , SPF_E_BIG_SUBDOM /**< Subdomain truncation depth too large */ 134 , SPF_E_INVALID_DELIM /**< Invalid delimiter character */ 135 , SPF_E_BIG_STRING /**< Option string too long */ 136 , SPF_E_BIG_MECH /**< Too many mechanisms */ 137 , SPF_E_BIG_MOD /**< Too many modifiers */ 138 , SPF_E_BIG_DNS /**< Mechanisms used too many DNS lookups */ 139 , SPF_E_INVALID_IP4 /**< Invalid IPv4 address literal */ 140 , SPF_E_INVALID_IP6 /**< Invalid IPv6 address literal */ 141 , SPF_E_INVALID_PREFIX /**< Invalid mechanism prefix */ 142 , SPF_E_RESULT_UNKNOWN /**< SPF result is \"unknown\" */ 143 , SPF_E_UNINIT_VAR /**< Uninitialized variable */ 144 , SPF_E_MOD_NOT_FOUND /**< Modifier not found */ 145 , SPF_E_NOT_CONFIG /**< Not configured */ 146 , SPF_E_DNS_ERROR /**< DNS lookup failure */ 147 , SPF_E_BAD_HOST_IP /**< Invalid hostname (an IP address?) */ 148 , SPF_E_BAD_HOST_TLD /**< Hostname has a missing or invalid TLD */ 149 , SPF_E_MECH_AFTER_ALL /**< Mechanisms found after the \"all:\" 150 mechanism will be ignored */ 151 , SPF_E_INCLUDE_RETURNED_NONE /**< If an include recursive query returns none it's a perm error */ 152 , SPF_E_RECURSIVE /**< Recursive include */ 153 , SPF_E_MULTIPLE_RECORDS /**< Multiple SPF or TXT records found */ 154 } SPF_errcode_t; 155 156 typedef 157 struct SPF_error_struct 158 { 159 SPF_errcode_t code; 160 char *message; 161 char is_error; 162 } SPF_error_t; 163 164 typedef struct SPF_response_struct SPF_response_t; 165 166 #include "spf.h" 167 #include "spf_request.h" 168 169 struct SPF_response_struct { 170 /* Structure variables */ 171 SPF_request_t *spf_request; 172 SPF_record_t *spf_record_exp; 173 174 /* The answer itself. */ 175 SPF_result_t result; 176 SPF_reason_t reason; 177 SPF_errcode_t err; 178 179 char *received_spf; 180 char *received_spf_value; 181 char *header_comment; 182 char *smtp_comment; 183 char *explanation; 184 185 /* The errors */ 186 SPF_error_t *errors; 187 unsigned short errors_size; /**< Allocated */ 188 unsigned short errors_length; /**< Used */ 189 unsigned short num_errors; /**< Excluding warnings */ 190 191 /* Stuff which lets us get there. */ 192 int num_dns_mech; 193 }; 194 195 196 SPF_response_t *SPF_response_new(SPF_request_t *spf_request); 197 void SPF_response_free(SPF_response_t *rp); 198 SPF_response_t *SPF_response_combine(SPF_response_t *main, 199 SPF_response_t *r2mx); 200 201 /* Query functions for elements of the result */ 202 SPF_result_t SPF_response_result(SPF_response_t *rp); 203 SPF_reason_t SPF_response_reason(SPF_response_t *rp); 204 SPF_errcode_t SPF_response_errcode(SPF_response_t *rp); 205 const char *SPF_response_get_received_spf(SPF_response_t *rp); 206 const char *SPF_response_get_received_spf_value(SPF_response_t*rp); 207 const char *SPF_response_get_header_comment(SPF_response_t *rp); 208 const char *SPF_response_get_smtp_comment(SPF_response_t *rp); 209 const char *SPF_response_get_explanation(SPF_response_t *rp); 210 211 /** How many warnings were generated? */ 212 int SPF_response_messages(SPF_response_t *rp); 213 /** How many errors were generated? */ 214 int SPF_response_errors(SPF_response_t *rp); 215 /** Errors + warnings */ 216 int SPF_response_warnings(SPF_response_t *rp); 217 /** Returns an individual message */ 218 SPF_error_t *SPF_response_message(SPF_response_t *rp, int idx); 219 220 SPF_errcode_t SPF_error_code(SPF_error_t *err); 221 const char * SPF_error_message(SPF_error_t *err); 222 char SPF_error_errorp(SPF_error_t *err); 223 224 /** Internal functions for adding errors. */ 225 226 SPF_errcode_t SPF_response_add_error_ptr(SPF_response_t *rp, 227 SPF_errcode_t code, 228 const char *text, const char *tptr, 229 const char *format, ...); 230 SPF_errcode_t SPF_response_add_error_idx(SPF_response_t *rp, 231 SPF_errcode_t code, 232 const char *text, int idx, 233 const char *format, ...); 234 SPF_errcode_t SPF_response_add_error(SPF_response_t *rp, 235 SPF_errcode_t code, 236 const char *format, ...); 237 SPF_errcode_t SPF_response_add_warn_ptr(SPF_response_t *rp, 238 SPF_errcode_t code, 239 const char *text, const char *tptr, 240 const char *format, ...); 241 SPF_errcode_t SPF_response_add_warn_idx(SPF_response_t *rp, 242 SPF_errcode_t code, 243 const char *text, int idx, 244 const char *format, ...); 245 SPF_errcode_t SPF_response_add_warn(SPF_response_t *rp, 246 SPF_errcode_t code, 247 const char *format, ...); 248 249 #endif 250