51#ifdef HAVE_SYS_TYPES_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>
91#ifdef HAVE_GETOPT_LONG_ONLY
105#include <sys/types.h>
107#include <sys/socket.h>
109#include <netinet/in.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;
196static SPF_server_t *spf_server;
201response_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");
229response_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;
364static 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)) {
421static const struct option longopts[] = {
444static 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)
473daemon_get_user(
const char *arg)
477 pwd = getpwuid(atol(arg));
481 fprintf(stderr,
"Failed to find user %s\n", arg);
490daemon_get_group(
const char *arg)
494 grp = getgrgid(atol(arg));
498 fprintf(stderr,
"Failed to find user %s\n", arg);
499 DIE(
"Unknown group");
506daemon_config(
int argc,
char *argv[])
511 memset(&spfd_config, 0,
sizeof(spfd_config));
533 spfd_config.pathuser = daemon_get_user(
optarg);
538 spfd_config.pathgroup = daemon_get_group(
optarg);
548 spfd_config.setuser = daemon_get_user(
optarg);
553 spfd_config.setgroup = daemon_get_group(
optarg);
558 fprintf(stdout,
"One request mode\n");
564 DIE(
"Invalid argument");
572 fprintf(stderr,
"Error: getopt returned character code 0%o ??\n", c);
579daemon_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);
603daemon_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));
685 DIE(
"Failed to set receiving domain name");
692 DIE(
"Failed to set server sanitize flag");
697 UNLESS(SPF_server_set_max_dns_mech(spf_server,
699 DIE(
"Failed to set maximum DNS requests");
708 response_print_errors(
"Compiling local policy",
710 DIE(
"Failed to set local policy");
719 response_print_errors(
"Setting default explanation",
721 DIE(
"Failed to set default explanation");
727 spfd_state.
sock_udp = daemon_bind_inet_udp();
729 spfd_state.
sock_tcp = daemon_bind_inet_tcp();
730 if (spfd_config.
path)
731 spfd_state.
sock_unix = daemon_bind_unix();
738find_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"))
750 fprintf(stderr,
"Invalid key %s\n", key);
756handle_datagram(
void *arg)
771 end = key + strcspn(key,
"\r\n");
773 value = strchr(key,
'=');
780 fp = find_field(req, key);
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),
803 printf(
"- %s\n", req->
sender); fflush(stdout);
819handle_stream(
void *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);
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);
911#define NEW_REQUEST ((request_t *)calloc(1, sizeof(request_t)));
914 memcpy(&sfd, &rfd,
sizeof(rfd));
919 if (FD_ISSET(spfd_state.
sock_udp, &sfd)) {
928 req->
data = strdup(buf);
929 pthread_create(&th, &attr, handle_datagram, req);
937 if (FD_ISSET(spfd_state.
sock_tcp, &sfd)) {
944 pthread_create(&th, &attr, handle_stream, req);
950 if (FD_ISSET(spfd_state.
sock_unix, &sfd)) {
957 pthread_create(&th, &attr, handle_stream, req);
964 pthread_attr_destroy(&attr);
970 daemon_config(argc, argv);
#define required_argument
SPF_server_t * SPF_server_new(SPF_server_dnstype_t dnstype, int debug)
SPF_errcode_t SPF_server_set_explanation(SPF_server_t *sp, const char *exp, SPF_response_t **spf_responsep)
SPF_errcode_t SPF_server_set_sanitize(SPF_server_t *sp, int sanitize)
SPF_errcode_t SPF_server_set_localpolicy(SPF_server_t *sp, const char *policy, int use_default_whitelist, SPF_response_t **spf_responsep)
SPF_errcode_t SPF_server_set_rec_dom(SPF_server_t *sp, const char *dom)
SPF_errcode_t SPF_response_errcode(SPF_response_t *rp)
const char * SPF_response_get_smtp_comment(SPF_response_t *rp)
const char * SPF_response_get_header_comment(SPF_response_t *rp)
const char * SPF_error_message(SPF_error_t *err)
SPF_error_t * SPF_response_message(SPF_response_t *rp, int idx)
int SPF_response_messages(SPF_response_t *rp)
char SPF_error_errorp(SPF_error_t *err)
SPF_response_t * SPF_response_combine(SPF_response_t *main, SPF_response_t *r2mx)
SPF_result_t SPF_response_result(SPF_response_t *rp)
SPF_reason_t SPF_response_reason(SPF_response_t *rp)
const char * SPF_strerror(SPF_errcode_t spf_err)
const char * SPF_strresult(SPF_result_t result)
const char * SPF_strreason(SPF_reason_t reason)
SPF_request_t * SPF_request_new(SPF_server_t *spf_server)
SPF_errcode_t SPF_request_set_ipv6_str(SPF_request_t *sr, const char *astr)
SPF_errcode_t SPF_request_query_fallback(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *record)
int SPF_request_set_env_from(SPF_request_t *sr, const char *from)
SPF_errcode_t SPF_request_set_helo_dom(SPF_request_t *sr, const char *dom)
SPF_errcode_t SPF_request_set_ipv4_str(SPF_request_t *sr, const char *astr)
SPF_errcode_t SPF_request_query_rcptto(SPF_request_t *spf_request, SPF_response_t **spf_responsep, const char *rcpt_to)
SPF_errcode_t SPF_request_query_mailfrom(SPF_request_t *spf_request, SPF_response_t **spf_responsep)
int main(int argc, char *argv[])
SPF_response_t * spf_response
SPF_request_t * spf_request