00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "spf_sys_config.h"
00017
00018
00019 #ifdef STDC_HEADERS
00020 # include <stdio.h>
00021 # include <stdlib.h>
00022 # include <ctype.h>
00023 #endif
00024
00025 #ifdef HAVE_INTTYPES_H
00026 #include <inttypes.h>
00027 #endif
00028
00029 #ifdef HAVE_NETDB_H
00030 #include <netdb.h>
00031 #endif
00032
00033 #ifdef HAVE_UNISTD_H
00034 #include <unistd.h>
00035 #endif
00036
00037 #ifdef HAVE_STRING_H
00038 # include <string.h>
00039 #else
00040 # ifdef HAVE_STRINGS_H
00041 # include <strings.h>
00042 # endif
00043 #endif
00044
00045 #ifdef HAVE_NETDB_H
00046 # include <netdb.h>
00047 #endif
00048
00049 #ifndef HOST_NAME_MAX
00050 #define HOST_NAME_MAX 255
00051 #endif
00052
00053
00054 #include "spf.h"
00055 #include "spf_response.h"
00056 #include "spf_record.h"
00057 #include "spf_server.h"
00058 #include "spf_dns.h"
00059 #include "spf_dns_resolv.h"
00060 #include "spf_dns_cache.h"
00061 #include "spf_dns_zone.h"
00062 #include "spf_internal.h"
00063 #include "spf_dns_internal.h"
00064
00065
00066 __attribute__((warn_unused_result))
00067 static SPF_errcode_t
00068 SPF_server_set_rec_dom_ghbn(SPF_server_t *sp)
00069 {
00070 sp->rec_dom = malloc(HOST_NAME_MAX);
00071 if (! sp->rec_dom)
00072 return SPF_E_NO_MEMORY;
00073 #ifdef _WIN32
00074 gethostnameFQDN(sp->rec_dom, HOST_NAME_MAX);
00075 return 0;
00076 #else
00077 if (gethostname(sp->rec_dom, HOST_NAME_MAX) < 0)
00078
00079 return SPF_E_INTERNAL_ERROR;
00080 #endif
00081 return SPF_E_SUCCESS;
00082 }
00083
00084 static void
00085 SPF_server_new_common_pre(SPF_server_t *sp, int debug)
00086 {
00087 SPF_errcode_t err;
00088
00089 memset(sp, 0, sizeof(SPF_server_t));
00090
00091 sp->max_dns_mech = SPF_MAX_DNS_MECH;
00092 sp->max_dns_ptr = SPF_MAX_DNS_PTR;
00093 sp->max_dns_mx = SPF_MAX_DNS_MX;
00094 sp->debug = debug;
00095
00096 err = SPF_server_set_rec_dom_ghbn(sp);
00097 if (err != SPF_E_SUCCESS)
00098 SPF_error("Failed to set rec_dom using gethostname()");
00099 }
00100
00101 static void
00102 SPF_server_new_common_post(SPF_server_t *sp)
00103 {
00104 SPF_response_t *spf_response;
00105 SPF_errcode_t err;
00106
00107 spf_response = NULL;
00108 err = SPF_server_set_explanation(sp, SPF_DEFAULT_EXP,
00109 &spf_response);
00110 if (err != SPF_E_SUCCESS)
00111 SPF_errorf("Error code %d compiling default explanation", err);
00112 if (spf_response) {
00113
00114 if (SPF_response_messages(spf_response) > 0)
00115 SPF_error("Response errors compiling default explanation");
00116 SPF_response_free(spf_response);
00117 }
00118
00119 spf_response = NULL;
00120 err = SPF_server_set_localpolicy(sp, "", 0, &spf_response);
00121 if (err != SPF_E_SUCCESS)
00122 SPF_errorf("Error code %d compiling default whitelist", err);
00123 if (spf_response) {
00124
00125 if (SPF_response_messages(spf_response) > 0)
00126 SPF_error("Response errors compiling default whitelist");
00127 SPF_response_free(spf_response);
00128 }
00129 }
00130
00131 SPF_server_t *
00132 SPF_server_new(SPF_server_dnstype_t dnstype, int debug)
00133 {
00134 SPF_dns_server_t *dc_r;
00135 SPF_dns_server_t *dc_c;
00136 SPF_dns_server_t *dc_z;
00137 SPF_server_t *sp;
00138
00139 sp = (SPF_server_t *)malloc(sizeof(SPF_server_t));
00140 if (! sp)
00141 return sp;
00142 SPF_server_new_common_pre(sp, debug);
00143 sp->destroy_resolver = 1;
00144
00145 switch (dnstype) {
00146 case SPF_DNS_RESOLV:
00147 dc_r = SPF_dns_resolv_new(NULL, NULL, debug);
00148 if (dc_r == NULL)
00149 SPF_error("Failed to create DNS resolver");
00150 sp->resolver = dc_r;
00151 break;
00152
00153 case SPF_DNS_CACHE:
00154 dc_r = SPF_dns_resolv_new(NULL, NULL, debug);
00155 if (dc_r == NULL)
00156 SPF_error("Failed to create DNS resolver");
00157 dc_c = SPF_dns_cache_new(dc_r, NULL, debug, 8);
00158 if (dc_c == NULL)
00159 SPF_error("Failed to create DNS cache");
00160 sp->resolver = dc_c;
00161 break;
00162
00163 case SPF_DNS_ZONE:
00164 dc_z = SPF_dns_zone_new(NULL, NULL, debug);
00165 if (dc_z == NULL)
00166 SPF_error("Failed to create DNS zone");
00167 sp->resolver = dc_z;
00168 break;
00169
00170 default:
00171 SPF_errorf("Unknown DNS type %d", dnstype);
00172 }
00173
00174 SPF_server_new_common_post(sp);
00175
00176 return sp;
00177 }
00178
00179 SPF_server_t *
00180 SPF_server_new_dns(SPF_dns_server_t *dns, int debug)
00181 {
00182 SPF_server_t *sp;
00183
00184 sp = (SPF_server_t *)malloc(sizeof(SPF_server_t));
00185 if (! sp)
00186 return sp;
00187 SPF_server_new_common_pre(sp, debug);
00188 sp->destroy_resolver = 0;
00189 sp->resolver = dns;
00190 SPF_server_new_common_post(sp);
00191 return sp;
00192 }
00193
00199 void
00200 SPF_server_free(SPF_server_t *sp)
00201 {
00202 if (sp->resolver && sp->destroy_resolver)
00203 SPF_dns_free(sp->resolver);
00204 if (sp->local_policy)
00205 SPF_record_free(sp->local_policy);
00206 if (sp->explanation)
00207 SPF_macro_free(sp->explanation);
00208 if (sp->rec_dom)
00209 free(sp->rec_dom);
00210
00211 free(sp);
00212 }
00213
00214 SPF_errcode_t
00215 SPF_server_set_rec_dom(SPF_server_t *sp, const char *dom)
00216 {
00217 if (sp->rec_dom)
00218 free(sp->rec_dom);
00219 if (dom == NULL)
00220 return SPF_server_set_rec_dom_ghbn(sp);
00221 sp->rec_dom = strdup(dom);
00222 if (! sp->rec_dom)
00223 return SPF_E_NO_MEMORY;
00224 return SPF_E_SUCCESS;
00225 }
00226
00227 SPF_errcode_t
00228 SPF_server_set_sanitize(SPF_server_t *sp, int sanitize)
00229 {
00230 sp->sanitize = sanitize;
00231 return SPF_E_SUCCESS;
00232 }
00233
00234 SPF_errcode_t
00235 SPF_server_set_explanation(SPF_server_t *sp, const char *exp,
00236 SPF_response_t **spf_responsep)
00237 {
00238 SPF_macro_t *spf_macro = NULL;
00239 SPF_errcode_t err;
00240
00241 SPF_ASSERT_NOTNULL(exp);
00242
00243
00244 if (! *spf_responsep) {
00245 *spf_responsep = SPF_response_new(NULL);
00246 if (! *spf_responsep)
00247 return SPF_E_NO_MEMORY;
00248 }
00249
00250 err = SPF_record_compile_macro(sp, *spf_responsep, &spf_macro, exp);
00251 if (err == SPF_E_SUCCESS) {
00252 if (sp->explanation)
00253 SPF_macro_free(sp->explanation);
00254 sp->explanation = spf_macro;
00255 }
00256 else {
00257 SPF_response_add_error(*spf_responsep, err,
00258 "Failed to compile explanation '%s'", exp);
00259 if (spf_macro)
00260 SPF_macro_free(spf_macro);
00261 }
00262
00263 return err;
00264 }
00265
00266 SPF_errcode_t
00267 SPF_server_set_localpolicy(SPF_server_t *sp, const char *policy,
00268 int use_default_whitelist,
00269 SPF_response_t **spf_responsep)
00270 {
00271 SPF_record_t *spf_record = NULL;
00272 SPF_errcode_t err;
00273 char *record;
00274 size_t len;
00275
00276 SPF_ASSERT_NOTNULL(policy);
00277
00278
00279 if (! *spf_responsep) {
00280 *spf_responsep = SPF_response_new(NULL);
00281 if (! *spf_responsep)
00282 return SPF_E_NO_MEMORY;
00283 }
00284
00285 len = sizeof(SPF_VER_STR) + strlen(policy) + 20;
00286 if (use_default_whitelist)
00287 len += sizeof(SPF_DEFAULT_WHITELIST);
00288 record = malloc(len);
00289 if (! record)
00290 return SPF_E_NO_MEMORY;
00291 if (use_default_whitelist)
00292 snprintf(record, len, "%s %s %s",
00293 SPF_VER_STR, policy, SPF_DEFAULT_WHITELIST);
00294 else
00295 snprintf(record, len, "%s %s", SPF_VER_STR, policy);
00296
00297 err = SPF_record_compile(sp, *spf_responsep, &spf_record, record);
00298 if (err == SPF_E_SUCCESS) {
00299 if (sp->local_policy)
00300 SPF_record_free(sp->local_policy);
00301 sp->local_policy = spf_record;
00302 }
00303 else {
00304 SPF_response_add_error(*spf_responsep, err,
00305 "Failed to compile local policy '%s'", policy);
00306 if (spf_record)
00307 SPF_record_free(spf_record);
00308 }
00309
00310 free(record);
00311
00312 return err;
00313 }
00314
00315 SPF_errcode_t
00316 SPF_server_get_record(SPF_server_t *spf_server,
00317 SPF_request_t *spf_request,
00318 SPF_response_t *spf_response,
00319 SPF_record_t **spf_recordp)
00320 {
00321 SPF_dns_server_t *resolver;
00322 SPF_dns_rr_t *rr_txt;
00323 SPF_errcode_t err;
00324 SPF_dns_stat_t herrno;
00325 const char *domain;
00326 ns_type rr_type;
00327 int num_found;
00328 int idx_found;
00329 int i;
00330
00331
00332 SPF_ASSERT_NOTNULL(spf_server);
00333 SPF_ASSERT_NOTNULL(spf_request);
00334 SPF_ASSERT_NOTNULL(spf_server->resolver);
00335 SPF_ASSERT_NOTNULL(spf_recordp);
00336
00337 domain = spf_request->cur_dom;
00338 SPF_ASSERT_NOTNULL(domain);
00339
00340 *spf_recordp = NULL;
00341
00342 resolver = spf_server->resolver;
00343
00344 if (resolver->get_spf)
00345 return resolver->get_spf(spf_server, spf_request,
00346 spf_response, spf_recordp);
00347
00348
00349 rr_type = ns_t_spf;
00350 retry:
00351 rr_txt = SPF_dns_lookup(resolver, domain, rr_type, TRUE);
00352
00353 switch (rr_txt->herrno) {
00354 case HOST_NOT_FOUND:
00355 if (spf_server->debug > 0)
00356 SPF_debugf("get_record(%s): HOST_NOT_FOUND", domain);
00357 SPF_dns_rr_free(rr_txt);
00358 if (rr_type == ns_t_spf) {
00359 rr_type = ns_t_txt;
00360 goto retry;
00361 }
00362 spf_response->result = SPF_RESULT_NONE;
00363 spf_response->reason = SPF_REASON_FAILURE;
00364 return SPF_response_add_error(spf_response, SPF_E_NOT_SPF,
00365 "Host '%s' not found.", domain);
00366
00367
00368 case NO_DATA:
00369 if (spf_server->debug > 0)
00370 SPF_debugf("get_record(%s): NO_DATA", domain);
00371 SPF_dns_rr_free(rr_txt);
00372 if (rr_type == ns_t_spf) {
00373 rr_type = ns_t_txt;
00374 goto retry;
00375 }
00376 spf_response->result = SPF_RESULT_NONE;
00377 spf_response->reason = SPF_REASON_FAILURE;
00378 return SPF_response_add_error(spf_response, SPF_E_NOT_SPF,
00379 "No DNS data for '%s'.", domain);
00380
00381
00382 case TRY_AGAIN:
00383 if (spf_server->debug > 0)
00384 SPF_debugf("get_record(%s): TRY_AGAIN", domain);
00385 SPF_dns_rr_free(rr_txt);
00386 return SPF_response_add_error(spf_response, SPF_E_DNS_ERROR,
00387 "Temporary DNS failure for '%s'.", domain);
00388
00389
00390 case NO_RECOVERY:
00391 if (spf_server->debug > 0)
00392 SPF_debugf("get_record(%s): NO_RECOERY", domain);
00393 SPF_dns_rr_free(rr_txt);
00394 return SPF_response_add_error(spf_response, SPF_E_DNS_ERROR,
00395 "Unrecoverable DNS failure for '%s'.", domain);
00396
00397
00398 case NETDB_SUCCESS:
00399 if (spf_server->debug > 0)
00400 SPF_debugf("get_record(%s): NETDB_SUCCESS", domain);
00401 break;
00402
00403 default:
00404 if (spf_server->debug > 0)
00405 SPF_debugf("get_record(%s): UNKNOWN_ERROR", domain);
00406 herrno = rr_txt->herrno;
00407 SPF_dns_rr_free(rr_txt);
00408 return SPF_response_add_error(spf_response, SPF_E_DNS_ERROR,
00409 "Unknown DNS failure for '%s': %d.",
00410 domain, herrno);
00411
00412 }
00413
00414 if (rr_txt->num_rr == 0) {
00415 SPF_dns_rr_free(rr_txt);
00416 if (rr_type == ns_t_spf) {
00417 rr_type = ns_t_txt;
00418 goto retry;
00419 }
00420 return SPF_response_add_error(spf_response, SPF_E_NOT_SPF,
00421 "No TXT records returned from DNS lookup for '%s'",
00422 domain);
00423 }
00424
00425
00426 idx_found = 0;
00427
00428
00429 num_found = 0;
00430 for (i = 0; i < rr_txt->num_rr; i++) {
00431
00432
00433
00434
00435
00436 if (strncasecmp(rr_txt->rr[i]->txt,
00437 SPF_VER_STR, sizeof(SPF_VER_STR) - 1) == 0) {
00438 char e = rr_txt->rr[i]->txt[sizeof(SPF_VER_STR) - 1];
00439 if (e == ' ' || e == '\0') {
00440 if (spf_server->debug > 0)
00441 SPF_debugf("found SPF record: %s", rr_txt->rr[i]->txt);
00442 num_found++;
00443 idx_found = i;
00444 }
00445 }
00446 }
00447
00448 if (num_found == 0) {
00449 SPF_dns_rr_free(rr_txt);
00450 if (rr_type == ns_t_spf) {
00451 rr_type = ns_t_txt;
00452 goto retry;
00453 }
00454 spf_response->result = SPF_RESULT_NONE;
00455 spf_response->reason = SPF_REASON_FAILURE;
00456 return SPF_response_add_error(spf_response, SPF_E_NOT_SPF,
00457 "No SPF records for '%s'", domain);
00458 }
00459 if (num_found > 1) {
00460 SPF_dns_rr_free(rr_txt);
00461
00462
00463 spf_response->result = SPF_RESULT_PERMERROR;
00464 spf_response->reason = SPF_REASON_FAILURE;
00465 return SPF_response_add_error(spf_response, SPF_E_MULTIPLE_RECORDS,
00466 "Multiple SPF records for '%s'", domain);
00467 }
00468
00469
00470 err = SPF_record_compile(spf_server,
00471 spf_response, spf_recordp,
00472 rr_txt->rr[idx_found]->txt );
00473 SPF_dns_rr_free(rr_txt);
00474
00475
00476 if (err != SPF_E_SUCCESS)
00477 return SPF_response_add_error(spf_response, SPF_E_NOT_SPF,
00478 "Failed to compile SPF record for '%s'", domain);
00479
00480 return SPF_E_SUCCESS;
00481 }
00482
00488 #define SPF_ACCESS_INT(f) \
00489 SPF_errcode_t SPF_server_set_ ## f(SPF_server_t *s, int n) { \
00490 s->f = n; return SPF_E_SUCCESS; \
00491 } \
00492 int SPF_server_get_ ## f(SPF_server_t *s) { \
00493 return s->f; \
00494 }
00495
00501 SPF_ACCESS_INT(max_dns_mech);
00502 SPF_ACCESS_INT(max_dns_ptr);
00503 SPF_ACCESS_INT(max_dns_mx);