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 case SPF_RESULT_NONE:
00108
00109 err = SPF_i_set_explanation(spf_response);
00110 if (err != SPF_E_SUCCESS)
00111 return err;
00112
00113 memset(buf, '\0', sizeof(buf));
00114 snprintf(buf, SPF_SMTP_COMMENT_SIZE, "%s : Reason: %s",
00115 spf_response->explanation,
00116 SPF_strreason(spf_response->reason));
00117 buf[SPF_SMTP_COMMENT_SIZE - 1] = '\0';
00118
00119
00120 spf_response->smtp_comment = strdup(buf);
00121 if (! spf_response->smtp_comment)
00122 return SPF_E_NO_MEMORY;
00123
00124 break;
00125 case SPF_RESULT_INVALID:
00126 case SPF_RESULT_PASS:
00127 case SPF_RESULT_TEMPERROR:
00128 case SPF_RESULT_PERMERROR:
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, 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
00521 match = TRUE;
00522 for( i = 0; i < array_elem( ipv6.s6_addr ) && match; i++ )
00523 {
00524 if ( cidr > 8 )
00525 mask = 0xff;
00526 else if ( cidr > 0 )
00527 mask = (0xff << (8 - cidr)) & 0xff;
00528 else
00529 break;
00530 cidr -= 8;
00531
00532 match = (src_ipv6.s6_addr[i] & mask) == (ipv6.s6_addr[i] & mask);
00533 }
00534
00535 if (spf_server->debug) {
00536 INET_NTOP(AF_INET6, &src_ipv6.s6_addr,
00537 src_ip6_buf, sizeof(src_ip6_buf));
00538 INET_NTOP(AF_INET6, &ipv6.s6_addr,
00539 dst_ip6_buf, sizeof(dst_ip6_buf));
00540 SPF_debugf( "ip_match: %s == %s (/%d): %d",
00541 src_ip6_buf, dst_ip6_buf, cidr, match );
00542 }
00543
00544 return match;
00545 }
00546
00547 static int
00548 SPF_i_match_domain(SPF_server_t *spf_server,
00549 const char *hostname, const char *domain)
00550 {
00551 const char *hp;
00552 int hlen;
00553 int dlen;
00554
00555 if (spf_server->debug)
00556 SPF_debugf( "%s ?=? %s", hostname, domain );
00557
00558 hlen = strlen(hostname);
00559 dlen = strlen(domain);
00560
00561
00562 if (dlen > hlen)
00563 return 0;
00564
00565
00566 if (dlen == hlen)
00567 return (strcasecmp(hostname, domain) == 0);
00568
00569
00570 hp = hostname + (hlen - dlen);
00571
00572 if (*(hp - 1) != '.')
00573 return 0;
00574
00575 return (strcasecmp(hp, domain) == 0);
00576 }
00577
00578
00579
00580
00581
00582
00583 SPF_errcode_t
00584 SPF_record_interpret(SPF_record_t *spf_record,
00585 SPF_request_t *spf_request, SPF_response_t *spf_response,
00586 int depth)
00587 {
00588 SPF_server_t *spf_server;
00589
00590
00591 int i, j;
00592 int m;
00593 SPF_mech_t *mech;
00594 SPF_data_t *data;
00595 SPF_data_t *data_end;
00596
00597
00598 SPF_mech_t *local_policy;
00599 int found_all;
00600
00601 char *buf = NULL;
00602 size_t buf_len = 0;
00603 ns_type fetch_ns_type;
00604 const char *lookup;
00605
00606 SPF_dns_rr_t *rr_a;
00607 SPF_dns_rr_t *rr_aaaa;
00608 SPF_dns_rr_t *rr_ptr;
00609 SPF_dns_rr_t *rr_mx;
00610
00611 SPF_errcode_t err;
00612
00613 SPF_dns_server_t*resolver;
00614
00615
00616 SPF_record_t *spf_record_subr;
00617
00618 SPF_response_t *save_spf_response;
00619 SPF_response_t *spf_response_subr;
00620 const char *save_cur_dom;
00621
00622 struct in_addr addr4;
00623 struct in6_addr addr6;
00624
00625 int max_ptr;
00626 int max_mx;
00627 int max_exceeded;
00628
00629 char ip4_buf[ INET_ADDRSTRLEN ];
00630 char ip6_buf[ INET6_ADDRSTRLEN ];
00631
00632
00633
00634
00635
00636 SPF_ASSERT_NOTNULL(spf_record);
00637 SPF_ASSERT_NOTNULL(spf_request);
00638 SPF_ASSERT_NOTNULL(spf_response);
00639 spf_server = spf_record->spf_server;
00640 SPF_ASSERT_NOTNULL(spf_server);
00641
00642 SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
00643
00644 if (depth > 20)
00645 return DONE_PERMERR(SPF_E_RECURSIVE);
00646
00647 if ( spf_request->client_ver != AF_INET && spf_request->client_ver != AF_INET6 )
00648 return DONE_PERMERR(SPF_E_NOT_CONFIG);
00649
00650 if (spf_request->cur_dom == NULL)
00651 return DONE_PERMERR(SPF_E_NOT_CONFIG);
00652
00653
00654
00655
00656
00657
00658 #if 0
00659
00660 if ( SPF_request_is_loopback( spf_request ) )
00661 return DONE(SPF_RESULT_PASS,SPF_REASON_LOCALHOST,SPF_E_SUCCESS);
00662 #endif
00663
00664
00665
00666
00667
00668 local_policy = NULL;
00669
00670 if ( spf_request->use_local_policy ) {
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 if ( spf_server->local_policy ) {
00688 mech = spf_record->mech_first;
00689
00690 found_all = FALSE;
00691 for(m = 0; m < spf_record->num_mech; m++)
00692 {
00693 if ( mech->mech_type == MECH_ALL
00694 && (mech->prefix_type == PREFIX_FAIL
00695 || mech->prefix_type == PREFIX_UNKNOWN
00696 || mech->prefix_type == PREFIX_SOFTFAIL
00697 )
00698 )
00699 found_all = TRUE;
00700
00701 if ( mech->prefix_type != PREFIX_FAIL
00702 && mech->prefix_type != PREFIX_SOFTFAIL
00703 )
00704 local_policy = mech;
00705
00706 mech = SPF_mech_next( mech );
00707 }
00708
00709 if ( !found_all )
00710 local_policy = NULL;
00711 }
00712
00713 }
00714
00715
00716
00717
00718
00719
00720 #define SPF_ADD_DNS_MECH() do { spf_response->num_dns_mech++; } while(0)
00721
00722 #define SPF_MAYBE_SKIP_CIDR() \
00723 do { \
00724 if ( data < data_end && data->dc.parm_type == PARM_CIDR ) \
00725 data = SPF_data_next( data ); \
00726 } while(0)
00727
00728 #define SPF_GET_LOOKUP_DATA() \
00729 do { \
00730 if ( data == data_end ) \
00731 lookup = spf_request->cur_dom; \
00732 else { \
00733 err = SPF_record_expand_data( spf_server, \
00734 spf_request, spf_response, \
00735 data, ((char *)data_end - (char *)data), \
00736 &buf, &buf_len ); \
00737 if (err == SPF_E_NO_MEMORY) { \
00738 SPF_FREE_LOOKUP_DATA(); \
00739 return DONE_TEMPERR(err); \
00740 } \
00741 if (err) { \
00742 SPF_FREE_LOOKUP_DATA(); \
00743 return DONE_PERMERR(err); \
00744 } \
00745 lookup = buf; \
00746 } \
00747 } while(0)
00748 #define SPF_FREE_LOOKUP_DATA() \
00749 do { if (buf != NULL) { free(buf); buf = NULL; } } while(0)
00750
00751
00752 resolver = spf_server->resolver;
00753
00754 mech = spf_record->mech_first;
00755 for (m = 0; m < spf_record->num_mech; m++) {
00756
00757
00758
00759 if (spf_response->num_dns_mech > spf_server->max_dns_mech) {
00760 SPF_FREE_LOOKUP_DATA();
00761 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
00762 }
00763
00764 data = SPF_mech_data(mech);
00765 data_end = SPF_mech_end_data(mech);
00766
00767 switch (mech->mech_type) {
00768 case MECH_A:
00769 SPF_ADD_DNS_MECH();
00770 SPF_MAYBE_SKIP_CIDR();
00771 SPF_GET_LOOKUP_DATA();
00772
00773 if (spf_request->client_ver == AF_INET)
00774 fetch_ns_type = ns_t_a;
00775 else
00776 fetch_ns_type = ns_t_aaaa;
00777
00778 rr_a = SPF_dns_lookup(resolver, lookup, fetch_ns_type, TRUE);
00779
00780 if (spf_server->debug)
00781 SPF_debugf("found %d A records for %s (herrno: %d)",
00782 rr_a->num_rr, lookup, rr_a->herrno);
00783
00784 if (rr_a->herrno == TRY_AGAIN) {
00785 SPF_dns_rr_free(rr_a);
00786 SPF_FREE_LOOKUP_DATA();
00787 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00788 }
00789
00790 for (i = 0; i < rr_a->num_rr; i++) {
00791
00792 if (rr_a->rr_type != fetch_ns_type)
00793 continue;
00794
00795 if (spf_request->client_ver == AF_INET) {
00796 if (SPF_i_match_ip4(spf_server, spf_request, mech, rr_a->rr[i]->a)) {
00797 SPF_dns_rr_free(rr_a);
00798 SPF_FREE_LOOKUP_DATA();
00799 return DONE_MECH(mech->prefix_type);
00800 }
00801 }
00802 else {
00803 if (SPF_i_match_ip6(spf_server, spf_request, mech, rr_a->rr[i]->aaaa)) {
00804 SPF_dns_rr_free(rr_a);
00805 SPF_FREE_LOOKUP_DATA();
00806 return DONE_MECH(mech->prefix_type);
00807 }
00808 }
00809 }
00810
00811 SPF_dns_rr_free(rr_a);
00812 break;
00813
00814 case MECH_MX:
00815 SPF_ADD_DNS_MECH();
00816 SPF_MAYBE_SKIP_CIDR();
00817 SPF_GET_LOOKUP_DATA();
00818
00819 rr_mx = SPF_dns_lookup(resolver, lookup, ns_t_mx, TRUE);
00820
00821 if (spf_server->debug)
00822 SPF_debugf("found %d MX records for %s (herrno: %d)",
00823 rr_mx->num_rr, lookup, rr_mx->herrno);
00824
00825 if (rr_mx->herrno == TRY_AGAIN) {
00826 SPF_dns_rr_free(rr_mx);
00827 SPF_FREE_LOOKUP_DATA();
00828 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00829 }
00830
00831
00832 max_mx = rr_mx->num_rr;
00833 max_exceeded = 0;
00834 if (max_mx > spf_server->max_dns_mx) {
00835 max_exceeded = 1;
00836 max_mx = SPF_server_get_max_dns_mx(spf_server);
00837 }
00838
00839 for (j = 0; j < max_mx; j++) {
00840
00841 if (rr_mx->rr_type != ns_t_mx)
00842 continue;
00843
00844 if (spf_request->client_ver == AF_INET)
00845 fetch_ns_type = ns_t_a;
00846 else
00847 fetch_ns_type = ns_t_aaaa;
00848
00849 rr_a = SPF_dns_lookup(resolver, rr_mx->rr[j]->mx,
00850 fetch_ns_type, TRUE );
00851
00852 if (spf_server->debug)
00853 SPF_debugf("%d: found %d A records for %s (herrno: %d)",
00854 j, rr_a->num_rr, rr_mx->rr[j]->mx, rr_a->herrno);
00855 if (rr_a->herrno == TRY_AGAIN) {
00856 SPF_dns_rr_free(rr_mx);
00857 SPF_dns_rr_free(rr_a);
00858 SPF_FREE_LOOKUP_DATA();
00859 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00860 }
00861
00862 for (i = 0; i < rr_a->num_rr; i++) {
00863
00864 if (rr_a->rr_type != fetch_ns_type)
00865 continue;
00866
00867 if (spf_request->client_ver == AF_INET) {
00868 if (SPF_i_match_ip4(spf_server, spf_request, mech,
00869 rr_a->rr[i]->a)) {
00870 SPF_dns_rr_free(rr_mx);
00871 SPF_dns_rr_free(rr_a);
00872 SPF_FREE_LOOKUP_DATA();
00873 return DONE(mech->prefix_type, SPF_REASON_MECH,
00874 SPF_E_SUCCESS);
00875 }
00876 }
00877 else {
00878 if (SPF_i_match_ip6(spf_server, spf_request, mech,
00879 rr_a->rr[i]->aaaa)) {
00880 SPF_dns_rr_free(rr_mx);
00881 SPF_dns_rr_free(rr_a);
00882 SPF_FREE_LOOKUP_DATA();
00883 return DONE(mech->prefix_type, SPF_REASON_MECH,
00884 SPF_E_SUCCESS);
00885 }
00886 }
00887 }
00888 SPF_dns_rr_free(rr_a);
00889 }
00890
00891 SPF_dns_rr_free( rr_mx );
00892 if (max_exceeded) {
00893 SPF_FREE_LOOKUP_DATA();
00894 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
00895 }
00896 break;
00897
00898 case MECH_PTR:
00899 SPF_ADD_DNS_MECH();
00900 SPF_GET_LOOKUP_DATA();
00901
00902 if (spf_request->client_ver == AF_INET) {
00903 rr_ptr = SPF_dns_rlookup(resolver,
00904 spf_request->ipv4, ns_t_ptr, TRUE);
00905
00906 if (spf_server->debug) {
00907 INET_NTOP(AF_INET, &spf_request->ipv4.s_addr,
00908 ip4_buf, sizeof(ip4_buf));
00909 SPF_debugf("got %d PTR records for %s (herrno: %d)",
00910 rr_ptr->num_rr, ip4_buf, rr_ptr->herrno);
00911 }
00912
00913 if (rr_ptr->herrno == TRY_AGAIN) {
00914 SPF_dns_rr_free(rr_ptr);
00915 SPF_FREE_LOOKUP_DATA();
00916 return DONE_TEMPERR(SPF_E_DNS_ERROR);
00917 }
00918
00919
00920
00921 max_ptr = rr_ptr->num_rr;
00922 max_exceeded = 0;
00923 if (max_ptr > spf_server->max_dns_ptr) {
00924 max_exceeded = 1;
00925 max_ptr = SPF_server_get_max_dns_ptr(spf_server);
00926 }
00927
00928 for (i = 0; i < max_ptr; i++) {
00929
00930
00931 rr_a = SPF_dns_lookup(resolver,
00932 rr_ptr->rr[i]->ptr, ns_t_a, TRUE);
00933
00934 if (spf_server->debug)
00935 SPF_debugf( "%d: found %d A records for %s (herrno: %d)",
00936 i, rr_a->num_rr, rr_ptr->rr[i]->ptr, rr_a->herrno );
00937 if (rr_a->herrno == TRY_AGAIN) {
00938 SPF_dns_rr_free(rr_ptr);
00939 SPF_dns_rr_free(rr_a);
00940 SPF_FREE_LOOKUP_DATA();
00941 return DONE_TEMPERR( SPF_E_DNS_ERROR );
00942 }
00943
00944 for (j = 0; j < rr_a->num_rr; j++) {
00945
00946
00947 if (spf_server->debug) {
00948 INET_NTOP(AF_INET, &rr_a->rr[j]->a.s_addr,
00949 ip4_buf, sizeof(ip4_buf));
00950 SPF_debugf("%d: %d: found %s",
00951 i, j, ip4_buf);
00952 }
00953
00954 if (rr_a->rr[j]->a.s_addr ==
00955 spf_request->ipv4.s_addr) {
00956 if (SPF_i_match_domain(spf_server,
00957 rr_ptr->rr[i]->ptr, lookup)) {
00958 SPF_dns_rr_free(rr_ptr);
00959 SPF_dns_rr_free(rr_a);
00960 SPF_FREE_LOOKUP_DATA();
00961 return DONE_MECH(mech->prefix_type);
00962 }
00963 }
00964 }
00965 SPF_dns_rr_free(rr_a);
00966 }
00967 SPF_dns_rr_free(rr_ptr);
00968
00969 if (max_exceeded) {
00970 SPF_FREE_LOOKUP_DATA();
00971 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
00972 }
00973 }
00974
00975 else if ( spf_request->client_ver == AF_INET6 ) {
00976 rr_ptr = SPF_dns_rlookup6(resolver,
00977 spf_request->ipv6, ns_t_ptr, TRUE);
00978
00979 if ( spf_server->debug ) {
00980 INET_NTOP( AF_INET6, &spf_request->ipv6.s6_addr,
00981 ip6_buf, sizeof( ip6_buf ) );
00982 SPF_debugf( "found %d PTR records for %s (herrno: %d)",
00983 rr_ptr->num_rr, ip6_buf, rr_ptr->herrno );
00984 }
00985 if( rr_ptr->herrno == TRY_AGAIN ) {
00986 SPF_dns_rr_free(rr_ptr);
00987 SPF_FREE_LOOKUP_DATA();
00988 return DONE_TEMPERR( SPF_E_DNS_ERROR );
00989 }
00990
00991
00992 max_ptr = rr_ptr->num_rr;
00993 max_exceeded = 0;
00994 if (max_ptr > spf_server->max_dns_ptr) {
00995 max_ptr = SPF_server_get_max_dns_ptr(spf_server);
00996 max_exceeded = 1;
00997 }
00998
00999 for (i = 0; i < max_ptr; i++) {
01000
01001
01002 rr_aaaa = SPF_dns_lookup(resolver,
01003 rr_ptr->rr[i]->ptr, ns_t_aaaa, TRUE);
01004
01005 if ( spf_server->debug )
01006 SPF_debugf("%d: found %d AAAA records for %s (herrno: %d)",
01007 i, rr_aaaa->num_rr, rr_ptr->rr[i]->ptr, rr_aaaa->herrno);
01008 if( rr_aaaa->herrno == TRY_AGAIN ) {
01009 SPF_dns_rr_free(rr_ptr);
01010 SPF_dns_rr_free(rr_aaaa);
01011 SPF_FREE_LOOKUP_DATA();
01012 return DONE_TEMPERR( SPF_E_DNS_ERROR );
01013 }
01014
01015 for( j = 0; j < rr_aaaa->num_rr; j++ ) {
01016
01017 if ( spf_server->debug ) {
01018 INET_NTOP(AF_INET6, &rr_aaaa->rr[j]->aaaa.s6_addr,
01019 ip6_buf, sizeof(ip6_buf));
01020 SPF_debugf( "%d: %d: found %s",
01021 i, j, ip6_buf );
01022 }
01023
01024 if (memcmp(&rr_aaaa->rr[j]->aaaa,
01025 &spf_request->ipv6,
01026 sizeof(spf_request->ipv6)) == 0) {
01027 if (SPF_i_match_domain(spf_server,
01028 rr_ptr->rr[i]->ptr, lookup)) {
01029 SPF_dns_rr_free( rr_ptr );
01030 SPF_dns_rr_free(rr_aaaa);
01031 SPF_FREE_LOOKUP_DATA();
01032 return DONE_MECH( mech->prefix_type );
01033 }
01034 }
01035 }
01036 SPF_dns_rr_free(rr_aaaa);
01037 }
01038 SPF_dns_rr_free(rr_ptr);
01039
01040 if (max_exceeded) {
01041 SPF_FREE_LOOKUP_DATA();
01042 return DONE(SPF_RESULT_PERMERROR, SPF_REASON_NONE, SPF_E_BIG_DNS);
01043 }
01044 }
01045
01046
01047 break;
01048
01049 case MECH_INCLUDE:
01050 case MECH_REDIRECT:
01051 SPF_ADD_DNS_MECH();
01052
01053 err = SPF_record_expand_data(spf_server,
01054 spf_request, spf_response,
01055 SPF_mech_data(mech), SPF_mech_data_len(mech),
01056 &buf, &buf_len );
01057 if ( err == SPF_E_NO_MEMORY ) {
01058 SPF_FREE_LOOKUP_DATA();
01059 return DONE_TEMPERR( err );
01060 }
01061 if ( err ) {
01062 SPF_FREE_LOOKUP_DATA();
01063 return DONE_PERMERR( err );
01064 }
01065 lookup = buf;
01066
01067
01068 if (strcmp(lookup, spf_request->cur_dom) == 0) {
01069 SPF_FREE_LOOKUP_DATA();
01070 return DONE_PERMERR( SPF_E_RECURSIVE );
01071 }
01072
01073
01074
01075
01076
01077 spf_record_subr = NULL;
01078
01079 save_cur_dom = spf_request->cur_dom;
01080 spf_request->cur_dom = lookup;
01081 err = SPF_server_get_record(spf_server, spf_request,
01082 spf_response, &spf_record_subr);
01083
01084 if ( spf_server->debug > 0 )
01085 SPF_debugf( "include/redirect: got SPF record: %s",
01086 SPF_strerror( err ) );
01087
01088 if (err != SPF_E_SUCCESS) {
01089 spf_request->cur_dom = save_cur_dom;
01090 if (spf_record_subr)
01091 SPF_record_free(spf_record_subr);
01092 SPF_FREE_LOOKUP_DATA();
01093 if (err == SPF_E_DNS_ERROR)
01094 return DONE_TEMPERR( err );
01095 else
01096 return DONE_PERMERR( err );
01097 }
01098
01099 SPF_ASSERT_NOTNULL(spf_record_subr);
01100
01101
01102
01103
01104
01105 if (mech->mech_type == MECH_REDIRECT) {
01106 save_spf_response = NULL;
01107 if (spf_response->spf_record_exp == spf_record)
01108 spf_response->spf_record_exp = spf_record_subr;
01109 SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
01110 }
01111 else {
01112 save_spf_response = spf_response;
01113 spf_response = SPF_response_new(spf_request);
01114 if (! spf_response) {
01115 if (spf_record_subr)
01116 SPF_record_free(spf_record_subr);
01117 SPF_FREE_LOOKUP_DATA();
01118 return DONE_TEMPERR(SPF_E_NO_MEMORY);
01119 }
01120 spf_response->spf_record_exp = spf_record;
01121 SPF_ASSERT_NOTNULL(spf_response->spf_record_exp);
01122 }
01123
01124
01125
01126 err = SPF_record_interpret(spf_record_subr,
01127 spf_request, spf_response, depth + 1);
01128 spf_request->cur_dom = save_cur_dom;
01129
01130
01131
01132
01133
01134
01135 SPF_record_free(spf_record_subr);
01136 spf_record_subr = NULL;
01137
01138 if ( spf_server->debug > 0 )
01139 SPF_debugf( "include/redirect: executed SPF record: %s result: %s reason: %s",
01140 SPF_strerror( err ),
01141 SPF_strresult( spf_response->result ),
01142 SPF_strreason( spf_response->reason ) );
01143 if (mech->mech_type == MECH_REDIRECT) {
01144 SPF_FREE_LOOKUP_DATA();
01145 return err;
01146 }
01147 else {
01148
01149 spf_response_subr = spf_response;
01150 spf_response = save_spf_response;
01151 save_spf_response = NULL;
01152
01153
01154 switch (SPF_response_result(spf_response_subr)) {
01155 case SPF_RESULT_PASS:
01156
01157 SPF_FREE_LOOKUP_DATA();
01158 SPF_response_free(spf_response_subr);
01159 return DONE_MECH( mech->prefix_type );
01160
01161 case SPF_RESULT_FAIL:
01162 case SPF_RESULT_SOFTFAIL:
01163 case SPF_RESULT_NEUTRAL:
01164
01165 SPF_response_free(spf_response_subr);
01166 break;
01167
01168 case SPF_RESULT_TEMPERROR:
01169
01170 err = SPF_response_errcode(spf_response_subr);
01171 SPF_FREE_LOOKUP_DATA();
01172 SPF_response_free(spf_response_subr);
01173 return DONE_TEMPERR( err );
01174
01175 case SPF_RESULT_NONE:
01176
01177 SPF_FREE_LOOKUP_DATA();
01178 SPF_response_free(spf_response_subr);
01179 return DONE_PERMERR(SPF_E_INCLUDE_RETURNED_NONE);
01180 case SPF_RESULT_PERMERROR:
01181 case SPF_RESULT_INVALID:
01182
01183 err = SPF_response_errcode(spf_response_subr);
01184 SPF_FREE_LOOKUP_DATA();
01185 SPF_response_free(spf_response_subr);
01186 return DONE_PERMERR( err );
01187
01188 }
01189 #if 0
01190 SPF_FREE_LOOKUP_DATA();
01191 return err;
01192 #endif
01193 }
01194
01195 break;
01196
01197 case MECH_IP4:
01198 memcpy(&addr4, SPF_mech_ip4_data(mech), sizeof(addr4));
01199 if ( SPF_i_match_ip4( spf_server, spf_request, mech, addr4 ) ) {
01200 SPF_FREE_LOOKUP_DATA();
01201 return DONE_MECH( mech->prefix_type );
01202 }
01203 break;
01204
01205 case MECH_IP6:
01206 memcpy(&addr6, SPF_mech_ip6_data(mech), sizeof(addr6));
01207 if ( SPF_i_match_ip6( spf_server, spf_request, mech, addr6 ) ) {
01208 SPF_FREE_LOOKUP_DATA();
01209 return DONE_MECH( mech->prefix_type );
01210 }
01211 break;
01212
01213 case MECH_EXISTS:
01214 SPF_ADD_DNS_MECH();
01215
01216 err = SPF_record_expand_data(spf_server,
01217 spf_request, spf_response,
01218 SPF_mech_data(mech),SPF_mech_data_len(mech),
01219 &buf, &buf_len);
01220 if (err != SPF_E_SUCCESS) {
01221 SPF_FREE_LOOKUP_DATA();
01222 return DONE_TEMPERR( err );
01223 }
01224 lookup = buf;
01225
01226 rr_a = SPF_dns_lookup(resolver, lookup, ns_t_a, FALSE );
01227
01228 if ( spf_server->debug )
01229 SPF_debugf( "found %d A records for %s (herrno: %d)",
01230 rr_a->num_rr, lookup, rr_a->herrno );
01231
01232 if( rr_a->herrno == TRY_AGAIN ) {
01233 SPF_dns_rr_free(rr_a);
01234 SPF_FREE_LOOKUP_DATA();
01235 return DONE_TEMPERR(SPF_E_DNS_ERROR);
01236 }
01237 if ( rr_a->num_rr > 0 ) {
01238 SPF_dns_rr_free(rr_a);
01239 SPF_FREE_LOOKUP_DATA();
01240 return DONE_MECH(mech->prefix_type);
01241 }
01242
01243 SPF_dns_rr_free(rr_a);
01244 break;
01245
01246 case MECH_ALL:
01247 SPF_FREE_LOOKUP_DATA();
01248 if (mech->prefix_type == PREFIX_UNKNOWN)
01249 return DONE_PERMERR(SPF_E_UNKNOWN_MECH);
01250 return DONE_MECH(mech->prefix_type);
01251 break;
01252
01253 default:
01254 SPF_FREE_LOOKUP_DATA();
01255 return DONE_PERMERR(SPF_E_UNKNOWN_MECH);
01256 break;
01257 }
01258
01259
01260
01261
01262
01263 if ( mech == local_policy ) {
01264 err = SPF_record_interpret(spf_server->local_policy,
01265 spf_request, spf_response, depth + 1);
01266
01267 if ( spf_server->debug > 0 )
01268 SPF_debugf( "local_policy: executed SPF record: %s result: %s reason: %s",
01269 SPF_strerror( err ),
01270 SPF_strresult( spf_response->result ),
01271 SPF_strreason( spf_response->reason ) );
01272
01273 if (spf_response->result != SPF_RESULT_INVALID) {
01274 SPF_FREE_LOOKUP_DATA();
01275 return err;
01276 }
01277 }
01278
01279 mech = SPF_mech_next( mech );
01280 }
01281
01282 SPF_FREE_LOOKUP_DATA();
01283
01284 return DONE( SPF_RESULT_NEUTRAL, SPF_REASON_DEFAULT, SPF_E_SUCCESS );
01285 }