/* exchange. */
/* */
/********************************************************/
+#include <errno.h>
+#include <malloc.h>
+#include <resolv.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "subrou.h"
#include "unidns.h"
+
+#define B64K 65536 /*according US Cert VU#738331 */
+typedef union {
+ HEADER hdr; /*defined in resolv.h */
+ u_char buf[B64K]; /*according US Cert VU#738331 */
+ }RSPTYP;
+
static _Bool modopen; //module open/close status
+/*
+\f
+*/
+/************************************************/
+/* */
+/* Procedure to query DNS information */
+/* */
+/************************************************/
+static int myquery(const char *dname,int class,int type,
+ unsigned char *answer, int anslen)
+
+{
+#define OPEP "unidns.c:myquery,"
+
+int got;
+
+if ((got=res_query(dname,class,type,answer,anslen))<0) {
+ got=-1; /*trouble trouble*/
+ switch (errno) {
+ case 0 : /* do not care */
+ got=0; /*NO answer! */
+ break;
+ case ETIMEDOUT : /*rqst timed out*/
+ (void) rou_alert(0,"%s Timeout on domain <%s>!",OPEP,dname);
+ break;
+ default :
+ (void) rou_alert(0,"%s query error for domain <%s> type='%d' "
+ "(error=<%d/%s>)",OPEP,dname,type,errno,strerror(errno));
+ }
+ }
+else {
+ if (got>anslen) {
+ (void) rou_alert(0,"%s query too by for domain <%s> type='%d' (got=%d)",
+ OPEP,dname,type,got);
+ got=anslen;
+ }
+ }
+return got;
+
+#undef OPEP
+}
+/*
+\f
+*/
+/************************************************/
+/* */
+/* Procedure to extract text information */
+/* from DNS record. */
+/* SMTP client status. */
+/* */
+/************************************************/
+static char **extracting(RSPTYP *rsp,int rsplen,char *request,char *field)
+
+{
+#define OPEP "unidns.c:extracting,"
+
+char **list;
+int question;
+int answer;
+const unsigned char *msg;
+const unsigned char *eom;
+const unsigned char *cp;
+int rc;
+char buf[NS_PACKETSZ+1];
+
+list=(char **)0;
+question=ntohs(rsp->hdr.qdcount);
+answer=ntohs(rsp->hdr.ancount);
+msg=(unsigned char *)rsp;
+eom=(unsigned char *)rsp+rsplen;
+cp=(unsigned char *)rsp+sizeof(HEADER);
+while ((question-->0)&&(cp<eom)) {
+ if ((rc=dn_expand(msg,eom,cp,(char *)buf,sizeof(buf)-1))<0)
+ break;
+ cp +=rc+QFIXEDSZ;
+ }
+while((answer-->0)&&(cp<eom)) {
+ if ((rc=dn_expand(msg,eom,cp,(char *)buf,sizeof(buf)-1))<0) {
+ break;
+ }
+ if (rc>0) {
+ int type;
+ int class;
+ long ttl;
+ int dlen;
+ int collected;
+ const unsigned char *txtptr;
+ char *dynbuf;
+
+ cp+=rc;
+ GETSHORT(type,cp);
+ GETSHORT(class,cp);
+ GETLONG(ttl,cp);
+ GETSHORT(dlen,cp);
+ if (class!=1) {
+ (void) rou_alert(0,"%s unexpected class='%d' on request <%s> field=<%s> (ttl='%d')",
+ OPEP,class,request,field,ttl);
+ cp+=dlen;
+ break; /*no need to go further */
+ }
+ collected=0;
+ dynbuf=(char *)0;
+ switch (type) {
+ case T_MX :
+ if ((rc=dn_expand(msg,eom,cp+2,(char *)buf,sizeof(buf)-1))>0) {
+ int pref;
+ char info[30];
+
+ pref=(((unsigned int)cp[0])<<8)|((unsigned int)cp[1]);
+ (void) snprintf(info,sizeof(info),"%d",pref);
+ list=(char **)rou_addlist((void **)list,(void *)strdup(info));
+ list=(char **)rou_addlist((void **)list,(void *)strdup(buf));
+ }
+ break;
+ case T_CNAME :
+ #ifdef GETCNAME_2011
+ /*we are not interested to collect CNAME for now (JMP Feb 2011) */
+ if ((rc=dn_expand(msg,eom,cp,(char *)buf,sizeof(buf)))>0) {
+ list=(char **)rou_addlist((void **)list,(void *)strdup("100"));
+ list=(char **)rou_addlist((void **)list,(void *)strdup(buf));
+ }
+ #endif
+ break;
+ case T_SPF :
+ case T_TXT :
+ txtptr=cp;
+ dynbuf=(char *)calloc(10,sizeof(char));
+ while (collected<dlen) {
+ u_int taille;
+ char *newdynbuf;
+
+ (void) memset(buf,'\000',sizeof(buf));
+ taille=((u_int)(txtptr[0]))&0X0FF;
+ txtptr++;
+ (void) snprintf(buf,sizeof(buf),"%.*s ",taille,txtptr);
+ if ((newdynbuf=(char *)realloc(dynbuf,strlen(dynbuf)+strlen(buf)+5))!=(char *)0) {
+ dynbuf=newdynbuf;
+ (void) strcat(dynbuf,buf);
+ }
+ collected+=taille+1;
+ txtptr+=taille;
+ }
+ list=(char **)rou_addlist((void **)list,(void *)dynbuf);
+ break;
+ case T_A : {
+ u_int32_t *addr;
+
+ addr=(u_int32_t *)calloc(1,sizeof(u_int32_t));
+ *addr=ntohl(*((u_int32_t *)cp));
+ list=(char **)rou_addlist((void **)list,(void *)addr);
+ }
+ break;
+ case T_AAAA :
+ (void) rou_alert(0,"%s Unexpected T_AAAA field",OPEP);
+ break;
+ case T_PTR :
+ if ((rc=dn_expand(msg,eom,cp,(char *)buf,sizeof(buf)-1))>0) {
+ list=(char **)rou_addlist((void **)list,(void *)strdup(buf));
+ }
+ break;
+ default :
+ (void) rou_alert(0,"%s Unexpected '%d' field",OPEP,type);
+ break;
+ }
+ cp+=dlen;
+ }
+ }
+return list;
+#undef OPEP
+}
+/*
+^L
+*/
+/************************************************/
+/* */
+/* Procedure to extract a domain TXT */
+/* If the domain doesn't exist or domain */
+/* do not have a TXT, a void pointer is */
+/* returned. */
+/* */
+/* */
+/************************************************/
+static char **gettxt(char *domain,int ttype,char *field)
+
+{
+char **inftxt;
+int answer;
+RSPTYP rsp;
+
+inftxt=(char **)0;
+(void) memset(rsp.buf,'\000',sizeof(rsp.buf));
+switch (answer=myquery(domain,C_IN,ttype,rsp.buf,sizeof(rsp.buf))) {
+ case -1 : /*timeout */
+ break;
+ case 0 : /*no data available */
+ break;
+ default : /*data */
+ inftxt=extracting(&rsp,answer,domain,field);
+ break;
+ }
+return inftxt;
+}
+/*
+^L
+*/
+/************************************************/
+/* */
+/* Procedure to extract a hostname SPF */
+/* Search first for an SPF record, if not */
+/* implemented search for a TXT record */
+/* If the domain doesn't exist or domain */
+/* do not have a TXT or SPF, a void pointer*/
+/* is returned. */
+/* */
+/* */
+/************************************************/
+static char **getspf(char *domain)
+
+{
+char **inftxt;
+
+if ((inftxt=gettxt(domain,T_SPF,"SPF"))==(char **)0)
+ inftxt=gettxt(domain,T_TXT,"TXT");
+return inftxt;
+}
+/*
+^L
+*/
+/************************************************/
+/* */
+/* Procedure to extract a hostname TXT */
+/* If the domain doesn't exist or domain */
/*
^L
*/
PUBLIC SPFENU dns_get_spf_status(char *domain,char *peerip)
{
+#define OPEP "unidns.c:dns_get_spf_status"
+
SPFENU spf;
+char **list;
+int phase;
+_Bool proceed;
spf=spf_unknown;
+list=(char **)0;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //Are the parameters available
+ if ((domain==(char *)0)||(peerip=(char *)0)) {
+ (void) rou_alert(0,"%s missing one or both needed argument",OPEP);
+ phase=999; //trouble trouble
+ }
+ break;
+ case 1 : //get the spf LIST related to SPF
+ if ((list=getspf(domain))==(char **)0) {
+ phase=999;
+ }
+ break;
+ case 2 : //gett the spf LIST related to SPF
+ if (list!=(char **)0) {
+ char **ptr;
+
+ ptr=list;
+ while (*ptr!=(char *)0) {
+ (void) printf("JMPDBG <%s>\n",*ptr);
+ ptr++;
+ }
+ }
+ break;
+ default : //SAFE guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
return spf;
+
+#undef OPEP
}
/*
^L