Hello list,
I think spamd users would like to try this small utility.
Although its development is in the very beginning  it does its  job 
quite well for me it was written for the case
where a big mass mailer like google  is trying to send us mail. 

The utility notices such mailers and white lists  it by adding its 
allowed nets taken through spf queries to the white list. i.e.
it reads output of spamdb, then checks spf records for all greylisted 
mails and produces 'whitelist.auto' file  which can
then be used with spamd-setup.

it is small, so I put it into attachment.

-- 
With best regards,
        Gregory Edigarov
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define         ERREXIT(_p) perror(_p); exit(-1);

char           *tok[] = {"v=spf1", "redirect=", "include:", "ip4:", "ip6:"};

FILE           *out;

void            tspf(char *domain);

char           *
txtquery(const char *domain, unsigned int *ttl)
{
        unsigned char   answer[PACKETSZ], host[128], *pt, *txt;
        int             len, exp, cttl, size, txtlen, type;

        if (res_init() < 0) {
                ERREXIT("res_init");
        }
        printf("*Querying %s\n", domain);
        memset(answer, 0, PACKETSZ);
        if ((len = res_query(domain, C_IN, T_TXT, answer, PACKETSZ)) < 0) {
                ERREXIT("res_query");
        }
        pt = answer + sizeof(HEADER);
        if ((exp = dn_expand(answer, answer + len, pt, host, sizeof(host))) < 
0) {
                ERREXIT("dn_expand");
        }
        pt += exp;
        GETSHORT(type, pt);
        if (type != T_TXT) {
                ERREXIT("type");
        }
        pt += INT16SZ;          /* class */
        if ((exp = dn_expand(answer, answer + len, pt, host, sizeof(host))) < 
0) {
                ERREXIT("dn_expand");
        }
        pt += exp;
        GETSHORT(type, pt);
        if (type != T_TXT) {
                ERREXIT("type");
        }
        pt += INT16SZ;          /* class */
        GETLONG(cttl, pt);
        *ttl = cttl;
        GETSHORT(size, pt);
        txtlen = *pt;
        if (txtlen >= size || !txtlen) {
                ERREXIT("txtlen");
        }
        if (!(txt = malloc(txtlen + 2))) {
                ERREXIT("malloc")
        }
        pt++;
        strlcpy(txt, pt, txtlen + 1);
        return txt;
}

void
do_redirect(char *p)
{
        char           *txt;
        unsigned        ttl;

        p += strlen(tok[1]);
        puts(p);
        txt = txtquery(p, &ttl);
        tspf(txt);
}

void
do_include(char *p)
{
        char           *txt;
        unsigned        ttl;

        p += strlen(tok[2]);
        txt = txtquery(p, &ttl);

        tspf(txt);
}

void
do_ipv4(char *p)
{
        p += strlen(tok[3]);
        fprintf(out, "%s\n", p);
}

void
do_ipv6(char *p)
{
        p += strlen(tok[3]);
        fprintf(out, "%s\n", p);
}


void
tspf(char *dom)
{
        char           *ans, *p, *last;
        int             spf_v = 0;
        unsigned int    ttl;

        ans = txtquery(dom, &ttl);

        for (p = strtok_r(ans, " ", &last);
             p;
             p = strtok_r(NULL, " ", &last)) {
                if (!strncmp(p, tok[0], strlen(tok[0])))
                        spf_v = 1;
                if (!strncmp(p, tok[1], strlen(tok[1])) && spf_v)
                        do_redirect(p);
                if (!strncmp(p, tok[2], strlen(tok[2])) && spf_v)
                        do_include(p);
                if (!strncmp(p, tok[3], strlen(tok[3])) && spf_v)
                        do_ipv4(p);
                if (!strncmp(p, tok[4], strlen(tok[4])) && spf_v)
                        do_ipv6(p);
        }
        free(ans);
}

int
main(int argc, char **argv)
{
        FILE           *in;
        char            buf[1024];
        char            type[64], ip[256], helo[1024], mailfrom[1024], 
rcptto[1024],
                        td1[1024], td2[1024], td3[1024], trig1[2], trig2[2];
        char           *p;

        system("mv whitelist.auto whitelist.old");
        if (argc > 1)
                out = fopen(argv[1], "a+");
        else
                out = fopen("whitelist.new", "a+");

        if (out == NULL) {
                ERREXIT("fopen");
        }
        in = popen("spamdb", "r");
        if (in == NULL) {
                ERREXIT(p);
        }
        while (fgets(buf, sizeof(buf), in)) {
                if (!strncmp(buf, "GREY", 4)) {
                        for (p = (char *) &buf; *p; p++)
                                if (*p == '|')
                                        *p = ' ';
                        sscanf(buf, "%s %s %s %s %s %s %s %s %s %s",
                               (char *) &type, (char *) &ip, (char *) &helo, 
(char *) &mailfrom, (char *) &rcptto,
                               (char *) &td1, (char *) &td2, (char *) &td3, 
(char *) &trig1, (char *) &trig2);
                        puts((char *) &type);
                        puts((char *) &mailfrom);
                }
                p = strchr((char *) &mailfrom, '>');
                *p = '\0';
                p = strchr((char *) &mailfrom, '@');
                ++p;
                tspf(p);
        }
        fclose(out);

        system("cat whitelist.old whitelist.new|sort|uniq>whitelist.auto");
        exit(0);
}
PROG=   spf2whitelist
NOMAN=  noman

.include <bsd.prog.mk>

Reply via email to