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",
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
SPF_errcode_t SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
void SPF_get_lib_version(int *major, int *minor, int *patch)
SPF_errcode_t SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
SPF_errcode_t SPF_server_set_localpolicy(SPF_server_t *sp, const char *policy, int use_default_whitelist, SPF_response_t **spf_responsep)
#define SPF_LIB_VERSION_MAJOR
SPF_errcode_t SPF_request_query_fallback(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *record)
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
SPF_errcode_t SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
const char * SPF_response_get_header_comment(SPF_response_t *rp)
#define SPF_LIB_VERSION_MINOR
int SPF_request_set_env_from(SPF_request_t *sr, const char *from)
SPF_errcode_t SPF_server_set_sanitize(SPF_server_t *sp, int sanitize)
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
SPF_errcode_t SPF_request_query_rcptto(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *rcpt_to)
const char * SPF_strreason(SPF_reason_t reason)
const char * SPF_strresult(SPF_result_t result)
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)
SPF_result_t SPF_response_result(SPF_response_t *rp)
int SPF_response_messages(SPF_response_t *rp)
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
SPF_errcode_t SPF_request_query_mailfrom(SPF_request_t *spf_request, SPF_response_t **spf_responsep)
SPF_request_t * SPF_request_new(SPF_server_t *spf_server)
#define SPF_LIB_VERSION_PATCH
SPF_errcode_t SPF_server_set_rec_dom(SPF_server_t *sp, const char *dom)
void SPF_server_free(SPF_server_t *sp)
const char * SPF_response_get_received_spf(SPF_response_t *rp)
const char * SPF_strerror(SPF_errcode_t spf_err)
SPF_errcode_t SPF_server_set_explanation(SPF_server_t *sp, const char *exp, SPF_response_t **spf_responsep)
SPF_server_t * SPF_server_new(SPF_server_dnstype_t dnstype, int debug)
const char * SPF_error_message(SPF_error_t *err)
char SPF_error_errorp(SPF_error_t *err)
int main(int argc, char *argv[])