summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Varshavchik2014-11-05 21:56:15 -0500
committerSam Varshavchik2014-11-05 21:56:15 -0500
commit0d35e591d4b01e78e85486ed3c03b45586d64e18 (patch)
tree4afa1eff32725f5a5db7ad06e1bc135fc8d2985c
parentfd405a94770d5a1fa26b2cd2712f0d3e9fb7448c (diff)
downloadcourier-libs-0d35e591d4b01e78e85486ed3c03b45586d64e18.tar.bz2
Implement support for SPF records with multiple strings.
-rw-r--r--rfc1035/rfc1035.h4
-rw-r--r--rfc1035/spf.c79
-rw-r--r--rfc1035/testlookup.c4
3 files changed, 72 insertions, 15 deletions
diff --git a/rfc1035/rfc1035.h b/rfc1035/rfc1035.h
index 1d6eb31..7b9c4e7 100644
--- a/rfc1035/rfc1035.h
+++ b/rfc1035/rfc1035.h
@@ -540,8 +540,8 @@ const char *rfc1035_fmttime(unsigned long, char *);
char *rfc1035_dumprrdata(struct rfc1035_reply *, struct rfc1035_rr *);
int rfc1035_rr_gettxt(struct rfc1035_rr *,
- int,
- char buf[256]);
+ int,
+ char buf[256]);
/*
** I ignore any possible bugs in the resolver functions, and roll my own,
diff --git a/rfc1035/spf.c b/rfc1035/spf.c
index efda0d9..0894d86 100644
--- a/rfc1035/spf.c
+++ b/rfc1035/spf.c
@@ -149,7 +149,7 @@ char rfc1035_spf_lookup(const char *mailfrom,
static int isspf1(struct rfc1035_reply *reply, int n)
{
- char txtbuf[256];
+ char txtbuf[256];
const char *p;
rfc1035_rr_gettxt(reply->allrrs[n], 0, txtbuf);
@@ -166,15 +166,61 @@ static int isspf1(struct rfc1035_reply *reply, int n)
return 0;
}
-char rfc1035_spf_gettxt_res(const char *current_domain,
- char *buf,
- struct rfc1035_res *res)
+struct rfc1035_exp_str {
+ struct rfc1035_exp_str *next;
+ const char *ptr;
+};
+
+static char *rfc1035_concat_strings(struct rfc1035_rr *rr,
+ int startpos,
+ struct rfc1035_exp_str *head,
+ struct rfc1035_exp_str *tail)
+{
+ char buf[256];
+ struct rfc1035_exp_str node;
+ int ret=rfc1035_rr_gettxt(rr, startpos, buf);
+
+ node.next=NULL;
+ node.ptr=buf;
+ tail->next=&node;
+
+ if (ret < 0)
+ {
+ size_t s=1;
+ char *buf;
+ struct rfc1035_exp_str *p;
+
+ for (p=head; p; p=p->next)
+ {
+ s += strlen(p->ptr);
+ }
+
+ buf=malloc(s);
+ if (!buf)
+ return NULL;
+ *buf=0;
+
+ for (p=head; p; p=p->next)
+ {
+ strcat(buf, p->ptr);
+ }
+ return buf;
+ }
+
+ return rfc1035_concat_strings(rr, ret,
+ head,
+ &node);
+}
+
+static char rfc1035_spf_gettxt_res(const char *current_domain,
+ char **buf,
+ struct rfc1035_res *res)
{
struct rfc1035_reply *reply;
char namebuf[RFC1035_MAXNAMESIZE+1];
int n, o;
-
+ *buf=0;
namebuf[0]=0;
strncat(namebuf, current_domain, RFC1035_MAXNAMESIZE);
@@ -213,6 +259,11 @@ char rfc1035_spf_gettxt_res(const char *current_domain,
if (n >= 0)
{
+ struct rfc1035_exp_str str;
+
+ str.next=NULL;
+ str.ptr="";
+
for (o=n; (o=rfc1035_replysearch_an(res, reply, namebuf,
RFC1035_TYPE_TXT,
RFC1035_CLASS_IN,
@@ -234,16 +285,20 @@ char rfc1035_spf_gettxt_res(const char *current_domain,
}
}
- rfc1035_rr_gettxt(reply->allrrs[n], 0, buf);
+ *buf=rfc1035_concat_strings(reply->allrrs[n], 0, &str, &str);
rfc1035_replyfree(reply);
+
+ if (!*buf)
+ return SPF_UNKNOWN;
+
return SPF_PASS;
}
rfc1035_replyfree(reply);
return SPF_UNKNOWN;
}
-char rfc1035_spf_gettxt(const char *current_domain,
- char *buf)
+char rfc1035_spf_gettxt_n(const char *current_domain,
+ char **buf)
{
struct rfc1035_res res;
char c;
@@ -1009,7 +1064,7 @@ static void setexp(const char *exp,
static char lookup(struct rfc1035_spf_info *info)
{
- char record[256];
+ char *record;
char c;
/*
@@ -1025,12 +1080,14 @@ static char lookup(struct rfc1035_spf_info *info)
return SPF_UNKNOWN;
}
- c=rfc1035_spf_gettxt(info->current_domain, record);
+ c=rfc1035_spf_gettxt_n(info->current_domain, &record);
if (c != SPF_PASS)
return c;
- return rfc1035_spf_compute(record, info);
+ c=rfc1035_spf_compute(record, info);
+ free(record);
+ return c;
}
/*
diff --git a/rfc1035/testlookup.c b/rfc1035/testlookup.c
index 6ee7c61..657bf33 100644
--- a/rfc1035/testlookup.c
+++ b/rfc1035/testlookup.c
@@ -44,9 +44,9 @@ extern char rfc1035_spf_gettxt(const char *current_domain,
static void spflookup(const char *current_domain)
{
- char buf[256];
+ char *buf;
- switch (rfc1035_spf_gettxt(current_domain, buf)) {
+ switch (rfc1035_spf_gettxt_n(current_domain, &buf)) {
case SPF_NONE:
printf("none\n");
return;