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[] = {
444 static const char *shortopts =
"d:t:p:f:x:y:m:u:g:o:h:";
447 fprintf(stdout,
"Flags\n");
448 fprintf(stdout,
"\t-tcpport\n");
449 fprintf(stdout,
"\t-udpport\n");
450 fprintf(stdout,
"\t-path\n");
452 fprintf(stdout,
"\t-pathuser\n");
455 fprintf(stdout,
"\t-pathgroup\n");
457 fprintf(stdout,
"\t-pathmode\n");
459 fprintf(stdout,
"\t-setuser\n");
462 fprintf(stdout,
"\t-setgroup\n");
464 fprintf(stdout,
"\t-onerequest\n");
465 fprintf(stdout,
"\t-help\n");
469 #define DIE(x) do { fprintf(stderr, "%s\n", x); exit(1); } while(0)
473 daemon_get_user(
const char *arg)
477 pwd = getpwuid(atol(arg));
481 fprintf(stderr,
"Failed to find user %s\n", arg);
490 daemon_get_group(
const char *arg)
494 grp = getgrgid(atol(arg));
498 fprintf(stderr,
"Failed to find user %s\n", arg);
499 DIE(
"Unknown group");
506 daemon_config(
int argc,
char *argv[])
511 memset(&spfd_config, 0,
sizeof(spfd_config));
518 spfd_config.tcpport = atol(
optarg);
521 spfd_config.udpport = atol(
optarg);
524 spfd_config.path =
optarg;
528 spfd_config.debug = atol(
optarg);
533 spfd_config.pathuser = daemon_get_user(
optarg);
538 spfd_config.pathgroup = daemon_get_group(
optarg);
543 spfd_config.pathmode = atol(
optarg);
548 spfd_config.setuser = daemon_get_user(
optarg);
553 spfd_config.setgroup = daemon_get_group(
optarg);
557 spfd_config.onerequest = 1;
558 fprintf(stdout,
"One request mode\n");
564 DIE(
"Invalid argument");
572 fprintf(stderr,
"Error: getopt returned character code 0%o ??\n", c);
579 daemon_bind_inet_udp()
581 struct sockaddr_in addr;
584 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
586 DIE(
"Failed to create socket");
588 memset(&addr, 0,
sizeof(addr));
589 addr.sin_family = AF_INET;
590 addr.sin_port = htons(spfd_config.udpport);
591 addr.sin_addr.s_addr = INADDR_ANY;
592 if (bind(sock, (
struct sockaddr *)(&addr),
sizeof(addr)) < 0) {
594 DIE(
"Failed to bind socket");
597 fprintf(stderr,
"Accepting datagrams on %d\n", spfd_config.udpport);
603 daemon_bind_inet_tcp()
605 struct sockaddr_in addr;
611 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
613 DIE(
"Failed to create socket");
617 optlen =
sizeof(int);
618 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
620 memset(&addr, 0,
sizeof(addr));
621 addr.sin_family = AF_INET;
622 addr.sin_port = htons(spfd_config.tcpport);
623 addr.sin_addr.s_addr = INADDR_ANY;
624 if (bind(sock, (
struct sockaddr *)(&addr),
sizeof(addr)) < 0) {
626 DIE(
"Failed to bind socket");
629 if (listen(sock, 5) < 0) {
631 DIE(
"Failed to listen on socket");
634 fprintf(stderr,
"Accepting connections on %d\n", spfd_config.tcpport);
642 struct sockaddr_un addr;
645 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
647 DIE(
"Failed to create socket");
649 memset(&addr, 0,
sizeof(addr));
650 addr.sun_family = AF_UNIX;
651 strncpy(addr.sun_path, spfd_config.path,
sizeof(addr.sun_path) - 1);
652 if (unlink(spfd_config.path) < 0) {
653 if (errno != ENOENT) {
655 DIE(
"Failed to unlink socket");
658 if (bind(sock, (
struct sockaddr *)(&addr),
sizeof(addr)) < 0) {
660 DIE(
"Failed to bind socket");
662 if (listen(sock, 5) < 0) {
664 DIE(
"Failed to listen on socket");
667 fprintf(stderr,
"Accepting connections on %s\n", spfd_config.path);
675 SPF_response_t *spf_response =
NULL;
678 memset(&spfd_state, 0,
sizeof(spfd_state));
682 if (spfd_config.rec_dom) {
684 spfd_config.rec_dom)) {
685 DIE(
"Failed to set receiving domain name");
689 if (spfd_config.sanitize) {
691 spfd_config.sanitize)) {
692 DIE(
"Failed to set server sanitize flag");
696 if (spfd_config.max_lookup) {
697 UNLESS(SPF_server_set_max_dns_mech(spf_server,
698 spfd_config.max_lookup)){
699 DIE(
"Failed to set maximum DNS requests");
703 if (spfd_config.localpolicy) {
705 spfd_config.localpolicy,
706 spfd_config.use_trusted,
708 response_print_errors(
"Compiling local policy",
710 DIE(
"Failed to set local policy");
715 if (spfd_config.explanation) {
717 spfd_config.explanation,
719 response_print_errors(
"Setting default explanation",
721 DIE(
"Failed to set default explanation");
726 if (spfd_config.udpport)
727 spfd_state.sock_udp = daemon_bind_inet_udp();
728 if (spfd_config.tcpport)
729 spfd_state.sock_tcp = daemon_bind_inet_tcp();
730 if (spfd_config.path)
731 spfd_state.sock_unix = daemon_bind_unix();
738 find_field(request_t *req,
const char *key)
740 #define STREQ(a, b) (strcmp((a), (b)) == 0)
742 if (
STREQ(key,
"ip"))
744 if (
STREQ(key,
"helo"))
746 if (
STREQ(key,
"sender"))
748 if (
STREQ(key,
"rcpt"))
749 return &req->rcpt_to;
750 fprintf(stderr,
"Invalid key %s\n", key);
756 handle_datagram(
void *arg)
765 req = (request_t *)arg;
770 while (key < (req->data + req->datalen)) {
771 end = key + strcspn(key,
"\r\n");
773 value = strchr(key,
'=');
780 fp = find_field(req, key);
787 while (key < (req->data + req->datalen)) {
788 if (strchr(
"\r\n", *key))
798 printf(
"Target address length is %d: %s:%d\n", req->addrlen,
799 inet_ntoa(req->addr.in.sin_addr),
800 req->addr.in.sin_port);
803 printf(
"- %s\n", req->sender); fflush(stdout);
804 err = sendto(req->sock, req->fmt, req->fmtlen, 0,
805 (
struct sockaddr *)(&req->addr.in), req->addrlen);
819 handle_stream(
void *arg)
828 req = (request_t *)arg;
829 stream = fdopen(req->sock,
"r");
832 while (fgets(key, BUFSIZ, stream) !=
NULL) {
833 key[strcspn(key,
"\r\n")] =
'\0';
839 end = key + strcspn(key,
"\r\n");
841 value = strchr(key,
'=');
847 fp = find_field(req, key);
856 printf(
"- %s\n", req->sender); fflush(stdout);
857 send(req->sock, req->fmt, req->fmtlen, 0);
863 }
while (! (spfd_config.onerequest || feof(stream)));
865 shutdown(req->sock, SHUT_RDWR);
885 pthread_attr_init(&attr);
886 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
891 if (spfd_state.sock_udp) {
893 FD_SET(spfd_state.sock_udp, &rfd);
894 if (spfd_state.sock_udp > maxfd)
895 maxfd = spfd_state.sock_udp;
897 if (spfd_state.sock_tcp) {
899 FD_SET(spfd_state.sock_tcp, &rfd);
900 if (spfd_state.sock_tcp > maxfd)
901 maxfd = spfd_state.sock_tcp;
903 if (spfd_state.sock_unix) {
905 FD_SET(spfd_state.sock_unix, &rfd);
906 if (spfd_state.sock_unix > maxfd)
907 maxfd = spfd_state.sock_unix;
911 #define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
914 memcpy(&sfd, &rfd,
sizeof(rfd));
918 if (spfd_state.sock_udp) {
919 if (FD_ISSET(spfd_state.sock_udp, &sfd)) {
921 req->addrlen =
sizeof(req->addr);
923 req->sock = spfd_state.sock_udp;
924 req->datalen = recvfrom(spfd_state.sock_udp, buf,4095,0,
925 (
struct sockaddr *)(&req->addr.in), &req->addrlen);
926 if (req->datalen >= 0) {
927 buf[req->datalen] =
'\0';
928 req->data = strdup(buf);
929 pthread_create(&th, &attr, handle_datagram, req);
936 if (spfd_state.sock_tcp) {
937 if (FD_ISSET(spfd_state.sock_tcp, &sfd)) {
939 req->addrlen =
sizeof(req->addr);
941 req->sock = accept(spfd_state.sock_tcp,
942 (
struct sockaddr *)(&req->addr.in), &req->addrlen);
944 pthread_create(&th, &attr, handle_stream, req);
949 if (spfd_state.sock_unix) {
950 if (FD_ISSET(spfd_state.sock_unix, &sfd)) {
952 req->addrlen =
sizeof(req->addr);
954 req->sock = accept(spfd_state.sock_unix,
955 (
struct sockaddr *)(&req->addr.un), &req->addrlen);
957 pthread_create(&th, &attr, handle_stream, req);
964 pthread_attr_destroy(&attr);
970 daemon_config(argc, argv);