OBJS= \
modrec.o \
lvleml.o \
- gestcp.o \
+ gesspf.o gestcp.o \
devlog.o devsoc.o \
unidns.o unieml.o \
unipar.o uniprc.o unisig.o unitls.o \
unieml.h \
lvleml.h lvleml.c
+gesspf.o: \
+ subrou.h \
+ gesspf.h gesspf.h
+
gestcp.o: \
subrou.h \
unieml.h \
devsoc.h devsoc.c
unidns.o: \
- subafn.h subrou.h \
+ subrou.h \
unidns.h unidns.c
unieml.o: \
subrou.h \
devlog.h devsoc.h
-unidns.h: \
+gesspf.h: \
subafn.h
uniprc.h: \
--- /dev/null
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/********************************************************/
+/* */
+/* Implement all routine to manage SMTP low level */
+/* exchange. */
+/* */
+/********************************************************/
+#include <errno.h>
+#include <malloc.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "subrou.h"
+#include "unidns.h"
+#include "gesspf.h"
+
+#define MXDNS 10 //maximun number of DNS acess
+
+typedef enum { //mechanism definition
+ mch_all, //"all"
+ mch_a, //'a'
+ mch_exists, //"existe"
+ mch_include, //"include"
+ mch_ip4, //"ip4"
+ mch_ip6, //"ip6"
+ mch_mx, //"mx"
+ mch_ptr, //"mx"
+ mch_redirect, //"redirect"
+ mch_unknown //unknown mechanism
+ }MCHTYP;
+
+static _Bool modopen; //module open/close status
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to display SPF debug information */
+/* */
+/********************************************************/
+static void dbgspf(int dbg,char *proc,char *domain,AFNTYP *afnnum,char *seq,SPFENU status)
+
+{
+if (debug>-dbg) {
+ (void) rou_alert(dbg,"Origin=\"%s\"\n"
+ "\tCurrent SPF Value <%s>\n"
+ "\tPeer IP=[%s]\n"
+ "\tdomain=<%s> SPF=<%s>",
+ proc,spf_spfASCII(status),afnnum->strnumip,domain,seq);
+ }
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to parse mechanisme string */
+/* */
+/********************************************************/
+static MCHTYP tellmechanism(char *seq)
+
+{
+//MUST be set in the MCHTYP order
+static char *voc[]=
+ {
+ "all", //allways match
+ "a", //addresss
+ "exists", //allways match
+ "include", //include sub domain
+ "ip4", //IPV4 address format
+ "ip6", //IPV5 address format
+ "mx", //MX definition
+ "ptr", //PTR definition
+ "redirect", //PTR definition
+ (char *)0
+ };
+
+MCHTYP mch;
+
+mch=mch_unknown;
+for (int i=0;voc[i]!=(char *)0;i++) {
+ register int taille;
+
+ taille=strlen(voc[i]);
+ if (strncmp(voc[i],seq,taille)!=0)
+ continue;
+ (void) memmove(seq,seq+taille,strlen(seq+taille)+1);
+ mch=(MCHTYP)i;
+ break;
+ }
+return mch;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to get the next SPF component */
+/* return a dynamic char pointer with the isolated */
+/* SPF sequence. */
+/* */
+/********************************************************/
+static char *getspfseq(char *fullspf)
+
+{
+char *seq;
+int phase;
+_Bool proceed;
+
+seq=(char *)0;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //Converting the IP number
+ if (fullspf==(char *)0)
+ phase=999; //no need to go further
+ break;
+ case 1 : //skipping blank
+ while ((*fullspf==' ')||(*fullspf=='\t'))
+ fullspf++; //scanning blank
+ if (strlen(fullspf)==0)
+ phase=999; //no need to go further
+ break;
+ case 2 : //detecting specific char
+ seq=strdup(fullspf);
+ if (strchr("?~-+",fullspf[0])!=(char *)0) {
+ seq[1]='\000'; //on char only
+ phase=999; //no need to go further
+ }
+ break;
+ case 3 : //cleaning sequence
+ if (seq!=(char *)0) { //always
+ char *ptr;
+
+ if ((ptr=strchr(seq,' '))!=(char *)0)
+ *ptr='\000';
+ if ((ptr=strchr(seq,'\t'))!=(char *)0)
+ *ptr='\000';
+ }
+ break;
+ default : //SAFE Guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return seq;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to check the SPF MX values againt the */
+/* current afnnum. */
+/* return true if successful. */
+/* */
+/********************************************************/
+static _Bool checkmx(char *domain,AFNTYP *afnnum,char *seq)
+
+{
+_Bool found;
+
+found=false;
+return found;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to check ip peerip is within an */
+/* spf sequence */
+/* */
+/********************************************************/
+static _Bool checkip(char *domain,AFNTYP *afnnum,char *seq)
+
+{
+#define OPEP "gesspf.c:checkip"
+_Bool found;
+int cidr;
+AFNTYP *target;
+int phase;
+_Bool proceed;
+
+found=false;
+cidr=128;
+target=(AFNTYP *)0;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //Converting the IP number
+ if (seq==(char *)0) {
+ (void) rou_alert(2,"%s Sequence missing from domain <%s> "
+ "(Wrong SPF sequence wrong)",OPEP,domain);
+ phase=999;
+ }
+ break;
+ case 1 : //calculating the local cidr
+ if (seq!=(char *)0) { //always
+ char *ptr;
+
+ if ((ptr=strchr(seq,'/'))!=(char *)0) {
+ *ptr='\000';
+ cidr=atoi(ptr+1);
+ }
+ }
+ break;
+ case 2 : //computing the target ipnumber
+ if ((target=afn_getipnum(seq))==(AFNTYP *)0) {
+ (void) rou_alert(0,"%s Unable to convert <%s> from "
+ "domain <%s> (SPF bug?)",
+ OPEP,seq,domain);
+ phase=999; //no need to go further
+ }
+ break;
+ case 3 : //calculating the local cidr
+ switch (afn_cmpipnum(afnnum,target,cidr)) {
+ case -1 :
+ (void) rou_alert(0,"%s Unable to compare IP [%s] from SPF "
+ "domain <%s> (errno=<%s>) (SPF?)",
+ OPEP,seq,domain);
+ break;
+ case 1 :
+ found=true;
+ break;
+ case 0 :
+ found=false;
+ break;
+ }
+ target=afn_freeipnum(target);
+ break;
+ default : //SAFE guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return found;
+
+#undef OPEP
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to return an spf status according */
+/* sequence contents */
+/* */
+/********************************************************/
+static SPFENU checkseq(int *try,char *domain,char *seq,AFNTYP *afnnum,SPFENU spf)
+
+{
+#define OPEP "gesspf.c:checkseq"
+SPFENU locspf;
+int phase;
+_Bool proceed;
+
+spf=spf_neutral;
+locspf=spf_pass;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //is the sequence an SPF Mechanisms
+ if (strlen(seq)==1) {
+ switch (seq[0]) {
+ case '?' :
+ locspf=spf_neutral;
+ break;
+ case '~' :
+ locspf=spf_softfail;
+ break;
+ case '+' :
+ locspf=spf_pass;
+ break;
+ case '-' :
+ locspf=spf_fail;
+ break;
+ default :
+ (void) rou_alert(0,"%s <%s> is not an expected SPF Prefix (Bug?)",
+ OPEP,seq);
+ break;
+ }
+ phase=999; //no need to go further
+ }
+ break;
+ case 1 : //check directive
+ switch (tellmechanism(seq)) {
+ case mch_all : //usually last in sequence
+ spf=locspf;
+ break;
+ case mch_mx : //This is a MX refrence
+ if (checkmx(domain,afnnum,seq+1)==true)
+ spf=locspf;
+ break;
+ case mch_ip4 : //This is IPV4 number
+ case mch_ip6 : //This is IPV6 number
+ if (checkip(domain,afnnum,seq+1)==true)
+ spf=locspf;
+ (void) dbgspf(2,"checkip",domain,afnnum,seq+1,spf);
+ break;
+ case mch_include : //include sub domain
+ if (seq[0]==':') {
+ (*try)++;
+ spf=spf_getstatus(try,seq+1,afnnum);
+ }
+ else {
+ (void) rou_alert(0,"%s wrong SPF include seq <%s> (SPF format?)",
+ OPEP,seq);
+ spf=spf_permerr;
+ }
+ break;
+ default : //trouble
+ break;
+ case mch_unknown : //trouble
+ (void) rou_alert(0,"%s unknown mechanism <%s> (bug?, config?)",
+ OPEP,seq);
+ spf=spf_permerr;
+ break;
+ }
+ break;
+ default : //SAFE guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return spf;
+
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to return check if an IP is part of */
+/* spf allowed IP */
+/* */
+/********************************************************/
+static SPFENU is_peerip_ok(int *try,char *domain,AFNTYP *afnnum,char *spfrec)
+
+{
+#define OPEP "gesspf.c:is_peerip_ok"
+SPFENU spf;
+int phase;
+_Bool proceed;
+
+spf=spf_neutral;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //Converting the IP number
+ if (spfrec==(char *)0) {
+ (void) rou_alert(0,"%s SPF record is NULL (bug?)",OPEP);
+ phase=999;
+ }
+ break;
+ case 1 : //making sure spfrec is an SPF1
+ if (strlen(spfrec)>0) {
+ char *seq;
+ char *ref;
+
+ ref=spfrec;
+ while ((seq=getspfseq(spfrec))!=(char *)0) {
+ spfrec=strstr(spfrec,seq);
+ spfrec+=strlen(seq);
+ spf=checkseq(try,domain,seq,afnnum,spf);
+ seq=rou_freestr(seq);
+ if (spf!=spf_neutral)
+ break; //Found a pass status, breaking loop
+ }
+ (void) dbgspf(2,"is_peerip_ok",domain,afnnum,ref,spf);
+ }
+ break;
+ default : //SAFE Guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return spf;
+
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to return the SPF status string value */
+/* */
+/********************************************************/
+PUBLIC const char *dns_spfASCII(SPFENU spf)
+
+{
+#define OPEP "gesspf.c:dns_spfASCII"
+static char *spfascii[]=
+ {
+ "spf_pass",
+ "spf_fail",
+ "spf_softfail",
+ "spf_neutral",
+ "spf_timeout",
+ "spf_missing",
+ "spf_permerr",
+ "spf_unknown"
+ };
+
+const char *ascii;
+
+ascii="Unset (Bug?)";
+switch (spf) {
+ case spf_pass :
+ case spf_fail :
+ case spf_softfail :
+ case spf_neutral :
+ case spf_timeout :
+ case spf_missing :
+ case spf_permerr :
+ case spf_unknown :
+ ascii=spfascii[spf];
+ break;
+ default :
+ (void) rou_alert(0,"%s, Unexpected '%d' SPF status (Bug!)",OPEP,spf);
+ break;
+ }
+return ascii;
+
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to get the SPF status according a */
+/* domain name and and an IP. */
+/* */
+/********************************************************/
+PUBLIC SPFENU spf_getstatus(int *try,char *domain,AFNTYP *afnnum)
+
+{
+#define OPEP "gesspf.c:dns_get_spf_status"
+
+SPFENU spf;
+char *list;
+int phase;
+_Bool proceed;
+
+(*try)++;
+spf=spf_permerr;
+list=(char *)0;
+phase=0;
+proceed=true;
+(void) printf("JMPDBG try='%02d' domain=<%s> peerip=<%s>\n",
+ *try,domain,afnnum->strnumip);
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //Are the parameters available
+ if ((domain==(char *)0)||(afnnum==(AFNTYP *)0)) {
+ (void) rou_alert(0,"%s missing one or both needed argument",OPEP);
+ phase=999; //trouble trouble
+ }
+ break;
+ case 1 : //check the number of DNS access
+ if ((*try)>MXDNS) {
+ (void) rou_alert(0,"%s SPF record scan is too deep (aborting)",OPEP);
+ phase=999; //trouble trouble
+ }
+ break;
+ case 2 : //get the spf LIST related to SPF
+ if ((list=dns_getspf(domain))==(char *)0)
+ phase=999; //trouble trouble
+ break;
+ case 3 : //check if we have only ONE SPF entry
+ if (rou_nbrlist((void **)list)>1) {
+ (void) rou_alert(0,"%s more than 1 SPF record for domain <%s>",
+ OPEP,domain);
+ phase=999; //trouble trouble
+ }
+ break;
+ case 4 : //gett the spf LIST related to SPF
+ spf=is_peerip_ok(try,domain,afnnum,list);
+ list=rou_freestr(list);
+ break;
+ default : //SAFE guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+return spf;
+
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
+/* Procedure to "open/close" module and do */
+/* homework purpose */
+/* return zero if everything right */
+/* */
+/********************************************************/
+int spf_modegesspf(_Bool mode)
+
+{
+#define OPEP "unidoc.c:soc_modeunisoc"
+
+int status;
+
+status=0;
+if (mode!=modopen) {
+ (void) rou_modesubrou(mode);
+ (void) afn_modesubafn(mode);
+ switch ((int)mode) {
+ case true :
+ break;
+ case false :
+ break;
+ default :
+ (void) fprintf(stderr,"Calling %s with wrong mode='%d' (Bug?!):",
+ OPEP,(int)mode);
+ status=-1;
+ break;
+ }
+ modopen=mode;
+ }
+return status;
+#undef OPEP
+}
--- /dev/null
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/********************************************************/
+/* */
+/* Define all procedure to manage SPF entry within */
+/* DNS record. */
+/* */
+/********************************************************/
+#ifndef GESTSPF
+#define GESTSPF
+
+#include "subafn.h"
+
+typedef enum {
+ spf_pass, //OK if condition apply
+ spf_fail, //NOK if condition apply
+ spf_softfail, //Msg origin is dubious
+ spf_neutral, //same status as no SPF
+ spf_timeout, //no answer within time
+ spf_missing, //SPF not found
+ spf_permerr, //SPF permanent error
+ spf_unknown //Unknown SPF directive
+ }SPFENU;
+
+//procedure to return spf status as an ASCII string
+extern const char *spf_spfASCII(SPFENU spf);
+
+//get the SPF status for a specific domain and a remote peer IP
+extern SPFENU spf_getstatus(int *try,char *domain,AFNTYP *afnnum);
+
+//homework to be done before starting/stopping module.
+extern int spf_modegesspf(_Bool mode);
+
+#endif
//version definition
#define VERSION "0.4.2"
-#define RELEASE "15"
+#define RELEASE "16"
//Public variables
PUBLIC int debug=0; //debug level
#include "subrou.h"
#include "unidns.h"
-#define MXDNS 10 //maximun number of DNS acess
-
//spf1 marker within DNS record
#define SPF1 "v=spf1 "
u_char buf[B64K]; //according US Cert VU#738331
}RSPTYP;
-typedef enum { //mechanism definition
- mch_all, //"all"
- mch_a, //'a'
- mch_exists, //"existe"
- mch_include, //"include"
- mch_ip4, //"ip4"
- mch_ip6, //"ip6"
- mch_mx, //"mx"
- mch_ptr, //"mx"
- mch_redirect, //"redirect"
- mch_unknown //unknown mechanism
- }MCHTYP;
-
static _Bool modopen; //module open/close status
/*
\f
*/
/********************************************************/
/* */
-/* Procedure to display SPF debug information */
-/* */
-/********************************************************/
-static void dbgspf(int dbg,char *proc,char *domain,AFNTYP *afnnum,char *seq,SPFENU status)
-
-{
-if (debug>-dbg) {
- (void) rou_alert(dbg,"Origin=\"%s\"\n"
- "\tCurrent SPF Value <%s>\n"
- "\tPeer IP=[%s]\n"
- "\tdomain=<%s> SPF=<%s>",
- proc,dns_spfASCII(status),afnnum->strnumip,domain,seq);
- }
-}
-/*
-\f
-*/
-/********************************************************/
-/* */
/* Procedure to compare 2 MX and return */
/* a value according preference value */
/* */
*/
/********************************************************/
/* */
-/* Procedure to parse mechanisme string */
-/* */
-/********************************************************/
-static MCHTYP tellmechanism(char *seq)
-
-{
-//MUST be set in the MCHTYP order
-static char *voc[]=
- {
- "all", //allways match
- "a", //addresss
- "exists", //allways match
- "include", //include sub domain
- "ip4", //IPV4 address format
- "ip6", //IPV5 address format
- "mx", //MX definition
- "ptr", //PTR definition
- "redirect", //PTR definition
- (char *)0
- };
-
-MCHTYP mch;
-
-mch=mch_unknown;
-for (int i=0;voc[i]!=(char *)0;i++) {
- register int taille;
-
- taille=strlen(voc[i]);
- if (strncmp(voc[i],seq,taille)!=0)
- continue;
- (void) memmove(seq,seq+taille,strlen(seq+taille)+1);
- mch=(MCHTYP)i;
- break;
- }
-return mch;
-}
-/*
-\f
-*/
-/********************************************************/
-/* */
-/* Procedure to get the next SPF component */
-/* return a dynamic char pointer with the isolated */
-/* SPF sequence. */
-/* */
-/********************************************************/
-static char *getspfseq(char *fullspf)
-
-{
-char *seq;
-int phase;
-_Bool proceed;
-
-seq=(char *)0;
-phase=0;
-proceed=true;
-while (proceed==true) {
- switch (phase) {
- case 0 : //Converting the IP number
- if (fullspf==(char *)0)
- phase=999; //no need to go further
- break;
- case 1 : //skipping blank
- while ((*fullspf==' ')||(*fullspf=='\t'))
- fullspf++; //scanning blank
- if (strlen(fullspf)==0)
- phase=999; //no need to go further
- break;
- case 2 : //detecting specific char
- seq=strdup(fullspf);
- if (strchr("?~-+",fullspf[0])!=(char *)0) {
- seq[1]='\000'; //on char only
- phase=999; //no need to go further
- }
- break;
- case 3 : //cleaning sequence
- if (seq!=(char *)0) { //always
- char *ptr;
-
- if ((ptr=strchr(seq,' '))!=(char *)0)
- *ptr='\000';
- if ((ptr=strchr(seq,'\t'))!=(char *)0)
- *ptr='\000';
- }
- break;
- default : //SAFE Guard
- proceed=false;
- break;
- }
- phase++;
- }
-return seq;
-}
-/*
-\f
-*/
-/********************************************************/
-/* */
-/* Procedure to check the SPF MX values againt the */
-/* current afnnum. */
-/* return true if successful. */
-/* */
-/********************************************************/
-static _Bool checkmx(char *domain,AFNTYP *afnnum,char *seq)
-
-{
-_Bool found;
-
-found=false;
-return found;
-}
-/*
-\f
-*/
-/********************************************************/
-/* */
-/* Procedure to check ip peerip is within an */
-/* spf sequence */
-/* */
-/********************************************************/
-static _Bool checkip(char *domain,AFNTYP *afnnum,char *seq)
-
-{
-#define OPEP "unidns.c:checkip"
-_Bool found;
-int cidr;
-AFNTYP *target;
-int phase;
-_Bool proceed;
-
-found=false;
-cidr=128;
-target=(AFNTYP *)0;
-phase=0;
-proceed=true;
-while (proceed==true) {
- switch (phase) {
- case 0 : //Converting the IP number
- if (seq==(char *)0) {
- (void) rou_alert(2,"%s Sequence missing from domain <%s> "
- "(Wrong SPF sequence wrong)",OPEP,domain);
- phase=999;
- }
- break;
- case 1 : //calculating the local cidr
- if (seq!=(char *)0) { //always
- char *ptr;
-
- if ((ptr=strchr(seq,'/'))!=(char *)0) {
- *ptr='\000';
- cidr=atoi(ptr+1);
- }
- }
- break;
- case 2 : //computing the target ipnumber
- if ((target=afn_getipnum(seq))==(AFNTYP *)0) {
- (void) rou_alert(0,"%s Unable to convert <%s> from "
- "domain <%s> (SPF bug?)",
- OPEP,seq,domain);
- phase=999; //no need to go further
- }
- break;
- case 3 : //calculating the local cidr
- switch (afn_cmpipnum(afnnum,target,cidr)) {
- case -1 :
- (void) rou_alert(0,"%s Unable to compare IP [%s] from SPF "
- "domain <%s> (errno=<%s>) (SPF?)",
- OPEP,seq,domain);
- break;
- case 1 :
- found=true;
- break;
- case 0 :
- found=false;
- break;
- }
- target=afn_freeipnum(target);
- break;
- default : //SAFE guard
- proceed=false;
- break;
- }
- phase++;
- }
-return found;
-
-#undef OPEP
-}
-/*
-\f
-*/
-/********************************************************/
-/* */
-/* Procedure to return an spf status according */
-/* sequence contents */
-/* */
-/********************************************************/
-static SPFENU checkseq(int *try,char *domain,char *seq,AFNTYP *afnnum,SPFENU spf)
-
-{
-#define OPEP "unidns.c:checkseq"
-SPFENU locspf;
-int phase;
-_Bool proceed;
-
-spf=spf_neutral;
-locspf=spf_pass;
-phase=0;
-proceed=true;
-while (proceed==true) {
- switch (phase) {
- case 0 : //is the sequence an SPF Mechanisms
- if (strlen(seq)==1) {
- switch (seq[0]) {
- case '?' :
- locspf=spf_neutral;
- break;
- case '~' :
- locspf=spf_softfail;
- break;
- case '+' :
- locspf=spf_pass;
- break;
- case '-' :
- locspf=spf_fail;
- break;
- default :
- (void) rou_alert(0,"%s <%s> is not an expected SPF Prefix (Bug?)",
- OPEP,seq);
- break;
- }
- phase=999; //no need to go further
- }
- break;
- case 1 : //check directive
- switch (tellmechanism(seq)) {
- case mch_all : //usually last in sequence
- spf=locspf;
- break;
- case mch_mx : //This is a MX refrence
- if (checkmx(domain,afnnum,seq+1)==true)
- spf=locspf;
- break;
- case mch_ip4 : //This is IPV4 number
- case mch_ip6 : //This is IPV6 number
- if (checkip(domain,afnnum,seq+1)==true)
- spf=locspf;
- (void) dbgspf(2,"checkip",domain,afnnum,seq+1,spf);
- break;
- case mch_include : //include sub domain
- if (seq[0]==':') {
- (*try)++;
- spf=dns_get_spf_status(try,seq+1,afnnum);
- }
- else {
- (void) rou_alert(0,"%s wrong SPF include seq <%s> (SPF format?)",
- OPEP,seq);
- spf=spf_permerr;
- }
- break;
- default : //trouble
- break;
- case mch_unknown : //trouble
- (void) rou_alert(0,"%s unknown mechanism <%s> (bug?, config?)",
- OPEP,seq);
- spf=spf_permerr;
- break;
- }
- break;
- default : //SAFE guard
- proceed=false;
- break;
- }
- phase++;
- }
-return spf;
-
-#undef OPEP
-}
-/*
-\f
-*/
-/********************************************************/
-/* */
/* Procedure to query DNS information */
/* */
/********************************************************/
/* is returned. */
/* */
/********************************************************/
-static char **getspf(char *domain)
+PUBLIC char *dns_getspf(char *domain)
{
-char **infspf;
-
-if ((infspf=gettxt(domain,T_SPF,"SPF"))==(char **)0) {
- char **inftxt;
-
- inftxt=gettxt(domain,T_TXT,"TXT");
- if (inftxt!=(char **)0) {
- char **ptr;
-
- ptr=inftxt;
- while (*ptr!=(char *)0) {
- if (strstr(*ptr,SPF1)==*ptr) {
- char *dup;
-
- dup=strdup(*ptr);
- infspf=(char **)rou_addlist((void **)infspf,(void *)dup);
- }
- ptr++;
- }
- inftxt=(char **)rou_freelist((void **)inftxt,(freehandler_t)rou_freestr);
- }
- }
-return infspf;
-}
-/*
-^L
-*/
-/********************************************************/
-/* */
-/* Procedure to return check if an IP is part of */
-/* spf allowed IP */
-/* */
-/********************************************************/
-static SPFENU is_peerip_ok(int *try,char *domain,AFNTYP *afnnum,char *spfrec)
-
-{
-#define OPEP "unidns.c:is_peerip_ok"
-SPFENU spf;
-int phase;
-_Bool proceed;
+char *spfrec;
+char **list;
-spf=spf_neutral;
-phase=0;
-proceed=true;
-while (proceed==true) {
- switch (phase) {
- case 0 : //Converting the IP number
- if (spfrec==(char *)0) {
- (void) rou_alert(0,"%s SPF record is NULL (bug?)",OPEP);
- phase=999;
- }
- break;
- case 1 : //making sure spfrec is an SPF1
- if (strstr(spfrec,SPF1)!=spfrec) {
- (void) rou_alert(0,"%s DNS SPF <%s> not a valide one ",OPEP,spfrec);
- phase=999;
- }
- break;
- case 2 : //making sure spfrec is an SPF1
- spfrec+=strlen(SPF1);
- if (strlen(spfrec)>0) {
- char *seq;
- char *ref;
+spfrec=(char *)0;
+if ((list=gettxt(domain,T_SPF,"SPF"))==(char **)0)
+ list=gettxt(domain,T_TXT,"TXT");
+if (list!=(char **)0) {
+ char **ptr;
- ref=spfrec;
- while ((seq=getspfseq(spfrec))!=(char *)0) {
- spfrec=strstr(spfrec,seq);
- spfrec+=strlen(seq);
- spf=checkseq(try,domain,seq,afnnum,spf);
- seq=rou_freestr(seq);
- if (spf!=spf_neutral)
- break; //Found a pass status, breaking loop
- }
- (void) dbgspf(2,"is_peerip_ok",domain,afnnum,ref,spf);
- }
- break;
- default : //SAFE Guard
- proceed=false;
+ ptr=list;
+ while (*ptr!=(char *)0) {
+ if (strstr(*ptr,SPF1)==*ptr) {
+ spfrec=strdup(*ptr+strlen(SPF1));
break;
+ }
+ ptr++;
}
- phase++;
+ list=(char **)rou_freelist((void **)list,(freehandler_t)rou_freestr);
}
-return spf;
-
-#undef OPEP
-}
-/*
-^L
-*/
-/********************************************************/
-/* */
-/* Procedure to return the SPF status string value */
-/* */
-/********************************************************/
-PUBLIC const char *dns_spfASCII(SPFENU spf)
-
-{
-#define OPEP "unidns.c:dns_spfASCII"
-static char *spfascii[]=
- {
- "spf_pass",
- "spf_fail",
- "spf_softfail",
- "spf_neutral",
- "spf_timeout",
- "spf_missing",
- "spf_permerr",
- "spf_unknown"
- };
-
-const char *ascii;
-
-ascii="Unset (Bug?)";
-switch (spf) {
- case spf_pass :
- case spf_fail :
- case spf_softfail :
- case spf_neutral :
- case spf_timeout :
- case spf_missing :
- case spf_permerr :
- case spf_unknown :
- ascii=spfascii[spf];
- break;
- default :
- (void) rou_alert(0,"%s, Unexpected '%d' SPF status (Bug!)",OPEP,spf);
- break;
- }
-return ascii;
-
-#undef OPEP
+return spfrec;
}
/*
^L
}
return mxlist;
-#undef OPEP
-}
-/*
-^L
-*/
-/********************************************************/
-/* */
-/* Procedure to get the SPF status according a */
-/* domain name and and an IP. */
-/* */
-/********************************************************/
-PUBLIC SPFENU dns_get_spf_status(int *try,char *domain,AFNTYP *afnnum)
-
-{
-#define OPEP "unidns.c:dns_get_spf_status"
-
-SPFENU spf;
-char **list;
-int phase;
-_Bool proceed;
-
-(*try)++;
-spf=spf_permerr;
-list=(char **)0;
-phase=0;
-proceed=true;
-(void) printf("JMPDBG try='%02d' domain=<%s> peerip=<%s>\n",
- *try,domain,afnnum->strnumip);
-while (proceed==true) {
- switch (phase) {
- case 0 : //Are the parameters available
- if ((domain==(char *)0)||(afnnum==(AFNTYP *)0)) {
- (void) rou_alert(0,"%s missing one or both needed argument",OPEP);
- phase=999; //trouble trouble
- }
- break;
- case 1 : //check the number of DNS access
- if ((*try)>MXDNS) {
- (void) rou_alert(0,"%s SPF record scan is too deep (aborting)",OPEP);
- phase=999; //trouble trouble
- }
- break;
- case 2 : //get the spf LIST related to SPF
- if ((list=getspf(domain))==(char **)0)
- phase=999; //trouble trouble
- break;
- case 3 : //check if we have only ONE SPF entry
- if (rou_nbrlist((void **)list)>1) {
- (void) rou_alert(0,"%s more than 1 SPF record for domain <%s>",
- OPEP,domain);
- phase=999; //trouble trouble
- }
- break;
- case 4 : //gett the spf LIST related to SPF
- spf=is_peerip_ok(try,domain,afnnum,list[0]);
- list=(char **)rou_freelist((void **)list,(freehandler_t)rou_freestr);
- break;
- default : //SAFE guard
- proceed=false;
- break;
- }
- phase++;
- }
-return spf;
-
#undef OPEP
}
/*
status=0;
if (mode!=modopen) {
(void) rou_modesubrou(mode);
- (void) afn_modesubafn(mode);
switch ((int)mode) {
case true :
break;
#ifndef UNIDNS
#define UNIDNS
-#include "subafn.h"
-
-typedef enum {
- spf_pass, //OK if condition apply
- spf_fail, //NOK if condition apply
- spf_softfail, //Msg origin is dubious
- spf_neutral, //same status as no SPF
- spf_timeout, //no answer within time
- spf_missing, //SPF not found
- spf_permerr, //SPF permanent error
- spf_unknown //Unknown SPF directive
- }SPFENU;
-
//defining an MX structure
typedef struct {
int preference; /*MX preference */
char *mxname; /*MX hostname */
}MXTYP;
-//procedure to return spf status as an ASCII string
-extern const char *dns_spfASCII(SPFENU spf);
+//Procedure to get ONE SPF entry within domain dns
+extern char *dns_getspf(char *domain);
//procedure to get a list of MX IP releated to a specific
//domain.
extern MXTYP **dns_getmx(char *domain);
-//get the SPF status for a specific domain and a remote peer IP
-extern SPFENU dns_get_spf_status(int *try,char *domain,AFNTYP *afnnum);
-
//homework to be done before starting/stopping module.
extern int dns_modeunidns(_Bool mode);