00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "spf_sys_config.h"
00017
00018 #ifdef STDC_HEADERS
00019 # include <stdio.h>
00020 # include <stdlib.h>
00021 #endif
00022
00023 #ifdef HAVE_STRING_H
00024 # include <string.h>
00025 #else
00026 # ifdef HAVE_STRINGS_H
00027 # include <strings.h>
00028 # endif
00029 #endif
00030
00031 #ifdef HAVE_NETDB_H
00032 #include <netdb.h>
00033 #endif
00034
00035 #include <ctype.h>
00036
00037 #include "spf.h"
00038 #include "spf_dns.h"
00039 #include "spf_internal.h"
00040 #include "spf_dns_internal.h"
00041 #include "spf_server.h"
00042
00043 static SPF_errcode_t
00044 SPF_i_set_explanation(SPF_response_t *spf_response)
00045 {
00046 SPF_server_t *spf_server;
00047 SPF_request_t *spf_request;
00048 SPF_record_t *spf_record;
00049 SPF_errcode_t err;
00050 char *buf;
00051 size_t buflen;
00052
00053 SPF_ASSERT_NOTNULL(spf_response);
00054 spf_request = spf_response->spf_request;
00055 SPF_ASSERT_NOTNULL(spf_request);
00056 spf_server = spf_request->spf_server;
00057 SPF_ASSERT_NOTNULL(spf_server);
00058
00059 spf_record = spf_response->spf_record_exp;
00060 SPF_ASSERT_NOTNULL(spf_record);
00061
00062 if (spf_response->explanation)
00063 free(spf_response->explanation);
00064 spf_response->explanation = NULL;
00065
00066 buflen = SPF_SMTP_COMMENT_SIZE + 1;
00067 buf = malloc(buflen);
00068 if (buf == NULL)
00069 return SPF_E_NO_MEMORY;
00070 memset(buf, '\0', buflen);
00071
00072 err = SPF_request_get_exp(spf_server, spf_request,
00073 spf_response, spf_record, &buf, &buflen);
00074 if (err != SPF_E_SUCCESS) {
00075 free(buf);
00076 return err;
00077 }
00078
00079 spf_response->explanation = buf;
00080
00081 return SPF_E_SUCCESS;
00082 }
00083
00084 static SPF_errcode_t
00085 SPF_i_set_smtp_comment(SPF_response_t *spf_response)
00086 {
00087 SPF_server_t *spf_server;
00088 SPF_request_t *spf_request;
00089 SPF_errcode_t err;
00090 char buf[SPF_SMTP_COMMENT_SIZE];
00091
00092 SPF_ASSERT_NOTNULL(spf_response);
00093 spf_request = spf_response->spf_request;
00094 SPF_ASSERT_NOTNULL(spf_request);
00095 spf_server = spf_request->spf_server;
00096 SPF_ASSERT_NOTNULL(spf_server);
00097
00098 if (spf_response->smtp_comment)
00099 free(spf_response->smtp_comment);
00100 spf_response->smtp_comment = NULL;
00101
00102
00103 switch (spf_response->result) {
00104 case SPF_RESULT_FAIL:
00105 case SPF_RESULT_SOFTFAIL:
00106 case SPF_RESULT_NEUTRAL:
00107
00108 err = SPF_i_set_explanation(spf_response);
00109 if (err != SPF_E_SUCCESS)
00110 return err;
00111
00112 memset(buf, '\0', sizeof(buf));
00113 snprintf(buf, SPF_SMTP_COMMENT_SIZE, "%s : Reason: %s",
00114 spf_response->explanation,
00115 SPF_strreason(spf_response->reason));
00116 buf[SPF_SMTP_COMMENT_SIZE - 1] = '\0';
00117
00118
00119 spf_response->smtp_comment = strdup(buf);
00120 if (! spf_response->smtp_comment)
00121 return SPF_E_NO_MEMORY;
00122
00123 break;
00124 case SPF_RESULT_INVALID:
00125 case SPF_RESULT_PASS:
00126 case SPF_RESULT_TEMPERROR:
00127 case SPF_RESULT_PERMERROR:
00128 case SPF_RESULT_NONE:
00129 default:
00130 break;
00131 }
00132
00133 return SPF_E_SUCCESS;
00134 }
00135
00136 static SPF_errcode_t
00137 SPF_i_set_header_comment(SPF_response_t *spf_response)
00138 {
00139 SPF_server_t *spf_server;
00140 SPF_request_t *spf_request;
00141 char *spf_source;
00142
00143 size_t len;
00144
00145 char ip4_buf[ INET_ADDRSTRLEN ];
00146 char ip6_buf[ INET6_ADDRSTRLEN ];
00147 const char *ip;
00148
00149 char *buf;
00150 char *sender_dom;
00151 char *p, *p_end;
00152
00153 SPF_ASSERT_NOTNULL(spf_response);
00154 spf_request = spf_response->spf_request;
00155 SPF_ASSERT_NOTNULL(spf_request);
00156 spf_server = spf_request->spf_server;
00157 SPF_ASSERT_NOTNULL(spf_server);
00158
00159 if (spf_response->header_comment)
00160 free(spf_response->header_comment);
00161 spf_response->header_comment = NULL;
00162
00163
00164 sender_dom = spf_request->env_from_dp;
00165 if (sender_dom == NULL)
00166 sender_dom = spf_request->helo_dom;
00167
00168 if ( spf_response->reason == SPF_REASON_LOCAL_POLICY ) {
00169 spf_source = strdup( "local policy" );
00170 }
00171 else if ( spf_response->reason == SPF_REASON_2MX ) {
00172 if ( spf_request->rcpt_to_dom == NULL || spf_request->rcpt_to_dom[0] == '\0' )
00173 SPF_error( "RCPT TO domain is NULL" );
00174
00175 spf_source = strdup( spf_request->rcpt_to_dom );
00176 }
00177 else if ( sender_dom == NULL ) {
00178 spf_source = strdup( "unknown domain" );
00179 }
00180 else {
00181 len = strlen( sender_dom ) + sizeof( "domain of " );
00182 spf_source = malloc( len );
00183 if ( spf_source )
00184 snprintf( spf_source, len, "domain of %s", sender_dom );
00185 }
00186
00187 if ( spf_source == NULL )
00188 return SPF_E_INTERNAL_ERROR;
00189
00190 ip = NULL;
00191 if ( spf_request->client_ver == AF_INET ) {
00192 ip = inet_ntop( AF_INET, &spf_request->ipv4,
00193 ip4_buf, sizeof( ip4_buf ) );
00194 }
00195 else if (spf_request->client_ver == AF_INET6 ) {
00196 ip = inet_ntop( AF_INET6, &spf_request->ipv6,
00197 ip6_buf, sizeof( ip6_buf ) );
00198 }
00199 if ( ip == NULL )
00200 ip = "(unknown ip address)";
00201
00202 len = strlen( SPF_request_get_rec_dom(spf_request) ) + strlen( spf_source ) + strlen( ip ) + 80;
00203 buf = malloc( len );
00204 if ( buf == NULL ) {
00205 free( spf_source );
00206 return SPF_E_INTERNAL_ERROR;
00207 }
00208
00209 p = buf;
00210 p_end = p + len;
00211
00212
00213 p += snprintf( p, p_end - p, "%s: ", SPF_request_get_rec_dom(spf_request) );
00214
00215 switch(spf_response->result)
00216 {
00217 case SPF_RESULT_PASS:
00218 if ( spf_response->reason == SPF_REASON_LOCALHOST )
00219 snprintf( p, p_end - p, "localhost is always allowed." );
00220 else if ( spf_response->reason == SPF_REASON_2MX )
00221 snprintf( p, p_end - p, "message received from %s which is an MX secondary for %s.",
00222 ip, spf_source );
00223 else
00224 snprintf( p, p_end - p, "%s designates %s as permitted sender",
00225 spf_source, ip );
00226 break;
00227
00228 case SPF_RESULT_FAIL:
00229 snprintf( p, p_end - p, "%s does not designate %s as permitted sender",
00230 spf_source, ip );
00231 break;
00232
00233 case SPF_RESULT_SOFTFAIL:
00234 snprintf( p, p_end - p, "transitioning %s does not designate %s as permitted sender",
00235 spf_source, ip );
00236 break;
00237
00238 case SPF_RESULT_PERMERROR:
00239 snprintf(p, p_end - p, "error in processing during lookup of %s: %s",
00240 spf_source, SPF_strerror(spf_response->err));
00241 break;
00242
00243 case SPF_RESULT_NEUTRAL:
00244 snprintf(p, p_end - p, "%s is neither permitted nor denied by %s",
00245 ip, spf_source);
00246 break;
00247 case SPF_RESULT_NONE:
00248 snprintf(p, p_end - p, "%s does not provide an SPF record",
00249 spf_source);
00250 break;
00251
00252 case SPF_RESULT_TEMPERROR:
00253 snprintf(p, p_end - p, "encountered temporary error during SPF processing of %s",
00254 spf_source );
00255 break;
00256
00257
00258 default:
00259 snprintf( p, p_end - p, "error: unknown SPF result %d encountered while checking %s for %s",
00260 spf_response->result, ip, spf_source );
00261 break;
00262 }
00263
00264 if (spf_source)
00265 free(spf_source);
00266
00267 spf_response->header_comment = SPF_sanitize(spf_server, buf);
00268
00269 return SPF_E_SUCCESS;
00270 }
00271
00272 static SPF_errcode_t
00273 SPF_i_set_received_spf(SPF_response_t *spf_response)
00274 {
00275 SPF_server_t *spf_server;
00276 SPF_request_t *spf_request;
00277 char ip4_buf[ INET_ADDRSTRLEN ];
00278 char ip6_buf[ INET6_ADDRSTRLEN ];
00279 const char *ip;
00280
00281 char *buf;
00282 size_t buflen = SPF_RECEIVED_SPF_SIZE;
00283 char *buf_value;
00284
00285 char *p, *p_end;
00286
00287 SPF_ASSERT_NOTNULL(spf_response);
00288 spf_request = spf_response->spf_request;
00289 SPF_ASSERT_NOTNULL(spf_request);
00290 spf_server = spf_request->spf_server;
00291 SPF_ASSERT_NOTNULL(spf_server);
00292
00293 if (spf_response->received_spf)
00294 free(spf_response->received_spf);
00295 spf_response->received_spf = NULL;
00296
00297 buf = malloc( buflen );
00298 if ( buf == NULL )
00299 return SPF_E_INTERNAL_ERROR;
00300
00301 p = buf;
00302 p_end = p + buflen;
00303
00304
00305
00306 p += snprintf( p, p_end - p, "Received-SPF: ");
00307 buf_value = p;
00308
00309 do {
00310 p += snprintf( p, p_end - p, "%s (%s)",
00311 SPF_strresult( spf_response->result ),
00312 spf_response->header_comment );
00313 if ( p_end - p <= 0 ) break;
00314
00315
00316
00317
00318 ip = NULL;
00319 if ( spf_request->client_ver == AF_INET ) {
00320 ip = inet_ntop( AF_INET, &spf_request->ipv4,
00321 ip4_buf, sizeof( ip4_buf ) );
00322 }
00323 else if (spf_request->client_ver == AF_INET6 ) {
00324 ip = inet_ntop( AF_INET6, &spf_request->ipv6,
00325 ip6_buf, sizeof( ip6_buf ) );
00326 }
00327
00328 if ( ip != NULL ) {
00329 p += snprintf( p, p_end - p, " client-ip=%s;", ip );
00330 if ( p_end - p <= 0 ) break;
00331 }
00332
00333
00334
00335 if ( spf_request->env_from != NULL ) {
00336 p += snprintf( p, p_end - p, " envelope-from=%s;", spf_request->env_from );
00337 if ( p_end - p <= 0 ) break;
00338 }
00339
00340
00341
00342 if ( spf_request->helo_dom != NULL ) {
00343 p += snprintf( p, p_end - p, " helo=%s;", spf_request->helo_dom );
00344 if ( p_end - p <= 0 ) break;
00345 }
00346
00347
00348
00349 #if 0
00350
00351 if ( output.err_msg != NULL ) {
00352 p += snprintf( p, p_end - p, " problem=%s;", output.err_msg );
00353 if ( p_end - p <= 0 ) break;
00354 }
00355 else if ( c_results.err_msg != NULL ) {
00356 p += snprintf( p, p_end - p, " problem=%s;", c_results.err_msg );
00357 if ( p_end - p <= 0 ) break;
00358 }
00359 #endif
00360
00361
00362
00363
00364 } while(0);
00365
00366 spf_response->received_spf = SPF_sanitize(spf_server, buf);
00367 spf_response->received_spf_value = buf_value;
00368
00369 return SPF_E_SUCCESS;
00370 }
00371
00372
00373
00374 #define DONE(result,reason,err) SPF_i_done(spf_response, result, reason, err)
00375 #define DONE_TEMPERR(err) DONE(SPF_RESULT_TEMPERROR,SPF_REASON_NONE,err)
00376 #define DONE_PERMERR(err) DONE(SPF_RESULT_PERMERROR,SPF_REASON_NONE,err)
00377 #define DONE_MECH(result) DONE(result, SPF_REASON_MECH, SPF_E_SUCCESS)
00378
00387 SPF_errcode_t
00388 SPF_i_done(SPF_response_t *spf_response,
00389 SPF_result_t result, SPF_reason_t reason, SPF_errcode_t err)
00390 {
00391 SPF_request_t *spf_request;
00392 SPF_server_t *spf_server;
00393
00394 SPF_ASSERT_NOTNULL(spf_response);
00395 spf_request = spf_response->spf_request;
00396 SPF_ASSERT_NOTNULL(spf_request);
00397 spf_server = spf_request->spf_server;
00398 SPF_ASSERT_NOTNULL(spf_server);
00399
00400 spf_response->result = result;
00401 spf_response->reason = reason;
00402 spf_response->err = err;
00403
00404 SPF_i_set_smtp_comment(spf_response);
00405 SPF_i_set_header_comment(spf_response);
00406 SPF_i_set_received_spf(spf_response);
00407
00408 return err;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418 #define INET_NTOP(af, src, dst, cnt) do { \
00419 if (inet_ntop(af, src, dst, cnt) == NULL) \
00420 snprintf(dst, cnt, "ip-error" ); \
00421 } while(0)
00422
00423 static int
00424 SPF_i_mech_cidr(SPF_request_t *spf_request, SPF_mech_t *mech)
00425 {
00426 SPF_data_t *data;
00427
00428 SPF_ASSERT_NOTNULL(mech);
00429
00430 switch( mech->mech_type )
00431 {
00432 case MECH_IP4:
00433 case MECH_IP6:
00434 return mech->mech_len;
00435 break;
00436
00437 case MECH_A:
00438 case MECH_MX:
00439 data = SPF_mech_data( mech );
00440
00441 if ( data < SPF_mech_end_data( mech )
00442 && data->dc.parm_type == PARM_CIDR )
00443 {
00444 if ( spf_request->client_ver == AF_INET )
00445 return data->dc.ipv4;
00446 else if ( spf_request->client_ver == AF_INET6 )
00447 return data->dc.ipv6;
00448 }
00449 break;
00450 }
00451
00452 return 0;
00453 }
00454
00455
00456
00457 static int
00458 SPF_i_match_ip4(SPF_server_t *spf_server,
00459 SPF_request_t *spf_request,
00460 SPF_mech_t *mech,
00461 struct in_addr ipv4 )
00462 {
00463 char src_ip4_buf[ INET_ADDRSTRLEN ];
00464 char dst_ip4_buf[ INET_ADDRSTRLEN ];
00465 char mask_ip4_buf[ INET_ADDRSTRLEN ];
00466
00467 struct in_addr src_ipv4;
00468 int cidr, mask;
00469
00470
00471 if ( spf_request->client_ver != AF_INET )
00472 return FALSE;
00473
00474 src_ipv4 = spf_request->ipv4;
00475
00476 cidr = SPF_i_mech_cidr( spf_request, mech );
00477 if ( cidr == 0 )
00478 cidr = 32;
00479 mask = 0xffffffff << (32 - cidr);
00480 mask = htonl(mask);
00481
00482 if (spf_server->debug) {
00483 INET_NTOP(AF_INET, &src_ipv4.s_addr,
00484 src_ip4_buf, sizeof(src_ip4_buf));
00485 INET_NTOP(AF_INET, &ipv4.s_addr,
00486 dst_ip4_buf, sizeof(dst_ip4_buf));
00487 INET_NTOP(AF_INET, &mask,
00488 mask_ip4_buf, sizeof(mask_ip4_buf));
00489 SPF_debugf( "ip_match: %s == %s (/%d %s): %d",
00490 src_ip4_buf, dst_ip4_buf, cidr, mask_ip4_buf,
00491 (src_ipv4.s_addr & mask) == (ipv4.s_addr & mask));
00492 }
00493
00494 return (src_ipv4.s_addr & mask) == (ipv4.s_addr & mask);
00495 }
00496
00497
00498 static int
00499 SPF_i_match_ip6(SPF_server_t *spf_server,
00500 SPF_request_t *spf_request,
00501 SPF_mech_t *mech,
00502 struct in6_addr ipv6 )
00503 {
00504 char src_ip6_buf[ INET6_ADDRSTRLEN ];
00505 char dst_ip6_buf[ INET6_ADDRSTRLEN ];
00506
00507 struct in6_addr src_ipv6;
00508 int cidr, cidr_save, mask;
00509 int i;
00510 int match;
00511
00512 if ( spf_request->client_ver != AF_INET6 )
00513 return FALSE;
00514
00515 src_ipv6 = spf_request->ipv6;
00516
00517 cidr = SPF_i_mech_cidr(spf_request, mech);
00518 if ( cidr == 0 )
00519 cidr = 128;
00520 cidr_save = cidr;
00521
00522 match = TRUE;
00523 for( i = 0; i < array_elem( ipv6.s6_addr ) && match; i++ )
00524 {
00525 if ( cidr > 8 )
00526 mask = 0xff;
00527 else if ( cidr > 0 )
00528 mask = (0xff << (8 - cidr)) & 0xff;
00529 else
00530 break;
00531 cidr -= 8;
00532
00533 match = (src_ipv6.s6_addr[i] & mask) == (ipv6.s6_addr[i] & mask);
00534 }
00535
00536 if (spf_server->debug) {
00537 INET_NTOP(AF_INET6, &src_ipv6.s6_addr,
00538 src_ip6_buf, sizeof(src_ip6_buf));
00539 INET_NTOP(AF_INET6, &ipv6.s6_addr,
00540 dst_ip6_buf, sizeof(dst_ip6_buf));
00541 SPF_debugf( "ip_match: %s == %s (/%d): %d",
00542 src_ip6_buf, dst_ip6_buf, cidr_save, match );
00543 }
00544
00545 return match;
00546 }
00547
00548 static int
00549 SPF_i_match_domain(SPF_server_t *spf_server,
00550 const char *hostname, const char *domain)
00551 {
00552 const char *hp;
00553 size_t hlen;
00554 size_t dlen;
00555
00556 if (spf_server->debug)
00557 SPF_debugf( "%s ?=? %s", hostname, domain );
00558
00559 hlen = strlen(hostname);
00560 dlen = strlen(domain);
00561
00562
00563 if (dlen > hlen)
00564 return 0;
00565
00566
00567 if (dlen == hlen)
00568 return (strcasecmp(hostname, domain) == 0);
00569
00570
00571 hp = hostname + (hlen - dlen);
00572
00573 if (*(hp - 1) != '.')
00574 return 0;
00575
00576 return (strcasecmp(hp, domain) == 0);
00577 }
00578
00579
00580
00581
00582
00583
00584 SPF_errcode_t
00585 SPF_record_interpret(SPF_record_t *spf_record,
00586 SPF_request_t *spf_request, SPF_response_t *spf_response,
00587 int depth)
00588 {
00589 SPF_server_t *spf_server;
00590
00591
00592 int i, j;
00593 int m;
00594 SPF_mech_t *mech;
00595 SPF_data_t *data;
00596 SPF_data_t *data_end;
00597
00598
00599 SPF_mech_t *local_policy;
00600 int found_all;
00601
00602 char *buf = NULL;
00603 size_t buf_len = 0;
00604 ns_type fetch_ns_type;
00605 const char *lookup;
00606
00607 SPF_dns_rr_t *rr_a;
00608 SPF_dns_rr_t *rr_aaaa;
00609 SPF_dns_rr_t *rr_ptr;
00610 SPF_dns_rr_t *rr_mx;
00611
00612 SPF_errcode_t err;
00613
00614 SPF_dns_server_t*resolver;
00615
00616
00617 SPF_record_t *spf_record_subr;
00618
00619 SPF_response_t *save_spf_response;
00620 SPF_response_t *spf_response_subr;
00621 const char *save_cur_dom;
00622
00623 struct in_addr addr4;
00624 struct in6_addr addr6;
00625
00626 int max_ptr;
00627 int max_mx;
00628 int max_exceeded;
00629
00630 char ip4_buf[ INET_ADDRSTRLEN ];
00631 char ip6_buf[ INET6_ADDRSTRLEN ];
00632
00633
00634
00635
00636
00637 SPF_ASSERT_NOTNULL(spf_record);
00638 SPF_ASSERT_NOTNULL(spf_request);
00639 SPF_ASSERT_NOTNULL(spf_response);
00640 spf_server = spf_record->spf_server;
00641 SPF_ASSERT_NOTNULL(spf_server);
00642
00643 SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
00644
00645 if (depth > 20)
00646 return DONE_PERMERR(SPF_E_RECURSIVE);
00647
00648 if ( spf_request->client_ver != AF_INET && spf_request->client_ver != AF_INET6 )
00649 return DONE_PERMERR(SPF_E_NOT_CONFIG);
00650
00651 if (spf_request->cur_dom == NULL)
00652 return DONE_PERMERR(SPF_E_NOT_CONFIG);
00653
00654
00655
00656
00657
00658
00659 #if 0
00660
00661 if ( SPF_request_is_loopback( spf_request ) )
00662 return DONE(SPF_RESULT_PASS,SPF_REASON_LOCALHOST,SPF_E_SUCCESS);
00663 #endif
00664
00665
00666
00667
00668
00669 local_policy = NULL;
00670
00671 if ( spf_request->use_local_policy ) {
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 if ( spf_server->local_policy ) {
00689 mech = spf_record->mech_first;
00690
00691 found_all = FALSE;
00692 for(m = 0; m < spf_record->num_mech; m++)
00693 {
00694 if ( mech->mech_type == MECH_ALL
00695 && (mech->prefix_type == PREFIX_FAIL
00696 || mech->prefix_type == PREFIX_UNKNOWN
00697 || mech->prefix_type == PREFIX_SOFTFAIL
00698 )
00699 )
00700 found_all = TRUE;
00701
00702 if ( mech->prefix_type != PREFIX_FAIL
00703 && mech->prefix_type != PREFIX_SOFTFAIL
00704 )
00705 local_policy = mech;
00706
00707 mech = SPF_mech_next( mech );
00708 }
00709
00710 if ( !found_all )
00711 local_policy = NULL;
00712 }
00713
00714 }
00715
00716
00717
00718
00719
00720
00721 #define SPF_ADD_DNS_MECH() do { spf_response->num_dns_mech++; } while(0)
00722
00723 #define SPF_MAYBE_SKIP_CIDR() \
00724 do { \
00725 if ( data < data_end && data->dc.parm_type == PARM_CIDR ) \
00726 data = SPF_data_next( data ); \
00727 } while(0)
00728
00729 #define SPF_GET_LOOKUP_DATA() \
00730 do { \
00731 if ( data == data_end ) \
00732 lookup = spf_request->cur_dom; \
00733 else { \
00734 err = SPF_record_expand_data( spf_server, \
00735 spf_request, spf_response, \
00736 data, ((char *)data_end - (char *)data), \
00737 &buf, &buf_len ); \
00738 if (err == SPF_E_NO_MEMORY) { \
00739 SPF_FREE_LOOKUP_DATA(); \
00740 return DONE_TEMPERR(err); \
00741 } \
00742 if (err) { \
00743 SPF_FREE_LOOKUP_DATA(); \
00744 return DONE_PERMERR(err); \
00745 } \
00746 lookup = buf; \
00747 } \
00748 } while(0)
00749 #define SPF_FREE_LOOKUP_DATA() \
00750 do { if (buf != NULL) { free(buf); buf = NULL; } } while(0)
00751
00752
00753 resolver = spf_server->resolver;
00754
00755 mech = spf_record->mech_first;
00756 for (m = 0; m < spf_record->num_mech; m++) {
00757
00758
00759
00760 if (spf_response->num_dns_mech > spf_server->max_dns_mech) {
00761 SPF_FREE_LOOKUP_DATA();
00762 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
00763 }
00764
00765 data = SPF_mech_data(mech);
00766 data_end = SPF_mech_end_data(mech);
00767
00768 switch (mech->mech_type) {
00769 case MECH_A:
00770 SPF_ADD_DNS_MECH();
00771 SPF_MAYBE_SKIP_CIDR();
00772 SPF_GET_LOOKUP_DATA();
00773
00774 if (spf_request->client_ver == AF_INET)
00775 fetch_ns_type = ns_t_a;
00776 else
00777 fetch_ns_type = ns_t_aaaa;
00778
00779 rr_a = SPF_dns_lookup(resolver, lookup, fetch_ns_type, TRUE);
00780
00781 if (spf_server->debug)
00782 SPF_debugf("found %d A records for %s (herrno: %d)",
00783 rr_a->num_rr, lookup, rr_a->herrno);
00784
00785 if (rr_a->herrno == TRY_AGAIN) {
00786 SPF_dns_rr_free(rr_a);
00787 SPF_FREE_LOOKUP_DATA();
00788 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00789 }
00790
00791 for (i = 0; i < rr_a->num_rr; i++) {
00792
00793 if (rr_a->rr_type != fetch_ns_type)
00794 continue;
00795
00796 if (spf_request->client_ver == AF_INET) {
00797 if (SPF_i_match_ip4(spf_server, spf_request, mech, rr_a->rr[i]->a)) {
00798 SPF_dns_rr_free(rr_a);
00799 SPF_FREE_LOOKUP_DATA();
00800 return DONE_MECH(mech->prefix_type);
00801 }
00802 }
00803 else {
00804 if (SPF_i_match_ip6(spf_server, spf_request, mech, rr_a->rr[i]->aaaa)) {
00805 SPF_dns_rr_free(rr_a);
00806 SPF_FREE_LOOKUP_DATA();
00807 return DONE_MECH(mech->prefix_type);
00808 }
00809 }
00810 }
00811
00812 SPF_dns_rr_free(rr_a);
00813 break;
00814
00815 case MECH_MX:
00816 SPF_ADD_DNS_MECH();
00817 SPF_MAYBE_SKIP_CIDR();
00818 SPF_GET_LOOKUP_DATA();
00819
00820 rr_mx = SPF_dns_lookup(resolver, lookup, ns_t_mx, TRUE);
00821
00822 if (spf_server->debug)
00823 SPF_debugf("found %d MX records for %s (herrno: %d)",
00824 rr_mx->num_rr, lookup, rr_mx->herrno);
00825
00826 if (rr_mx->herrno == TRY_AGAIN) {
00827 SPF_dns_rr_free(rr_mx);
00828 SPF_FREE_LOOKUP_DATA();
00829 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00830 }
00831
00832
00833 max_mx = rr_mx->num_rr;
00834 max_exceeded = 0;
00835 if (max_mx > spf_server->max_dns_mx) {
00836 max_exceeded = 1;
00837 max_mx = SPF_server_get_max_dns_mx(spf_server);
00838 }
00839
00840 for (j = 0; j < max_mx; j++) {
00841
00842 if (rr_mx->rr_type != ns_t_mx)
00843 continue;
00844
00845 if (spf_request->client_ver == AF_INET)
00846 fetch_ns_type = ns_t_a;
00847 else
00848 fetch_ns_type = ns_t_aaaa;
00849
00850 rr_a = SPF_dns_lookup(resolver, rr_mx->rr[j]->mx,
00851 fetch_ns_type, TRUE );
00852
00853 if (spf_server->debug)
00854 SPF_debugf("%d: found %d A records for %s (herrno: %d)",
00855 j, rr_a->num_rr, rr_mx->rr[j]->mx, rr_a->herrno);
00856 if (rr_a->herrno == TRY_AGAIN) {
00857 SPF_dns_rr_free(rr_mx);
00858 SPF_dns_rr_free(rr_a);
00859 SPF_FREE_LOOKUP_DATA();
00860 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00861 }
00862
00863 for (i = 0; i < rr_a->num_rr; i++) {
00864
00865 if (rr_a->rr_type != fetch_ns_type)
00866 continue;
00867
00868 if (spf_request->client_ver == AF_INET) {
00869 if (SPF_i_match_ip4(spf_server, spf_request, mech,
00870 rr_a->rr[i]->a)) {
00871 SPF_dns_rr_free(rr_mx);
00872 SPF_dns_rr_free(rr_a);
00873 SPF_FREE_LOOKUP_DATA();
00874 return DONE(mech->prefix_type, SPF_REASON_MECH,
00875 SPF_E_SUCCESS);
00876 }
00877 }
00878 else {
00879 if (SPF_i_match_ip6(spf_server, spf_request, mech,
00880 rr_a->rr[i]->aaaa)) {
00881 SPF_dns_rr_free(rr_mx);
00882 SPF_dns_rr_free(rr_a);
00883 SPF_FREE_LOOKUP_DATA();
00884 return DONE(mech->prefix_type, SPF_REASON_MECH,
00885 SPF_E_SUCCESS);
00886 }
00887 }
00888 }
00889 SPF_dns_rr_free(rr_a);
00890 }
00891
00892 SPF_dns_rr_free( rr_mx );
00893 if (max_exceeded) {
00894 SPF_FREE_LOOKUP_DATA();
00895 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
00896 }
00897 break;
00898
00899 case MECH_PTR:
00900 SPF_ADD_DNS_MECH();
00901 SPF_GET_LOOKUP_DATA();
00902
00903 if (spf_request->client_ver == AF_INET) {
00904 rr_ptr = SPF_dns_rlookup(resolver,
00905 spf_request->ipv4, ns_t_ptr, TRUE);
00906
00907 if (spf_server->debug) {
00908 INET_NTOP(AF_INET, &spf_request->ipv4.s_addr,
00909 ip4_buf, sizeof(ip4_buf));
00910 SPF_debugf("got %d PTR records for %s (herrno: %d)",
00911 rr_ptr->num_rr, ip4_buf, rr_ptr->herrno);
00912 }
00913
00914 if (rr_ptr->herrno == TRY_AGAIN) {
00915 SPF_dns_rr_free(rr_ptr);
00916 SPF_FREE_LOOKUP_DATA();
00917 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00918 }
00919
00920
00921
00922 max_ptr = rr_ptr->num_rr;
00923 max_exceeded = 0;
00924 if (max_ptr > spf_server->max_dns_ptr) {
00925 max_exceeded = 1;
00926 max_ptr = SPF_server_get_max_dns_ptr(spf_server);
00927 }
00928
00929 for (i = 0; i < max_ptr; i++) {
00930
00931
00932 rr_a = SPF_dns_lookup(resolver,
00933 rr_ptr->rr[i]->ptr, ns_t_a, TRUE);
00934
00935 if (spf_server->debug)
00936 SPF_debugf( "%d: found %d A records for %s (herrno: %d)",
00937 i, rr_a->num_rr, rr_ptr->rr[i]->ptr, rr_a->herrno );
00938 if (rr_a->herrno == TRY_AGAIN) {
00939 SPF_dns_rr_free(rr_ptr);
00940 SPF_dns_rr_free(rr_a);
00941 SPF_FREE_LOOKUP_DATA();
00942 return DONE_TEMPERR( SPF_E_DNS_ERROR );
00943 }
00944
00945 for (j = 0; j < rr_a->num_rr; j++) {
00946
00947
00948 if (spf_server->debug) {
00949 INET_NTOP(AF_INET, &rr_a->rr[j]->a.s_addr,
00950 ip4_buf, sizeof(ip4_buf));
00951 SPF_debugf("%d: %d: found %s",
00952 i, j, ip4_buf);
00953 }
00954
00955 if (rr_a->rr[j]->a.s_addr ==
00956 spf_request->ipv4.s_addr) {
00957 if (SPF_i_match_domain(spf_server,
00958 rr_ptr->rr[i]->ptr, lookup)) {
00959 SPF_dns_rr_free(rr_ptr);
00960 SPF_dns_rr_free(rr_a);
00961 SPF_FREE_LOOKUP_DATA();
00962 return DONE_MECH(mech->prefix_type);
00963 }
00964 }
00965 }
00966 SPF_dns_rr_free(rr_a);
00967 }
00968 SPF_dns_rr_free(rr_ptr);
00969
00970 if (max_exceeded) {
00971 SPF_FREE_LOOKUP_DATA();
00972 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
00973 }
00974 }
00975
00976 else if ( spf_request->client_ver == AF_INET6 ) {
00977 rr_ptr = SPF_dns_rlookup6(resolver,
00978 spf_request->ipv6, ns_t_ptr, TRUE);
00979
00980 if ( spf_server->debug ) {
00981 INET_NTOP( AF_INET6, &spf_request->ipv6.s6_addr,
00982 ip6_buf, sizeof( ip6_buf ) );
00983 SPF_debugf( "found %d PTR records for %s (herrno: %d)",
00984 rr_ptr->num_rr, ip6_buf, rr_ptr->herrno );
00985 }
00986 if( rr_ptr->herrno == TRY_AGAIN ) {
00987 SPF_dns_rr_free(rr_ptr);
00988 SPF_FREE_LOOKUP_DATA();
00989 return DONE_TEMPERR( SPF_E_DNS_ERROR );
00990 }
00991
00992
00993 max_ptr = rr_ptr->num_rr;
00994 max_exceeded = 0;
00995 if (max_ptr > spf_server->max_dns_ptr) {
00996 max_ptr = SPF_server_get_max_dns_ptr(spf_server);
00997 max_exceeded = 1;
00998 }
00999
01000 for (i = 0; i < max_ptr; i++) {
01001
01002
01003 rr_aaaa = SPF_dns_lookup(resolver,
01004 rr_ptr->rr[i]->ptr, ns_t_aaaa, TRUE);
01005
01006 if ( spf_server->debug )
01007 SPF_debugf("%d: found %d AAAA records for %s (herrno: %d)",
01008 i, rr_aaaa->num_rr, rr_ptr->rr[i]->ptr, rr_aaaa->herrno);
01009 if( rr_aaaa->herrno == TRY_AGAIN ) {
01010 SPF_dns_rr_free(rr_ptr);
01011 SPF_dns_rr_free(rr_aaaa);
01012 SPF_FREE_LOOKUP_DATA();
01013 return DONE_TEMPERR( SPF_E_DNS_ERROR );
01014 }
01015
01016 for( j = 0; j < rr_aaaa->num_rr; j++ ) {
01017
01018 if ( spf_server->debug ) {
01019 INET_NTOP(AF_INET6, &rr_aaaa->rr[j]->aaaa.s6_addr,
01020 ip6_buf, sizeof(ip6_buf));
01021 SPF_debugf( "%d: %d: found %s",
01022 i, j, ip6_buf );
01023 }
01024
01025 if (memcmp(&rr_aaaa->rr[j]->aaaa,
01026 &spf_request->ipv6,
01027 sizeof(spf_request->ipv6)) == 0) {
01028 if (SPF_i_match_domain(spf_server,
01029 rr_ptr->rr[i]->ptr, lookup)) {
01030 SPF_dns_rr_free( rr_ptr );
01031 SPF_dns_rr_free(rr_aaaa);
01032 SPF_FREE_LOOKUP_DATA();
01033 return DONE_MECH( mech->prefix_type );
01034 }
01035 }
01036 }
01037 SPF_dns_rr_free(rr_aaaa);
01038 }
01039 SPF_dns_rr_free(rr_ptr);
01040
01041 if (max_exceeded) {
01042 SPF_FREE_LOOKUP_DATA();
01043 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
01044 }
01045 }
01046
01047
01048 break;
01049
01050 case MECH_INCLUDE:
01051 case MECH_REDIRECT:
01052 SPF_ADD_DNS_MECH();
01053
01054 err = SPF_record_expand_data(spf_server,
01055 spf_request, spf_response,
01056 SPF_mech_data(mech), SPF_mech_data_len(mech),
01057 &buf, &buf_len );
01058 if ( err == SPF_E_NO_MEMORY ) {
01059 SPF_FREE_LOOKUP_DATA();
01060 return DONE_TEMPERR( err );
01061 }
01062 if ( err ) {
01063 SPF_FREE_LOOKUP_DATA();
01064 return DONE_PERMERR( err );
01065 }
01066 lookup = buf;
01067
01068
01069 if (strcmp(lookup, spf_request->cur_dom) == 0) {
01070 SPF_FREE_LOOKUP_DATA();
01071 return DONE_PERMERR( SPF_E_RECURSIVE );
01072 }
01073
01074
01075
01076
01077
01078 spf_record_subr = NULL;
01079
01080 save_cur_dom = spf_request->cur_dom;
01081 spf_request->cur_dom = lookup;
01082 err = SPF_server_get_record(spf_server, spf_request,
01083 spf_response, &spf_record_subr);
01084
01085 if ( spf_server->debug > 0 )
01086 SPF_debugf( "include/redirect: got SPF record: %s",
01087 SPF_strerror( err ) );
01088
01089 if (err != SPF_E_SUCCESS) {
01090 spf_request->cur_dom = save_cur_dom;
01091 if (spf_record_subr)
01092 SPF_record_free(spf_record_subr);
01093 SPF_FREE_LOOKUP_DATA();
01094 if (err == SPF_E_DNS_ERROR)
01095 return DONE_TEMPERR( err );
01096 else
01097 return DONE_PERMERR( err );
01098 }
01099
01100 SPF_ASSERT_NOTNULL(spf_record_subr);
01101
01102
01103
01104
01105
01106 if (mech->mech_type == MECH_REDIRECT) {
01107 save_spf_response = NULL;
01108 if (spf_response->spf_record_exp == spf_record)
01109 spf_response->spf_record_exp = spf_record_subr;
01110 SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
01111 }
01112 else {
01113 save_spf_response = spf_response;
01114 spf_response = SPF_response_new(spf_request);
01115 if (! spf_response) {
01116 if (spf_record_subr)
01117 SPF_record_free(spf_record_subr);
01118 SPF_FREE_LOOKUP_DATA();
01119 return DONE_TEMPERR(SPF_E_NO_MEMORY);
01120 }
01121 spf_response->spf_record_exp = spf_record;
01122 SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
01123 }
01124
01125
01126
01127 err = SPF_record_interpret(spf_record_subr,
01128 spf_request, spf_response, depth + 1);
01129 spf_request->cur_dom = save_cur_dom;
01130
01131
01132
01133
01134
01135
01136 SPF_record_free(spf_record_subr);
01137 spf_record_subr = NULL;
01138
01139 if ( spf_server->debug > 0 )
01140 SPF_debugf( "include/redirect: executed SPF record: %s result: %s reason: %s",
01141 SPF_strerror( err ),
01142 SPF_strresult( spf_response->result ),
01143 SPF_strreason( spf_response->reason ) );
01144 if (mech->mech_type == MECH_REDIRECT) {
01145 SPF_FREE_LOOKUP_DATA();
01146 return err;
01147 }
01148 else {
01149
01150 spf_response_subr = spf_response;
01151 spf_response = save_spf_response;
01152 save_spf_response = NULL;
01153
01154
01155 switch (SPF_response_result(spf_response_subr)) {
01156 case SPF_RESULT_PASS:
01157
01158 SPF_FREE_LOOKUP_DATA();
01159 SPF_response_free(spf_response_subr);
01160 return DONE_MECH( mech->prefix_type );
01161
01162 case SPF_RESULT_FAIL:
01163 case SPF_RESULT_SOFTFAIL:
01164 case SPF_RESULT_NEUTRAL:
01165
01166 SPF_response_free(spf_response_subr);
01167 break;
01168
01169 case SPF_RESULT_TEMPERROR:
01170
01171 err = SPF_response_errcode(spf_response_subr);
01172 SPF_FREE_LOOKUP_DATA();
01173 SPF_response_free(spf_response_subr);
01174 return DONE_TEMPERR( err );
01175
01176 case SPF_RESULT_NONE:
01177
01178 SPF_FREE_LOOKUP_DATA();
01179 SPF_response_free(spf_response_subr);
01180 return DONE_PERMERR(SPF_E_INCLUDE_RETURNED_NONE);
01181 case SPF_RESULT_PERMERROR:
01182 case SPF_RESULT_INVALID:
01183
01184 err = SPF_response_errcode(spf_response_subr);
01185 SPF_FREE_LOOKUP_DATA();
01186 SPF_response_free(spf_response_subr);
01187 return DONE_PERMERR( err );
01188
01189 }
01190 #if 0
01191 SPF_FREE_LOOKUP_DATA();
01192 return err;
01193 #endif
01194 }
01195
01196 break;
01197
01198 case MECH_IP4:
01199 memcpy(&addr4, SPF_mech_ip4_data(mech), sizeof(addr4));
01200 if ( SPF_i_match_ip4( spf_server, spf_request, mech, addr4 ) ) {
01201 SPF_FREE_LOOKUP_DATA();
01202 return DONE_MECH( mech->prefix_type );
01203 }
01204 break;
01205
01206 case MECH_IP6:
01207 memcpy(&addr6, SPF_mech_ip6_data(mech), sizeof(addr6));
01208 if ( SPF_i_match_ip6( spf_server, spf_request, mech, addr6 ) ) {
01209 SPF_FREE_LOOKUP_DATA();
01210 return DONE_MECH( mech->prefix_type );
01211 }
01212 break;
01213
01214 case MECH_EXISTS:
01215 SPF_ADD_DNS_MECH();
01216
01217 err = SPF_record_expand_data(spf_server,
01218 spf_request, spf_response,
01219 SPF_mech_data(mech),SPF_mech_data_len(mech),
01220 &buf, &buf_len);
01221 if (err != SPF_E_SUCCESS) {
01222 SPF_FREE_LOOKUP_DATA();
01223 return DONE_TEMPERR( err );
01224 }
01225 lookup = buf;
01226
01227 rr_a = SPF_dns_lookup(resolver, lookup, ns_t_a, FALSE );
01228
01229 if ( spf_server->debug )
01230 SPF_debugf( "found %d A records for %s (herrno: %d)",
01231 rr_a->num_rr, lookup, rr_a->herrno );
01232
01233 if( rr_a->herrno == TRY_AGAIN ) {
01234 SPF_dns_rr_free(rr_a);
01235 SPF_FREE_LOOKUP_DATA();
01236 return DONE_TEMPERR(SPF_E_DNS_ERROR);
01237 }
01238 if ( rr_a->num_rr > 0 ) {
01239 SPF_dns_rr_free(rr_a);
01240 SPF_FREE_LOOKUP_DATA();
01241 return DONE_MECH(mech->prefix_type);
01242 }
01243
01244 SPF_dns_rr_free(rr_a);
01245 break;
01246
01247 case MECH_ALL:
01248 SPF_FREE_LOOKUP_DATA();
01249 if (mech->prefix_type == PREFIX_UNKNOWN)
01250 return DONE_PERMERR(SPF_E_UNKNOWN_MECH);
01251 return DONE_MECH(mech->prefix_type);
01252 break;
01253
01254 default:
01255 SPF_FREE_LOOKUP_DATA();
01256 return DONE_PERMERR(SPF_E_UNKNOWN_MECH);
01257 break;
01258 }
01259
01260
01261
01262
01263
01264 if ( mech == local_policy ) {
01265 err = SPF_record_interpret(spf_server->local_policy,
01266 spf_request, spf_response, depth + 1);
01267
01268 if ( spf_server->debug > 0 )
01269 SPF_debugf( "local_policy: executed SPF record: %s result: %s reason: %s",
01270 SPF_strerror( err ),
01271 SPF_strresult( spf_response->result ),
01272 SPF_strreason( spf_response->reason ) );
01273
01274 if (spf_response->result != SPF_RESULT_INVALID) {
01275 SPF_FREE_LOOKUP_DATA();
01276 return err;
01277 }
01278 }
01279
01280 mech = SPF_mech_next( mech );
01281 }
01282
01283 SPF_FREE_LOOKUP_DATA();
01284
01285 return DONE( SPF_RESULT_NEUTRAL, SPF_REASON_DEFAULT, SPF_E_SUCCESS );
01286 }