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;
197 static config_t spfd_config;
198 static state_t spfd_state;
201 response_print_errors(
const char *context,
204 SPF_error_t *spf_error;
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,
250 request_check(request_t *req)
252 const char *msg =
NULL;
254 msg =
"No IP address given";
255 else if (!req->sender)
256 msg =
"No sender address given";
259 snprintf(req->fmt, 4095,
267 request_query(request_t *req)
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");
313 if (spfd_config.sec_mx) {
314 if (req->rcpt_to && *req->rcpt_to) {
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;
341 if (spfd_config.fallback) {
343 &spf_response, spfd_config.fallback)) {
344 FAIL(
"Querying fallback record");
357 (void)response_print;
359 req->spf_response = spf_response;
360 req->spf_request = spf_request;
364 static inline const char *
373 request_format(request_t *req)
375 SPF_response_t *spf_response;
377 spf_response = req->spf_response;
380 req->fmtlen = snprintf(req->fmt, 4095,
386 "header_comment=%s\n"
388 , req->ip, req->sender
397 req->fmtlen = snprintf(req->fmt, 4095,
402 , req->ip, req->sender
407 req->fmt[4095] =
'\0';
411 request_handle(request_t *req)
413 printf(
"| %s\n", req->sender); fflush(stdout);
414 if (!request_check(req)) {
421 static const struct option longopts[] = {
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));
517 spfd_config.tcpport = atol(
optarg);
520 spfd_config.udpport = atol(
optarg);
523 spfd_config.path =
optarg;
527 spfd_config.debug = atol(
optarg);
532 spfd_config.pathuser = daemon_get_user(
optarg);
537 spfd_config.pathgroup = daemon_get_group(
optarg);
542 spfd_config.pathmode = atol(
optarg);
547 spfd_config.setuser = daemon_get_user(
optarg);
552 spfd_config.setgroup = daemon_get_group(
optarg);
556 spfd_config.onerequest = 1;
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));
681 if (spfd_config.rec_dom) {
683 spfd_config.rec_dom)) {
684 DIE(
"Failed to set receiving domain name");
688 if (spfd_config.sanitize) {
690 spfd_config.sanitize)) {
691 DIE(
"Failed to set server sanitize flag");
695 if (spfd_config.max_lookup) {
696 UNLESS(SPF_server_set_max_dns_mech(spf_server,
697 spfd_config.max_lookup)){
698 DIE(
"Failed to set maximum DNS requests");
702 if (spfd_config.localpolicy) {
704 spfd_config.localpolicy,
705 spfd_config.use_trusted,
707 response_print_errors(
"Compiling local policy",
709 DIE(
"Failed to set local policy");
714 if (spfd_config.explanation) {
716 spfd_config.explanation,
718 response_print_errors(
"Setting default explanation",
720 DIE(
"Failed to set default explanation");
725 if (spfd_config.udpport)
726 spfd_state.sock_udp = daemon_bind_inet_udp();
727 if (spfd_config.tcpport)
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"))
748 return &req->rcpt_to;
749 fprintf(stderr,
"Invalid key %s\n", key);
755 handle_datagram(
void *arg)
764 req = (request_t *)arg;
769 while (key < (req->data + req->datalen)) {
770 end = key + strcspn(key,
"\r\n");
772 value = strchr(key,
'=');
779 fp = find_field(req, key);
786 while (key < (req->data + req->datalen)) {
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),
799 req->addr.in.sin_port);
802 printf(
"- %s\n", req->sender); fflush(stdout);
803 err = sendto(req->sock, req->fmt, req->fmtlen, 0,
804 (
struct sockaddr *)(&req->addr.in), req->addrlen);
818 handle_stream(
void *arg)
827 req = (request_t *)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);
856 send(req->sock, req->fmt, req->fmtlen, 0);
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);
890 if (spfd_state.sock_udp) {
892 FD_SET(spfd_state.sock_udp, &rfd);
893 if (spfd_state.sock_udp > maxfd)
894 maxfd = spfd_state.sock_udp;
896 if (spfd_state.sock_tcp) {
898 FD_SET(spfd_state.sock_tcp, &rfd);
899 if (spfd_state.sock_tcp > maxfd)
900 maxfd = spfd_state.sock_tcp;
902 if (spfd_state.sock_unix) {
904 FD_SET(spfd_state.sock_unix, &rfd);
905 if (spfd_state.sock_unix > maxfd)
906 maxfd = spfd_state.sock_unix;
910 #define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
913 memcpy(&sfd, &rfd,
sizeof(rfd));
917 if (spfd_state.sock_udp) {
918 if (FD_ISSET(spfd_state.sock_udp, &sfd)) {
920 req->addrlen =
sizeof(req->addr);
922 req->sock = spfd_state.sock_udp;
923 req->datalen = recvfrom(spfd_state.sock_udp, buf,4095,0,
924 (
struct sockaddr *)(&req->addr.in), &req->addrlen);
925 if (req->datalen >= 0) {
926 buf[req->datalen] =
'\0';
927 req->data = strdup(buf);
928 pthread_create(&th, &attr, handle_datagram, req);
935 if (spfd_state.sock_tcp) {
936 if (FD_ISSET(spfd_state.sock_tcp, &sfd)) {
938 req->addrlen =
sizeof(req->addr);
940 req->sock = accept(spfd_state.sock_tcp,
941 (
struct sockaddr *)(&req->addr.in), &req->addrlen);
943 pthread_create(&th, &attr, handle_stream, req);
948 if (spfd_state.sock_unix) {
949 if (FD_ISSET(spfd_state.sock_unix, &sfd)) {
951 req->addrlen =
sizeof(req->addr);
953 req->sock = accept(spfd_state.sock_unix,
954 (
struct sockaddr *)(&req->addr.un), &req->addrlen);
956 pthread_create(&th, &attr, handle_stream, req);
963 pthread_attr_destroy(&attr);
969 daemon_config(argc, argv);