int response_printf(response_t* response, const char* format, ...) { char buffer[1024]; va_list ap; int len = sizeof(buffer); // FIXME: should use veriable size buffer... va_start(ap, format); vsnprintf(buffer, len, format, ap); buffer[len-1] = 0; va_end(ap); return response_print(response, buffer); }
int main( int argc, char *argv[] ) { SPF_client_options_t *opts; SPF_client_request_t *req = NULL; SPF_server_t *spf_server = NULL; SPF_request_t *spf_request = NULL; SPF_response_t *spf_response = NULL; SPF_response_t *spf_response_2mx = NULL; SPF_errcode_t err; int opt_keep_comments = 0; #ifdef TO_MX char *p, *p_end; #endif int request_limit=0; int major, minor, patch; int res = 0; int c; const char *partial_result; char *result = NULL; int result_len = 0; char hostname[255]; char pf_result[100]; struct hostent *fullhostname; /* Figure out our name */ progname = strrchr(argv[0], '/'); if (progname != NULL) ++progname; else progname = argv[0]; /*open syslog*/ openlog(progname, LOG_PID|LOG_CONS|LOG_NDELAY|LOG_NOWAIT, LOG_MAIL); /* Redefine libSPF2 output routines to go to syslog */ SPF_error_handler = SPF_error_syslog; SPF_warning_handler = SPF_warning_syslog; SPF_info_handler = SPF_info_syslog; SPF_debug_handler = SPF_debug_syslog; opts = (SPF_client_options_t *)malloc(sizeof(SPF_client_options_t)); memset(opts, 0, sizeof(SPF_client_options_t)); /* * check the arguments */ for (;;) { int option_index; /* Largely unused */ c = getopt_long_only (argc, argv, "f:i:s:h:r:lt::gemcnd::kz:a:v", long_options, &option_index); if (c == -1) break; switch (c) { case 'l': opts->localpolicy = optarg; break; case 't': if (optarg == NULL) opts->use_trusted = 1; else opts->use_trusted = atoi(optarg); break; case 'g': opts->fallback = optarg; break; case 'e': opts->explanation = optarg; break; case 'm': opts->max_lookup = atoi(optarg); break; case 'c': /* "clean" */ opts->sanitize = atoi(optarg); break; case 'n': /* name of host doing SPF checking */ opts->rec_dom = optarg; break; case 'a': unimplemented('a'); break; case 'z': unimplemented('z'); break; case 'v': fprintf( stderr, "policyd-spf-fs version information:\n" ); fprintf( stderr, "policyd-spf-fs version: $Rev: 27 $\n"); fprintf( stderr, "SPF test system version: %s\n", SPF_TEST_VERSION ); fprintf( stderr, "Compiled with SPF library version: %d.%d.%d\n", SPF_LIB_VERSION_MAJOR, SPF_LIB_VERSION_MINOR, SPF_LIB_VERSION_PATCH ); SPF_get_lib_version( &major, &minor, &patch ); fprintf( stderr, "Running with SPF library version: %d.%d.%d\n", major, minor, patch ); fprintf( stderr, "\n" ); FAIL_ERROR; break; case 0: case '?': help(); FAIL_ERROR; break; case 'k': opt_keep_comments = 1; break; case 'd': if (optarg == NULL) opts->debug = 1; else opts->debug = atoi( optarg ); break; default: fprintf( stderr, "Error: getopt returned character code 0%o ??\n", c); FAIL_ERROR; } } if (optind != argc) { help(); FAIL_ERROR; } if (!opts->rec_dom) { gethostname(hostname, 255); fullhostname = gethostbyname(hostname); if (opts->debug > 1) syslog(LOG_DEBUG, "Hostname: %s\n",fullhostname->h_name); opts->rec_dom = fullhostname->h_name; } /* * set up the SPF configuration */ spf_server = SPF_server_new(SPF_DNS_CACHE, opts->debug > 2 ? opts->debug-2 : 0); if ( opts->rec_dom ) SPF_server_set_rec_dom( spf_server, opts->rec_dom ); if ( opts->sanitize ) SPF_server_set_sanitize( spf_server, opts->sanitize ); if ( opts->max_lookup ) SPF_server_set_max_dns_mech(spf_server, opts->max_lookup); if (opts->localpolicy) { err = SPF_server_set_localpolicy( spf_server, opts->localpolicy, opts->use_trusted, &spf_response); if ( err ) { response_print_errors("Error setting local policy", spf_response, err); WARN_ERROR; } FREE_RESPONSE(spf_response); } if ( !opts->explanation ) { opts->explanation = DEFAULT_EXPLANATION; } err = SPF_server_set_explanation( spf_server, opts->explanation, &spf_response ); if ( err ) { response_print_errors("Error setting default explanation", spf_response, err); WARN_ERROR; } FREE_RESPONSE(spf_response); /* * process the SPF request */ request_limit=0; while ( request_limit < REQUEST_LIMIT ) { request_limit++; if (request_limit == 0) { free(req); } req = (SPF_client_request_t *)malloc(sizeof(SPF_client_request_t)); memset(req, 0, sizeof(SPF_client_request_t)); if (read_request_from_pf(opts, req)) { syslog(LOG_WARNING, "IO Closed while reading, exiting"); EXIT_OK; } if (opts->debug > 1) syslog(LOG_DEBUG, "Reincarnation %d\n", request_limit); /* We have to do this here else we leak on CONTINUE_ERROR */ FREE_REQUEST(spf_request); FREE_RESPONSE(spf_response); spf_request = SPF_request_new(spf_server); if (SPF_request_set_ipv4_str(spf_request, req->ip) && SPF_request_set_ipv6_str(spf_request, req->ip)) { syslog(LOG_WARNING, "Invalid IP address.\n" ); CONTINUE_ERROR; } if (req->helo) { if (SPF_request_set_helo_dom( spf_request, req->helo ) ) { syslog(LOG_WARNING, "Invalid HELO domain.\n" ); CONTINUE_ERROR; } } if (strchr(req->sender, '@') > 0) { if (SPF_request_set_env_from( spf_request, req->sender ) ) { syslog(LOG_WARNING, "Invalid envelope from address.\n" ); CONTINUE_ERROR; } } else { /* This is something we can not check*/ CONTINUE_DUNNO("no valid email address found"); } err = SPF_request_query_mailfrom(spf_request, &spf_response); if (opts->debug > 1) response_print("Main query", spf_response); if (err) { if (opts->debug > 1) response_print_errors("Failed to query MAIL-FROM", spf_response, err); CONTINUE_DUNNO("no SPF record found"); } if (result != NULL) result[0] = '\0'; APPEND_RESULT(SPF_response_result(spf_response)); #ifdef TO_MX /* This code returns usualy neutral and oferwrites a fail from the above spf code which is not what we like. So we disable it for the time deing ... */ if (req->rcpt_to != NULL && *req->rcpt_to != '\0' ) { p = req->rcpt_to; p_end = p + strcspn(p, ",;"); /* This is some incarnation of 2mx mode. */ while (SPF_response_result(spf_response)!=SPF_RESULT_PASS) { if (*p_end) *p_end = '\0'; else p_end = NULL; /* Note this is last rcpt */ err = SPF_request_query_rcptto(spf_request, &spf_response_2mx, p); if (opts->debug > 1) response_print("2mx query", spf_response_2mx); if (err) { response_print_errors("Failed to query RCPT-TO", spf_response, err); CONTINUE_ERROR; } /* append the result */ APPEND_RESULT(SPF_response_result(spf_response_2mx)); spf_response = SPF_response_combine(spf_response, spf_response_2mx); if (!p_end) break; p = p_end + 1; } } #endif /* TO_MX */ /* We now have an option to call SPF_request_query_fallback */ if (opts->fallback) { err = SPF_request_query_fallback(spf_request, &spf_response, opts->fallback); if (opts->debug > 1) response_print("fallback query", spf_response_2mx); if (err) { response_print_errors("Failed to query best-guess", spf_response, err); CONTINUE_ERROR; } /* append the result */ APPEND_RESULT(SPF_response_result(spf_response_2mx)); spf_response = SPF_response_combine(spf_response, spf_response_2mx); } /* printf( "R: %s\nSC: %s\nHC: %s\nRS: %s\n", result, X_OR_EMPTY(SPF_response_get_smtp_comment(spf_response)), X_OR_EMPTY(SPF_response_get_header_comment(spf_response)), X_OR_EMPTY(SPF_response_get_received_spf(spf_response)) ); */ pf_response(opts, spf_response, req); res = SPF_response_result(spf_response); fflush(stdout); } error: FREE(result, free); FREE_RESPONSE(spf_response); FREE_REQUEST(spf_request); FREE(spf_server, SPF_server_free); syslog(LOG_INFO, "Terminating with result %d, Reincarnation: %d\n", res, request_limit); return res; }