44SPF_i_set_explanation(SPF_response_t *spf_response)
46 SPF_server_t *spf_server;
47 SPF_request_t *spf_request;
48 SPF_record_t *spf_record;
54 spf_request = spf_response->spf_request;
56 spf_server = spf_request->spf_server;
59 spf_record = spf_response->spf_record_exp;
62 if (spf_response->explanation)
63 free(spf_response->explanation);
64 spf_response->explanation =
NULL;
70 memset(buf,
'\0', buflen);
73 spf_response, spf_record, &buf, &buflen);
79 spf_response->explanation = buf;
85SPF_i_set_smtp_comment(SPF_response_t *spf_response)
87 SPF_server_t *spf_server;
88 SPF_request_t *spf_request;
93 spf_request = spf_response->spf_request;
95 spf_server = spf_request->spf_server;
98 if (spf_response->smtp_comment)
99 free(spf_response->smtp_comment);
100 spf_response->smtp_comment =
NULL;
103 switch (spf_response->result) {
108 err = SPF_i_set_explanation(spf_response);
112 memset(buf,
'\0',
sizeof(buf));
114 spf_response->explanation,
119 spf_response->smtp_comment = strdup(buf);
120 if (! spf_response->smtp_comment)
137SPF_i_set_header_comment(SPF_response_t *spf_response)
139 SPF_server_t *spf_server;
140 SPF_request_t *spf_request;
145 char ip4_buf[ INET_ADDRSTRLEN ];
146 char ip6_buf[ INET6_ADDRSTRLEN ];
154 spf_request = spf_response->spf_request;
156 spf_server = spf_request->spf_server;
159 if (spf_response->header_comment)
160 free(spf_response->header_comment);
161 spf_response->header_comment =
NULL;
164 sender_dom = spf_request->env_from_dp;
165 if (sender_dom ==
NULL)
166 sender_dom = spf_request->helo_dom;
169 spf_source = strdup(
"local policy" );
172 if ( spf_request->rcpt_to_dom ==
NULL || spf_request->rcpt_to_dom[0] ==
'\0' )
175 spf_source = strdup( spf_request->rcpt_to_dom );
177 else if ( sender_dom ==
NULL ) {
178 spf_source = strdup(
"unknown domain" );
181 len = strlen( sender_dom ) +
sizeof(
"domain of " );
182 spf_source = malloc( len );
184 snprintf( spf_source, len,
"domain of %s", sender_dom );
187 if ( spf_source ==
NULL )
191 if ( spf_request->client_ver == AF_INET ) {
192 ip = inet_ntop( AF_INET, &spf_request->ipv4,
193 ip4_buf,
sizeof( ip4_buf ) );
195 else if (spf_request->client_ver == AF_INET6 ) {
196 ip = inet_ntop( AF_INET6, &spf_request->ipv6,
197 ip6_buf,
sizeof( ip6_buf ) );
200 ip =
"(unknown ip address)";
215 switch(spf_response->result)
219 snprintf( p, p_end - p,
"localhost is always allowed." );
221 snprintf( p, p_end - p,
"message received from %s which is an MX secondary for %s.",
224 snprintf( p, p_end - p,
"%s designates %s as permitted sender",
229 snprintf( p, p_end - p,
"%s does not designate %s as permitted sender",
234 snprintf( p, p_end - p,
"transitioning %s does not designate %s as permitted sender",
239 snprintf(p, p_end - p,
"error in processing during lookup of %s: %s",
244 snprintf(p, p_end - p,
"%s is neither permitted nor denied by %s",
248 snprintf(p, p_end - p,
"%s does not provide an SPF record",
253 snprintf(p, p_end - p,
"encountered temporary error during SPF processing of %s",
259 snprintf( p, p_end - p,
"error: unknown SPF result %d encountered while checking %s for %s",
260 spf_response->result, ip, spf_source );
267 spf_response->header_comment =
SPF_sanitize(spf_server, buf);
273SPF_i_set_received_spf(SPF_response_t *spf_response)
275 SPF_server_t *spf_server;
276 SPF_request_t *spf_request;
277 char ip4_buf[ INET_ADDRSTRLEN ];
278 char ip6_buf[ INET6_ADDRSTRLEN ];
288 spf_request = spf_response->spf_request;
290 spf_server = spf_request->spf_server;
293 if (spf_response->received_spf)
294 free(spf_response->received_spf);
295 spf_response->received_spf =
NULL;
297 buf = malloc( buflen );
306 p += snprintf( p, p_end - p,
"Received-SPF: ");
310 p += snprintf( p, p_end - p,
"%s (%s)",
312 spf_response->header_comment );
313 if ( p_end - p <= 0 )
break;
319 if ( spf_request->client_ver == AF_INET ) {
320 ip = inet_ntop( AF_INET, &spf_request->ipv4,
321 ip4_buf,
sizeof( ip4_buf ) );
323 else if (spf_request->client_ver == AF_INET6 ) {
324 ip = inet_ntop( AF_INET6, &spf_request->ipv6,
325 ip6_buf,
sizeof( ip6_buf ) );
329 p += snprintf( p, p_end - p,
" client-ip=%s;", ip );
330 if ( p_end - p <= 0 )
break;
335 if ( spf_request->env_from !=
NULL ) {
336 p += snprintf( p, p_end - p,
" envelope-from=%s;", spf_request->env_from );
337 if ( p_end - p <= 0 )
break;
342 if ( spf_request->helo_dom !=
NULL ) {
343 p += snprintf( p, p_end - p,
" helo=%s;", spf_request->helo_dom );
344 if ( p_end - p <= 0 )
break;
351 if ( output.err_msg !=
NULL ) {
352 p += snprintf( p, p_end - p,
" problem=%s;", output.err_msg );
353 if ( p_end - p <= 0 )
break;
355 else if ( c_results.err_msg !=
NULL ) {
356 p += snprintf( p, p_end - p,
" problem=%s;", c_results.err_msg );
357 if ( p_end - p <= 0 )
break;
366 spf_response->received_spf =
SPF_sanitize(spf_server, buf);
367 spf_response->received_spf_value = buf_value;
374#define DONE(result,reason,err) SPF_i_done(spf_response, result, reason, err)
375#define DONE_TEMPERR(err) DONE(SPF_RESULT_TEMPERROR,SPF_REASON_NONE,err)
376#define DONE_PERMERR(err) DONE(SPF_RESULT_PERMERROR,SPF_REASON_NONE,err)
377#define DONE_MECH(result) DONE(result, SPF_REASON_MECH, SPF_E_SUCCESS)
391 SPF_request_t *spf_request;
392 SPF_server_t *spf_server;
395 spf_request = spf_response->spf_request;
397 spf_server = spf_request->spf_server;
400 spf_response->result = result;
401 spf_response->reason = reason;
402 spf_response->err = err;
404 SPF_i_set_smtp_comment(spf_response);
405 SPF_i_set_header_comment(spf_response);
406 SPF_i_set_received_spf(spf_response);
418#define INET_NTOP(af, src, dst, cnt) do { \
419 if (inet_ntop(af, src, dst, cnt) == NULL) \
420 snprintf(dst, cnt, "ip-error" ); \
424SPF_i_mech_cidr(SPF_request_t *spf_request,
SPF_mech_t *mech)
439 data = SPF_mech_data( mech );
441 if ( data < SPF_mech_end_data( mech )
444 if ( spf_request->client_ver == AF_INET )
446 else if ( spf_request->client_ver == AF_INET6 )
458SPF_i_match_ip4(SPF_server_t *spf_server,
459 SPF_request_t *spf_request,
461 struct in_addr ipv4 )
463 char src_ip4_buf[ INET_ADDRSTRLEN ];
464 char dst_ip4_buf[ INET_ADDRSTRLEN ];
465 char mask_ip4_buf[ INET_ADDRSTRLEN ];
467 struct in_addr src_ipv4;
471 if ( spf_request->client_ver != AF_INET )
474 src_ipv4 = spf_request->ipv4;
476 cidr = SPF_i_mech_cidr( spf_request, mech );
479 mask = 0xffffffff << (32 - cidr);
482 if (spf_server->debug) {
484 src_ip4_buf,
sizeof(src_ip4_buf));
486 dst_ip4_buf,
sizeof(dst_ip4_buf));
488 mask_ip4_buf,
sizeof(mask_ip4_buf));
489 SPF_debugf(
"ip_match: %s == %s (/%d %s): %d",
490 src_ip4_buf, dst_ip4_buf, cidr, mask_ip4_buf,
491 (src_ipv4.s_addr & mask) == (ipv4.s_addr & mask));
494 return (src_ipv4.s_addr & mask) == (ipv4.s_addr & mask);
499SPF_i_match_ip6(SPF_server_t *spf_server,
500 SPF_request_t *spf_request,
502 struct in6_addr ipv6 )
504 char src_ip6_buf[ INET6_ADDRSTRLEN ];
505 char dst_ip6_buf[ INET6_ADDRSTRLEN ];
507 struct in6_addr src_ipv6;
508 int cidr, cidr_save, mask;
512 if ( spf_request->client_ver != AF_INET6 )
515 src_ipv6 = spf_request->ipv6;
517 cidr = SPF_i_mech_cidr(spf_request, mech);
523 for( i = 0; i <
array_elem( ipv6.s6_addr ) && match; i++ )
528 mask = (0xff << (8 - cidr)) & 0xff;
533 match = (src_ipv6.s6_addr[i] & mask) == (ipv6.s6_addr[i] & mask);
536 if (spf_server->debug) {
538 src_ip6_buf,
sizeof(src_ip6_buf));
540 dst_ip6_buf,
sizeof(dst_ip6_buf));
542 src_ip6_buf, dst_ip6_buf, cidr_save, match );
549SPF_i_match_domain(SPF_server_t *spf_server,
550 const char *hostname,
const char *domain)
556 if (spf_server->debug)
559 hlen = strlen(hostname);
560 dlen = strlen(domain);
568 return (strcasecmp(hostname, domain) == 0);
571 hp = hostname + (hlen - dlen);
573 if (*(hp - 1) !=
'.')
576 return (strcasecmp(hp, domain) == 0);
586 SPF_request_t *spf_request, SPF_response_t *spf_response,
589 SPF_server_t *spf_server;
614 SPF_dns_server_t*resolver;
617 SPF_record_t *spf_record_subr;
619 SPF_response_t *save_spf_response;
620 SPF_response_t *spf_response_subr;
621 const char *save_cur_dom;
623 struct in_addr addr4;
624 struct in6_addr addr6;
630 char ip4_buf[ INET_ADDRSTRLEN ];
631 char ip6_buf[ INET6_ADDRSTRLEN ];
640 spf_server = spf_record->spf_server;
648 if ( spf_request->client_ver != AF_INET && spf_request->client_ver != AF_INET6 )
651 if (spf_request->cur_dom ==
NULL)
671 if ( spf_request->use_local_policy ) {
688 if ( spf_server->local_policy ) {
689 mech = spf_record->mech_first;
692 for(m = 0; m < spf_record->num_mech; m++)
707 mech = SPF_mech_next( mech );
721#define SPF_ADD_DNS_MECH() do { spf_response->num_dns_mech++; } while(0)
723#define SPF_MAYBE_SKIP_CIDR() \
725 if ( data < data_end && data->dc.parm_type == PARM_CIDR ) \
726 data = SPF_data_next( data ); \
729#define SPF_GET_LOOKUP_DATA() \
731 if ( data == data_end ) \
732 lookup = spf_request->cur_dom; \
734 err = SPF_record_expand_data( spf_server, \
735 spf_request, spf_response, \
736 data, ((char *)data_end - (char *)data), \
738 if (err == SPF_E_NO_MEMORY) { \
739 SPF_FREE_LOOKUP_DATA(); \
740 return DONE_TEMPERR(err); \
743 SPF_FREE_LOOKUP_DATA(); \
744 return DONE_PERMERR(err); \
749#define SPF_FREE_LOOKUP_DATA() \
750 do { if (buf != NULL) { free(buf); buf = NULL; } } while(0)
753 resolver = spf_server->resolver;
755 mech = spf_record->mech_first;
756 for (m = 0; m < spf_record->num_mech; m++) {
760 if (spf_response->num_dns_mech > spf_server->max_dns_mech) {
765 data = SPF_mech_data(mech);
766 data_end = SPF_mech_end_data(mech);
774 if (spf_request->client_ver == AF_INET)
781 if (spf_server->debug)
782 SPF_debugf(
"found %d A records for %s (herrno: %d)",
791 for (i = 0; i < rr_a->
num_rr; i++) {
793 if (rr_a->
rr_type != fetch_ns_type)
796 if (spf_request->client_ver == AF_INET) {
797 if (SPF_i_match_ip4(spf_server, spf_request, mech, rr_a->
rr[i]->
a)) {
804 if (SPF_i_match_ip6(spf_server, spf_request, mech, rr_a->
rr[i]->
aaaa)) {
822 if (spf_server->debug)
823 SPF_debugf(
"found %d MX records for %s (herrno: %d)",
835 if (max_mx > spf_server->max_dns_mx) {
837 max_mx = SPF_server_get_max_dns_mx(spf_server);
840 for (j = 0; j < max_mx; j++) {
845 if (spf_request->client_ver == AF_INET)
851 fetch_ns_type,
TRUE );
853 if (spf_server->debug)
854 SPF_debugf(
"%d: found %d A records for %s (herrno: %d)",
863 for (i = 0; i < rr_a->
num_rr; i++) {
865 if (rr_a->
rr_type != fetch_ns_type)
868 if (spf_request->client_ver == AF_INET) {
869 if (SPF_i_match_ip4(spf_server, spf_request, mech,
879 if (SPF_i_match_ip6(spf_server, spf_request, mech,
903 if (spf_request->client_ver == AF_INET) {
907 if (spf_server->debug) {
908 INET_NTOP(AF_INET, &spf_request->ipv4.s_addr,
909 ip4_buf,
sizeof(ip4_buf));
910 SPF_debugf(
"got %d PTR records for %s (herrno: %d)",
924 if (max_ptr > spf_server->max_dns_ptr) {
926 max_ptr = SPF_server_get_max_dns_ptr(spf_server);
929 for (i = 0; i < max_ptr; i++) {
935 if (spf_server->debug)
936 SPF_debugf(
"%d: found %d A records for %s (herrno: %d)",
945 for (j = 0; j < rr_a->
num_rr; j++) {
948 if (spf_server->debug) {
950 ip4_buf,
sizeof(ip4_buf));
955 if (rr_a->
rr[j]->
a.s_addr ==
956 spf_request->ipv4.s_addr) {
957 if (SPF_i_match_domain(spf_server,
958 rr_ptr->
rr[i]->
ptr, lookup)) {
976 else if ( spf_request->client_ver == AF_INET6 ) {
980 if ( spf_server->debug ) {
981 INET_NTOP( AF_INET6, &spf_request->ipv6.s6_addr,
982 ip6_buf,
sizeof( ip6_buf ) );
983 SPF_debugf(
"found %d PTR records for %s (herrno: %d)",
995 if (max_ptr > spf_server->max_dns_ptr) {
996 max_ptr = SPF_server_get_max_dns_ptr(spf_server);
1000 for (i = 0; i < max_ptr; i++) {
1006 if ( spf_server->debug )
1007 SPF_debugf(
"%d: found %d AAAA records for %s (herrno: %d)",
1016 for( j = 0; j < rr_aaaa->
num_rr; j++ ) {
1018 if ( spf_server->debug ) {
1020 ip6_buf,
sizeof(ip6_buf));
1025 if (memcmp(&rr_aaaa->
rr[j]->
aaaa,
1027 sizeof(spf_request->ipv6)) == 0) {
1028 if (SPF_i_match_domain(spf_server,
1029 rr_ptr->
rr[i]->
ptr, lookup)) {
1055 spf_request, spf_response,
1056 SPF_mech_data(mech), SPF_mech_data_len(mech),
1069 if (strcmp(lookup, spf_request->cur_dom) == 0) {
1078 spf_record_subr =
NULL;
1080 save_cur_dom = spf_request->cur_dom;
1081 spf_request->cur_dom = lookup;
1083 spf_response, &spf_record_subr);
1085 if ( spf_server->debug > 0 )
1086 SPF_debugf(
"include/redirect: got SPF record: %s",
1090 spf_request->cur_dom = save_cur_dom;
1091 if (spf_record_subr)
1107 save_spf_response =
NULL;
1108 if (spf_response->spf_record_exp == spf_record)
1109 spf_response->spf_record_exp = spf_record_subr;
1113 save_spf_response = spf_response;
1115 if (! spf_response) {
1116 if (spf_record_subr)
1121 spf_response->spf_record_exp = spf_record;
1128 spf_request, spf_response, depth + 1);
1129 spf_request->cur_dom = save_cur_dom;
1137 spf_record_subr =
NULL;
1139 if ( spf_server->debug > 0 )
1140 SPF_debugf(
"include/redirect: executed SPF record: %s result: %s reason: %s",
1150 spf_response_subr = spf_response;
1151 spf_response = save_spf_response;
1152 save_spf_response =
NULL;
1199 memcpy(&addr4, SPF_mech_ip4_data(mech),
sizeof(addr4));
1200 if ( SPF_i_match_ip4( spf_server, spf_request, mech, addr4 ) ) {
1207 memcpy(&addr6, SPF_mech_ip6_data(mech),
sizeof(addr6));
1208 if ( SPF_i_match_ip6( spf_server, spf_request, mech, addr6 ) ) {
1218 spf_request, spf_response,
1219 SPF_mech_data(mech),SPF_mech_data_len(mech),
1229 if ( spf_server->debug )
1230 SPF_debugf(
"found %d A records for %s (herrno: %d)",
1238 if ( rr_a->
num_rr > 0 ) {
1264 if ( mech == local_policy ) {
1266 spf_request, spf_response, depth + 1);
1268 if ( spf_server->debug > 0 )
1269 SPF_debugf(
"local_policy: executed SPF record: %s result: %s reason: %s",
1280 mech = SPF_mech_next( mech );
SPF_errcode_t SPF_server_get_record(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_record_t **spf_recordp)
SPF_dns_rr_t * SPF_dns_rlookup(SPF_dns_server_t *spf_dns_server, struct in_addr ipv4, ns_type rr_type, int should_cache)
SPF_dns_rr_t * SPF_dns_rlookup6(SPF_dns_server_t *spf_dns_server, struct in6_addr ipv6, ns_type rr_type, int should_cache)
SPF_dns_rr_t * SPF_dns_lookup(SPF_dns_server_t *spf_dns_server, const char *domain, ns_type rr_type, int should_cache)
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
SPF_response_t * SPF_response_new(SPF_request_t *spf_request)
void SPF_response_free(SPF_response_t *rp)
@ SPF_REASON_LOCAL_POLICY
@ SPF_E_INCLUDE_RETURNED_NONE
SPF_result_t SPF_response_result(SPF_response_t *rp)
SPF_errcode_t SPF_record_expand_data(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_data_t *data, size_t data_len, char **bufp, size_t *buflenp)
void SPF_record_free(SPF_record_t *rp)
const char * SPF_strerror(SPF_errcode_t spf_err)
#define SPF_RECEIVED_SPF_SIZE
#define SPF_SMTP_COMMENT_SIZE
const char * SPF_strresult(SPF_result_t result)
const char * SPF_strreason(SPF_reason_t reason)
void SPF_dns_rr_free(SPF_dns_rr_t *spfrr)
#define SPF_ASSERT_NOTNULL(x)
#define SPF_error(errmsg)
char * SPF_sanitize(SPF_server_t *spf_server, char *str)
SPF_errcode_t SPF_request_get_exp(SPF_server_t *spf_server, SPF_request_t *spf_request, SPF_response_t *spf_response, SPF_record_t *spf_record, char **bufp, size_t *buflenp)
const char * SPF_request_get_rec_dom(SPF_request_t *sr)
int SPF_request_is_loopback(SPF_request_t *sr)
#define DONE_TEMPERR(err)
#define SPF_FREE_LOOKUP_DATA()
SPF_errcode_t SPF_i_done(SPF_response_t *spf_response, SPF_result_t result, SPF_reason_t reason, SPF_errcode_t err)
#define INET_NTOP(af, src, dst, cnt)
SPF_errcode_t SPF_record_interpret(SPF_record_t *spf_record, SPF_request_t *spf_request, SPF_response_t *spf_response, int depth)
#define SPF_ADD_DNS_MECH()
#define DONE_MECH(result)
#define SPF_MAYBE_SKIP_CIDR()
#define DONE(result, reason, err)
#define SPF_GET_LOOKUP_DATA()
#define DONE_PERMERR(err)
unsigned char prefix_type