47 #define SPF_TEST_VERSION "3.0" 58 #ifdef HAVE_SYS_TYPES_H 59 #include <sys/types.h> 62 #ifdef HAVE_INTTYPES_H 69 # ifdef HAVE_STRINGS_H 74 #ifdef HAVE_SYS_SOCKET_H 75 # include <sys/socket.h> 77 #ifdef HAVE_NETINET_IN_H 78 # include <netinet/in.h> 81 #ifdef HAVE_ARPA_NAMESER_H 82 # include <arpa/nameser.h> 85 #ifdef HAVE_ARPA_INET_H 86 # include <arpa/inet.h> 112 #define FREE(x, f) do { if ((x)) (f)((x)); (x) = NULL; } while(0) 113 #define FREE_REQUEST(x) FREE((x), SPF_request_free) 114 #define FREE_RESPONSE(x) FREE((x), SPF_response_free) 116 #define CONTINUE_ERROR do { res = 255; continue; } while(0) 117 #define WARN_ERROR do { res = 255; } while(0) 118 #define FAIL_ERROR do { res = 255; goto error; } while(0) 120 #define RESIZE_RESULT(n) do { \ 121 if (result == NULL) { \ 122 result_len = 256 + n; \ 123 result = malloc(result_len); \ 126 else if (strlen(result) + n >= result_len) { \ 127 result_len = result_len + (result_len >> 1) + 8 + n; \ 128 result = realloc(result, result_len); \ 131 #define APPEND_RESULT(n) do { \ 132 partial_result = SPF_strresult(n); \ 133 RESIZE_RESULT(strlen(partial_result)); \ 134 strcat(result, partial_result); \ 137 #define X_OR_EMPTY(x) ((x) ? (x) : "") 139 static struct option long_options[] = {
143 {
"sender", 1, 0,
's'},
145 {
"rcpt-to", 1, 0,
'r'},
147 {
"debug", 2, 0,
'd'},
148 {
"local", 1, 0,
'l'},
149 {
"trusted", 1, 0,
't'},
150 {
"guess", 1, 0,
'g'},
151 {
"default-explanation", 1, 0,
'e'},
152 {
"max-lookup", 1, 0,
'm'},
153 {
"sanitize", 1, 0,
'c'},
155 {
"override", 1, 0,
'a'},
156 {
"fallback", 1, 0,
'z'},
158 {
"keep-comments", 0, 0,
'k'},
159 {
"version", 0, 0,
'v'},
166 unimplemented(
const char flag)
171 for (i = 0; (opt = &long_options[i])->name; i++) {
172 if (flag == opt->val) {
173 fprintf(stderr,
"Unimplemented option: -%s or -%c\n",
179 fprintf(stderr,
"Unimplemented option: -%c\n", flag);
190 "spfquery [control options | data options] ...\n" 192 "Use the -help option for more information\n" 203 "spfquery [control options | data options] ...\n" 205 "Valid data options are:\n" 206 " -file <filename> read spf data from a file. Use '-'\n" 207 " to read from stdin.\n" 209 " -ip <IP address> The IP address that is sending email\n" 210 " -sender <email address> The email address used as the\n" 211 " envelope-from. If no username (local\n" 212 " part) is given, 'postmaster' will be\n" 214 " -helo <domain name> The domain name given on the SMTP HELO\n" 215 " command. This is only needed if the\n" 216 " -sender option is not given.\n" 217 " -rcpt-to <email addresses> A comma separated lists of email addresses\n" 218 " that will have email from their secondary\n" 219 " MXes automatically allowed.\n" 221 "The data options are required. The -file option conflicts with all\n" 222 "the other data options. The -helo and -rcpt-to are optional.\n" 225 "Valid control options are:\n" 226 " -debug [debug level] debug level.\n" 227 " -local <SPF mechanisms> Local policy for whitelisting.\n" 228 " -trusted <0|1> Should trusted-forwarder.org be checked?\n" 229 " -guess <SPF mechanisms> Default checks if no SPF record is found.\n" 230 " -default-explanation <str> Default explanation string to use.\n" 231 " -max-lookup <number> Maximum number of DNS lookups to allow\n" 232 " -sanitize <0|1> Clean up invalid characters in output?\n" 233 " -name <domain name> The name of the system doing the SPF\n" 235 " -override <...> Override SPF records for domains\n" 236 " -fallback <...> Fallback SPF records for domains\n" 238 " -keep-comments Print comments found when reading\n" 240 " -version Print version of spfquery.\n" 241 " -help Print out these options.\n" 245 "spfquery -ip=11.22.33.44 -sender=user@aol.com -helo=spammer.tld\n" 246 "spfquery -f test_data\n" 247 "echo \"127.0.0.1 myname@mydomain.com helohost.com\" | spfquery -f -\n" 253 response_print_errors(
const char *context,
259 printf(
"StartError\n");
262 printf(
"Context: %s\n", context);
266 if (spf_response !=
NULL) {
269 printf(
"%s: %s%s\n",
280 printf(
"libspf2 gave a NULL spf_response\n");
282 printf(
"EndError\n");
286 response_print(
const char *context, SPF_response_t *spf_response)
289 printf(
"Context: %s\n", context);
290 if (spf_response ==
NULL) {
291 printf(
"NULL RESPONSE!\n");
294 printf(
"Response result: %s\n",
296 printf(
"Response reason: %s\n",
298 printf(
"Response err: %s\n",
300 response_print_errors(
NULL, spf_response,
307 struct SPF_client_options_struct {
320 struct SPF_client_request_struct {
327 int main(
int argc,
char *argv[] )
332 SPF_server_t *spf_server =
NULL;
333 SPF_request_t *spf_request =
NULL;
334 SPF_response_t *spf_response =
NULL;
335 SPF_response_t *spf_response_2mx =
NULL;
336 SPF_response_t *spf_response_fallback =
NULL;
339 char *opt_file =
NULL;
340 int opt_keep_comments = 0;
346 int major, minor, patch;
351 const char *partial_result;
364 if (SPF_win32_startup() == 0) {
365 fprintf( stderr,
"Could not startup WinSock, wrong version." );
377 c = getopt_long_only (argc, argv,
"f:i:s:h:r:lt::gemcnd::kz:a:v",
378 long_options, &option_index);
447 fprintf( stderr,
"spfquery version information:\n" );
448 fprintf( stderr,
"SPF test system version: %s\n",
450 fprintf( stderr,
"Compiled with SPF library version: %d.%d.%d\n",
454 fprintf( stderr,
"Running with SPF library version: %d.%d.%d\n",
455 major, minor, patch );
456 fprintf( stderr,
"\n" );
468 opt_keep_comments = 1;
475 opts->
debug = atoi( optarg );
479 fprintf( stderr,
"Error: getopt returned character code 0%o ??\n", c);
484 if (optind != argc) {
500 SPF_server_set_max_dns_mech(spf_server, opts->
max_lookup);
505 response_print_errors(
"Error setting local policy",
516 response_print_errors(
"Error setting default explanation",
531 if (strcmp(opt_file,
"-" ) == 0)
534 fin = fopen( opt_file,
"r" );
537 fprintf( stderr,
"Could not open: %s\n", opt_file );
555 if ( fgets( in_line,
sizeof( in_line ), fin ) ==
NULL )
558 in_line[strcspn(in_line,
"\r\n")] =
'\0';
561 p += strspn( p,
" \t\n" );
563 if ( *p ==
'\0' || *p ==
'#' ) {
564 if ( opt_keep_comments )
565 printf(
"%s\n", in_line );
570 p += strcspn( p,
" \t\n" );
573 p += strspn( p,
" \t\n" );
575 p += strcspn( p,
" \t\n" );
578 p += strspn( p,
" \t\n" );
580 p += strcspn( p,
" \t\n" );
583 p += strspn( p,
" \t\n" );
585 p += strcspn( p,
" \t\n" );
602 printf(
"Invalid IP address.\n" );
608 printf(
"Invalid HELO domain.\n" );
614 printf(
"Invalid envelope from address.\n" );
620 response_print(
"Main query", spf_response);
622 response_print_errors(
"Failed to query MAIL-FROM",
633 p_end = p + strcspn(p,
",;");
643 &spf_response_2mx, p);
645 response_print(
"2mx query", spf_response_2mx);
647 response_print_errors(
"Failed to query RCPT-TO",
667 &spf_response_fallback, opts->
fallback);
669 response_print(
"fallback query", spf_response_fallback);
671 response_print_errors(
"Failed to query best-guess",
672 spf_response_fallback, err);
680 spf_response_fallback);
683 printf(
"%s\n%s\n%s\n%s\n",
int SPF_response_messages(SPF_response_t *rp)
SPF_errcode_t SPF_server_set_sanitize(SPF_server_t *sp, int sanitize)
void SPF_get_lib_version(int *major, int *minor, int *patch)
const char * SPF_strerror(SPF_errcode_t spf_err)
SPF_errcode_t SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
char SPF_error_errorp(SPF_error_t *err)
SPF_request_t * SPF_request_new(SPF_server_t *spf_server)
int main(int argc, char *argv[])
#define SPF_LIB_VERSION_PATCH
SPF_errcode_t SPF_server_set_rec_dom(SPF_server_t *sp, const char *dom)
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
SPF_errcode_t SPF_request_query_mailfrom(SPF_request_t *spf_request, SPF_response_t **spf_responsep)
SPF_errcode_t SPF_server_set_localpolicy(SPF_server_t *sp, const char *policy, int use_default_whitelist, SPF_response_t **spf_responsep)
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
void SPF_server_free(SPF_server_t *sp)
SPF_errcode_t SPF_server_set_explanation(SPF_server_t *sp, const char *exp, SPF_response_t **spf_responsep)
SPF_errcode_t SPF_request_query_fallback(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *record)
int SPF_request_set_env_from(SPF_request_t *sr, const char *from)
SPF_errcode_t SPF_request_query_rcptto(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *rcpt_to)
const char * SPF_error_message(SPF_error_t *err)
SPF_server_t * SPF_server_new(SPF_server_dnstype_t dnstype, int debug)
const char * SPF_response_get_header_comment(SPF_response_t *rp)
const char * SPF_strresult(SPF_result_t result)
SPF_errcode_t SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
#define SPF_LIB_VERSION_MAJOR
const char * SPF_response_get_received_spf(SPF_response_t *rp)
SPF_errcode_t SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
const char * SPF_strreason(SPF_reason_t reason)
SPF_result_t SPF_response_result(SPF_response_t *rp)
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
#define SPF_LIB_VERSION_MINOR
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)