51 #ifdef HAVE_SYS_TYPES_H
52 #include <sys/types.h>
55 #ifdef HAVE_INTTYPES_H
62 # ifdef HAVE_STRINGS_H
67 #ifdef HAVE_SYS_SOCKET_H
68 # include <sys/socket.h>
70 #ifdef HAVE_NETINET_IN_H
71 # include <netinet/in.h>
73 #ifdef HAVE_ARPA_INET_H
74 # include <arpa/inet.h>
77 #ifdef HAVE_ARPA_NAMESER_H
78 # include <arpa/nameser.h>
81 #include <sys/types.h>
91 #ifdef HAVE_GETOPT_LONG_ONLY
105 #include <sys/types.h>
106 #include <sys/stat.h>
107 #include <sys/socket.h>
109 #include <netinet/in.h>
111 #include <sys/wait.h>
128 #define FREE(x, f) do { if ((x)) (f)((x)); (x) = NULL; } while(0)
129 #define FREE_REQUEST(x) FREE((x), SPF_request_free)
130 #define FREE_RESPONSE(x) FREE((x), SPF_response_free)
131 #define FREE_STRING(x) FREE((x), free)
169 struct sockaddr_in in;
170 struct sockaddr_un un;
196 static SPF_server_t *spf_server;
201 response_print_errors(
const char *context,
208 printf(
"Context: %s\n", context);
212 if (spf_response !=
NULL) {
215 printf(
"%s: %s%s\n",
224 printf(
"Error: libspf2 gave a NULL spf_response");
229 response_print(
const char *context, SPF_response_t *spf_response)
232 printf(
"Context: %s\n", context);
233 if (spf_response ==
NULL) {
234 printf(
"NULL RESPONSE!\n");
237 printf(
"Response result: %s\n",
239 printf(
"Response reason: %s\n",
241 printf(
"Response err: %s\n",
243 response_print_errors(
NULL, spf_response,
252 const char *msg =
NULL;
254 msg =
"No IP address given";
256 msg =
"No sender address given";
259 snprintf(req->
fmt, 4095,
269 SPF_request_t *spf_request =
NULL;
270 SPF_response_t *spf_response =
NULL;
271 SPF_response_t *spf_response_2mx =
NULL;
275 #define UNLESS(x) err = (x); if (err)
277 #define FAIL(x) do { goto fail; } while(0)
278 #define WARN(x, r) response_print_errors((x), (r), err)
282 if (strchr(req->
ip,
':')) {
284 FAIL(
"Setting IPv6 address");
289 FAIL(
"Setting IPv4 address");
295 FAIL(
"Failed to set HELO domain");
302 FAIL(
"Failed to set envelope-from address");
310 FAIL(
"Failed to query based on mail-from address");
316 p_end = p + strcspn(p,
" ,;");
323 &spf_response_2mx, p)) {
324 WARN(
"Failed to query based on 2mx recipient",
331 spf_response_2mx =
NULL;
343 &spf_response, spfd_config.
fallback)) {
344 FAIL(
"Querying fallback record");
357 (void)response_print;
364 static inline const char *
375 SPF_response_t *spf_response;
386 "header_comment=%s\n"
407 req->
fmt[4095] =
'\0';
413 printf(
"| %s\n", req->
sender); fflush(stdout);
414 if (!request_check(req)) {
443 static const char *shortopts =
"d:t:p:f:x:y:m:u:g:h:";
446 fprintf(stdout,
"Flags\n");
447 fprintf(stdout,
"\t-tcpport\n");
448 fprintf(stdout,
"\t-udpport\n");
449 fprintf(stdout,
"\t-path\n");
451 fprintf(stdout,
"\t-pathuser\n");
454 fprintf(stdout,
"\t-pathgroup\n");
456 fprintf(stdout,
"\t-pathmode\n");
458 fprintf(stdout,
"\t-setuser\n");
461 fprintf(stdout,
"\t-setgroup\n");
463 fprintf(stdout,
"\t-onerequest\n");
464 fprintf(stdout,
"\t-help\n");
468 #define DIE(x) do { fprintf(stderr, "%s\n", x); exit(1); } while(0)
472 daemon_get_user(
const char *arg)
476 pwd = getpwuid(atol(arg));
480 fprintf(stderr,
"Failed to find user %s\n", arg);
489 daemon_get_group(
const char *arg)
493 grp = getgrgid(atol(arg));
497 fprintf(stderr,
"Failed to find user %s\n", arg);
498 DIE(
"Unknown group");
505 daemon_config(
int argc,
char *argv[])
510 memset(&spfd_config, 0,
sizeof(spfd_config));
532 spfd_config.pathuser = daemon_get_user(
optarg);
537 spfd_config.pathgroup = daemon_get_group(
optarg);
547 spfd_config.setuser = daemon_get_user(
optarg);
552 spfd_config.setgroup = daemon_get_group(
optarg);
557 fprintf(stdout,
"One request mode\n");
563 DIE(
"Invalid argument");
571 fprintf(stderr,
"Error: getopt returned character code 0%o ??\n", c);
578 daemon_bind_inet_udp()
580 struct sockaddr_in addr;
583 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
585 DIE(
"Failed to create socket");
587 memset(&addr, 0,
sizeof(addr));
588 addr.sin_family = AF_INET;
589 addr.sin_port = htons(spfd_config.
udpport);
590 addr.sin_addr.s_addr = INADDR_ANY;
591 if (bind(sock, (
struct sockaddr *)(&addr),
sizeof(addr)) < 0) {
593 DIE(
"Failed to bind socket");
596 fprintf(stderr,
"Accepting datagrams on %d\n", spfd_config.
udpport);
602 daemon_bind_inet_tcp()
604 struct sockaddr_in addr;
610 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
612 DIE(
"Failed to create socket");
616 optlen =
sizeof(int);
617 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
619 memset(&addr, 0,
sizeof(addr));
620 addr.sin_family = AF_INET;
621 addr.sin_port = htons(spfd_config.
tcpport);
622 addr.sin_addr.s_addr = INADDR_ANY;
623 if (bind(sock, (
struct sockaddr *)(&addr),
sizeof(addr)) < 0) {
625 DIE(
"Failed to bind socket");
628 if (listen(sock, 5) < 0) {
630 DIE(
"Failed to listen on socket");
633 fprintf(stderr,
"Accepting connections on %d\n", spfd_config.
tcpport);
641 struct sockaddr_un addr;
644 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
646 DIE(
"Failed to create socket");
648 memset(&addr, 0,
sizeof(addr));
649 addr.sun_family = AF_UNIX;
650 strncpy(addr.sun_path, spfd_config.
path,
sizeof(addr.sun_path) - 1);
651 if (unlink(spfd_config.
path) < 0) {
652 if (errno != ENOENT) {
654 DIE(
"Failed to unlink socket");
657 if (bind(sock, (
struct sockaddr *)(&addr),
sizeof(addr)) < 0) {
659 DIE(
"Failed to bind socket");
661 if (listen(sock, 5) < 0) {
663 DIE(
"Failed to listen on socket");
666 fprintf(stderr,
"Accepting connections on %s\n", spfd_config.
path);
674 SPF_response_t *spf_response =
NULL;
677 memset(&spfd_state, 0,
sizeof(spfd_state));
684 DIE(
"Failed to set receiving domain name");
691 DIE(
"Failed to set server sanitize flag");
696 UNLESS(SPF_server_set_max_dns_mech(spf_server,
698 DIE(
"Failed to set maximum DNS requests");
707 response_print_errors(
"Compiling local policy",
709 DIE(
"Failed to set local policy");
718 response_print_errors(
"Setting default explanation",
720 DIE(
"Failed to set default explanation");
726 spfd_state.
sock_udp = daemon_bind_inet_udp();
728 spfd_state.
sock_tcp = daemon_bind_inet_tcp();
729 if (spfd_config.
path)
730 spfd_state.
sock_unix = daemon_bind_unix();
737 find_field(
request_t *req,
const char *key)
739 #define STREQ(a, b) (strcmp((a), (b)) == 0)
741 if (
STREQ(key,
"ip"))
743 if (
STREQ(key,
"helo"))
745 if (
STREQ(key,
"sender"))
747 if (
STREQ(key,
"rcpt"))
749 fprintf(stderr,
"Invalid key %s\n", key);
755 handle_datagram(
void *arg)
770 end = key + strcspn(key,
"\r\n");
772 value = strchr(key,
'=');
779 fp = find_field(req, key);
787 if (strchr(
"\r\n", *key))
797 printf(
"Target address length is %d: %s:%d\n", req->
addrlen,
798 inet_ntoa(req->
addr.
in.sin_addr),
802 printf(
"- %s\n", req->
sender); fflush(stdout);
818 handle_stream(
void *arg)
828 stream = fdopen(req->
sock,
"r");
831 while (fgets(key, BUFSIZ, stream) !=
NULL) {
832 key[strcspn(key,
"\r\n")] =
'\0';
838 end = key + strcspn(key,
"\r\n");
840 value = strchr(key,
'=');
846 fp = find_field(req, key);
855 printf(
"- %s\n", req->
sender); fflush(stdout);
862 }
while (! (spfd_config.
onerequest || feof(stream)));
864 shutdown(req->
sock, SHUT_RDWR);
884 pthread_attr_init(&attr);
885 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
910 #define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
913 memcpy(&sfd, &rfd,
sizeof(rfd));
918 if (FD_ISSET(spfd_state.
sock_udp, &sfd)) {
927 req->
data = strdup(buf);
928 pthread_create(&th, &attr, handle_datagram, req);
936 if (FD_ISSET(spfd_state.
sock_tcp, &sfd)) {
943 pthread_create(&th, &attr, handle_stream, req);
949 if (FD_ISSET(spfd_state.
sock_unix, &sfd)) {
956 pthread_create(&th, &attr, handle_stream, req);
963 pthread_attr_destroy(&attr);
969 daemon_config(argc, argv);
SPF_response_t * spf_response
SPF_errcode_t SPF_server_set_sanitize(SPF_server_t *sp, int sanitize)
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
SPF_errcode_t SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
SPF_errcode_t SPF_server_set_rec_dom(SPF_server_t *sp, const char *dom)
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
char SPF_error_errorp(SPF_error_t *err)
SPF_errcode_t SPF_request_query_fallback(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *record)
SPF_errcode_t SPF_server_set_localpolicy(SPF_server_t *sp, const char *policy, int use_default_whitelist, SPF_response_t **spf_responsep)
#define required_argument
SPF_errcode_t SPF_request_query_rcptto(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *rcpt_to)
const char * SPF_strresult(SPF_result_t result)
int main(int argc, char *argv[])
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
SPF_errcode_t SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
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_strerror(SPF_errcode_t spf_err)
SPF_errcode_t SPF_request_query_mailfrom(SPF_request_t *spf_request, SPF_response_t **spf_responsep)
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)
SPF_errcode_t SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
const char * SPF_strreason(SPF_reason_t reason)
const char * SPF_error_message(SPF_error_t *err)
SPF_request_t * SPF_request_new(SPF_server_t *spf_server)
int SPF_response_messages(SPF_response_t *rp)
SPF_request_t * spf_request
const char * SPF_response_get_header_comment(SPF_response_t *rp)
int SPF_request_set_env_from(SPF_request_t *sr, const char *from)
SPF_result_t SPF_response_result(SPF_response_t *rp)