libspf2
1.2.10
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of either: 00004 * 00005 * a) The GNU Lesser General Public License as published by the Free 00006 * Software Foundation; either version 2.1, or (at your option) any 00007 * later version, 00008 * 00009 * OR 00010 * 00011 * b) The two-clause BSD license. 00012 * 00013 * These licenses can be found with the distribution in the file LICENSES 00014 */ 00015 00016 #include "spf_sys_config.h" 00017 00018 #ifdef STDC_HEADERS 00019 # include <stdio.h> /* stdin / stdout */ 00020 # include <stdlib.h> /* malloc / free */ 00021 #endif 00022 00023 #ifdef HAVE_STRING_H 00024 # include <string.h> /* strstr / strdup */ 00025 #else 00026 # ifdef HAVE_STRINGS_H 00027 # include <strings.h> /* strstr / strdup */ 00028 # endif 00029 #endif 00030 00031 00032 #include "spf.h" 00033 #include "spf_dns.h" 00034 #include "spf_response.h" 00035 00036 SPF_response_t * 00037 SPF_response_new(SPF_request_t *spf_request) 00038 { 00039 SPF_response_t *rp; 00040 00041 rp = (SPF_response_t *)malloc(sizeof(SPF_response_t)); 00042 if (! rp) 00043 return rp; 00044 memset(rp, 0, sizeof(SPF_response_t)); 00045 00046 rp->spf_request = spf_request; 00047 rp->result = SPF_RESULT_INVALID; 00048 00049 return rp; 00050 } 00051 00052 void 00053 SPF_response_free(SPF_response_t *rp) 00054 { 00055 int i; 00056 00057 if (rp->received_spf) 00058 free(rp->received_spf); 00059 /* Don't free received_spf_value - it points into received_spf */ 00060 if (rp->header_comment) 00061 free(rp->header_comment); 00062 if (rp->smtp_comment) 00063 free(rp->smtp_comment); 00064 if (rp->explanation) 00065 free(rp->explanation); 00066 00067 if (rp->errors) { 00068 for (i = 0; i < rp->errors_length; i++) { 00069 free(rp->errors[i].message); 00070 } 00071 free(rp->errors); 00072 } 00073 00074 free(rp); 00075 } 00076 00077 static SPF_response_t * 00078 SPF_response_choose(SPF_response_t *yes, SPF_response_t *no) 00079 { 00080 SPF_response_free(no); 00081 return yes; 00082 } 00083 00084 /* 00085 * This is rather a guess-and-fiddle routine which tries to pick 00086 * the best of both worlds. It doesn't currently deal with error 00087 * messages at all. 00088 */ 00089 SPF_response_t * 00090 SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx) 00091 { 00092 switch (SPF_response_result(main)) { 00093 case SPF_RESULT_INVALID: 00094 /* If the main failed entirely, use the secondary */ 00095 return SPF_response_choose(r2mx, main); 00096 00097 case SPF_RESULT_PASS: 00098 /* If the main passed, use main */ 00099 return SPF_response_choose(main, r2mx); 00100 00101 case SPF_RESULT_NEUTRAL: 00102 /* If the main is neutral: */ 00103 switch (SPF_response_result(r2mx)) { 00104 case SPF_RESULT_PASS: 00105 /* Use the secondary if it passed */ 00106 return SPF_response_choose(r2mx, main); 00107 default: 00108 /* Otherwise just use the main */ 00109 return SPF_response_choose(main, r2mx); 00110 } 00111 00112 case SPF_RESULT_FAIL: 00113 /* If the main failed, use the secondary */ 00114 return SPF_response_choose(r2mx, main); 00115 00116 case SPF_RESULT_TEMPERROR: 00117 case SPF_RESULT_PERMERROR: 00118 case SPF_RESULT_SOFTFAIL: 00119 default: 00120 /* If the main is peculiar, including softfail: */ 00121 switch (SPF_response_result(r2mx)) { 00122 case SPF_RESULT_PASS: 00123 case SPF_RESULT_NEUTRAL: 00124 case SPF_RESULT_SOFTFAIL: 00125 /* Use the secondary if it didn't fail */ 00126 return SPF_response_choose(r2mx, main); 00127 default: 00128 /* Otherwise just use the main */ 00129 return SPF_response_choose(main, r2mx); 00130 } 00131 } 00132 } 00133 00134 SPF_result_t 00135 SPF_response_result(SPF_response_t *rp) 00136 { 00137 return rp->result; 00138 } 00139 00140 SPF_reason_t 00141 SPF_response_reason(SPF_response_t *rp) 00142 { 00143 return rp->reason; 00144 } 00145 00146 SPF_errcode_t 00147 SPF_response_errcode(SPF_response_t *rp) 00148 { 00149 return rp->err; 00150 } 00151 00152 const char * 00153 SPF_response_get_received_spf(SPF_response_t *rp) 00154 { 00155 return rp->received_spf; 00156 } 00157 00158 const char * 00159 SPF_response_get_received_spf_value(SPF_response_t *rp) 00160 { 00161 return rp->received_spf_value; 00162 } 00163 00164 const char * 00165 SPF_response_get_header_comment(SPF_response_t *rp) 00166 { 00167 return rp->header_comment; 00168 } 00169 00170 const char * 00171 SPF_response_get_smtp_comment(SPF_response_t *rp) 00172 { 00173 return rp->smtp_comment; 00174 } 00175 00176 const char * 00177 SPF_response_get_explanation(SPF_response_t *rp) 00178 { 00179 return rp->explanation; 00180 } 00181 00182 /* Error manipulation functions */ 00183 00184 #define SPF_ERRMSGSIZE 4096 00185 00186 static SPF_errcode_t 00187 SPF_response_add_error_v(SPF_response_t *rp, 00188 SPF_errcode_t code, int is_error, 00189 const char *text, int idx, 00190 const char *format, va_list ap) 00191 { 00192 SPF_error_t *tmp; 00193 char buf[SPF_ERRMSGSIZE]; 00194 int size; 00195 00196 /* TODO: Use text and idx */ 00197 00198 if (!format) 00199 format = SPF_strerror(code); 00200 size = vsnprintf(buf, sizeof(buf), format, ap); 00201 if (text != NULL) { 00202 snprintf(&buf[size], sizeof(buf) - size, 00203 " near '%.12s'", &text[idx]); 00204 } 00205 buf[SPF_ERRMSGSIZE - 1] = '\0'; 00206 00207 if (rp->errors_length == rp->errors_size) { 00208 size = rp->errors_size + (rp->errors_size / 4) + 4; 00209 tmp = (SPF_error_t *)realloc(rp->errors, size * sizeof(SPF_error_t)); 00210 if (! tmp) { 00211 SPF_error("Failed to allocate memory for extra response error"); 00212 return code; 00213 } 00214 rp->errors = tmp; 00215 rp->errors_size = size; 00216 } 00217 00218 rp->errors[rp->errors_length].code = code; 00219 rp->errors[rp->errors_length].is_error = is_error; 00220 /* If we are a memory error, this might fail. */ 00221 rp->errors[rp->errors_length].message = strdup(buf); 00222 rp->errors_length++; 00223 00224 return code; 00225 } 00226 00227 #define SPF_ADD_ERROR(_ise, _txt, _ix) \ 00228 va_list ap; va_start(ap, format); \ 00229 SPF_response_add_error_v(rp, code, _ise, _txt, _ix, format, ap); \ 00230 rp->num_errors++; \ 00231 va_end(ap); return code; 00232 #define SPF_ADD_WARN(_ise, _txt, _ix) \ 00233 va_list ap; va_start(ap, format); \ 00234 SPF_response_add_error_v(rp, code, _ise, _txt, _ix, format, ap); \ 00235 va_end(ap); return code; 00236 00237 SPF_errcode_t 00238 SPF_response_add_error_ptr(SPF_response_t *rp, 00239 SPF_errcode_t code, 00240 const char *text, const char *tptr, 00241 const char *format, ...) 00242 { 00243 SPF_ADD_ERROR(1, text ? text : tptr, text ? (tptr - text) : 0); 00244 } 00245 00246 SPF_errcode_t 00247 SPF_response_add_error_idx(SPF_response_t *rp, 00248 SPF_errcode_t code, 00249 const char *text, int idx, 00250 const char *format, ...) 00251 { 00252 SPF_ADD_ERROR(1, text, idx); 00253 } 00254 00255 SPF_errcode_t 00256 SPF_response_add_error(SPF_response_t *rp, 00257 SPF_errcode_t code, 00258 const char *format, ...) 00259 { 00260 SPF_ADD_ERROR(1, NULL, 0); 00261 } 00262 00263 SPF_errcode_t 00264 SPF_response_add_warn_ptr(SPF_response_t *rp, 00265 SPF_errcode_t code, 00266 const char *text, const char *tptr, 00267 const char *format, ...) 00268 { 00269 SPF_ADD_WARN(0, text ? text : tptr, text ? (tptr - text) : 0); 00270 } 00271 00272 SPF_errcode_t 00273 SPF_response_add_warn_idx(SPF_response_t *rp, 00274 SPF_errcode_t code, 00275 const char *text, int idx, 00276 const char *format, ...) 00277 { 00278 SPF_ADD_WARN(0, text, idx); 00279 } 00280 00281 SPF_errcode_t 00282 SPF_response_add_warn(SPF_response_t *rp, 00283 SPF_errcode_t code, 00284 const char *format, ...) 00285 { 00286 SPF_ADD_WARN(0, NULL, 0); 00287 } 00288 00289 int 00290 SPF_response_messages(SPF_response_t *rp) 00291 { 00292 return rp->errors_length; 00293 } 00294 00295 int 00296 SPF_response_errors(SPF_response_t *rp) 00297 { 00298 return rp->num_errors; 00299 } 00300 00301 int 00302 SPF_response_warnings(SPF_response_t *rp) 00303 { 00304 return rp->errors_length - rp->num_errors; 00305 } 00306 00307 SPF_error_t * 00308 SPF_response_message(SPF_response_t *rp, int idx) 00309 { 00310 return &rp->errors[idx]; 00311 } 00312 00313 SPF_errcode_t 00314 SPF_error_code(SPF_error_t *err) 00315 { 00316 return err->code; 00317 } 00318 00319 const char * 00320 SPF_error_message(SPF_error_t *err) 00321 { 00322 return err->message; 00323 } 00324 00325 char 00326 SPF_error_errorp(SPF_error_t *err) 00327 { 00328 return err->is_error; 00329 }