From: Jean-Marc Pigeon (Delson) Date: Tue, 11 Feb 2025 11:48:22 +0000 (-0500) Subject: chkspf start to work X-Git-Tag: tag-0.4.2-end~2 X-Git-Url: https://jmp-git.ovh.safe.ca/?a=commitdiff_plain;h=20f60ace4481b1b80826897cd4432968f944d4a5;p=jmp%2Fmailleur chkspf start to work --- diff --git a/app/Makefile b/app/Makefile index 5022dd0..4ac6bd5 100644 --- a/app/Makefile +++ b/app/Makefile @@ -23,12 +23,12 @@ clean : EXE= \ emlrec \ maild \ - emlval \ + chkspf \ SRC= \ emlrec.c \ maild.c \ - emlval.c \ + chkspf.c \ #-------------------------------------------------------------------- #definitions @@ -50,10 +50,10 @@ emlrec : toremake emlrec.o maild : toremake maild.o @ $(LD) $(LDFLAGS) -o ../bin/$@ $@.o $(LIBS) -emlval : toremake emlval.o +chkspf : toremake chkspf.o @ $(LD) $(LDFLAGS) -o ../bin/$@ $@.o $(LIBS) -emlval.o: emlval.c \ +chkspf.o: chkspf.c \ ../lib/unidns.h \ ../lib/subafn.h \ ../lib/subrou.h diff --git a/app/chkspf.c b/app/chkspf.c new file mode 100644 index 0000000..bf98826 --- /dev/null +++ b/app/chkspf.c @@ -0,0 +1,126 @@ +// vim: smarttab tabstop=8 shiftwidth=2 expandtab +/********************************************************/ +/* */ +/* Validation program to check SPF extraction */ +/* library. */ +/* */ +/********************************************************/ +#include +#include +#include +#include +#include + +#include "subrou.h" +#include "subafn.h" +#include "unidns.h" +#include "unipar.h" +#include "uniprc.h" +#include "gesspf.h" + +#define VALNAME "emlval" //validator application + +//vocabulary enum +typedef enum { + voc_start, //"start" + voc_end, //"end" + voc_include, //"include" + voc_unknown //unknown keys + }voc_enum; + +//vocabulary (Must be in sync withvoc_enum list) +char *vocable[]={ + "start", + "end", + "include", + (char *)0 + }; +/* + +*/ +/********************************************************/ +/* */ +/* Procedure to check SPF domain/peerip status */ +/* return the SPF status as an ascii. */ +/* */ +/********************************************************/ +static void checkstatus(char *domain,char *peerip) + +{ +int try; +SPFENU spf; +AFNTYP *afnnum; + +try=0; +afnnum=afn_getipnum(peerip); +spf=spf_getstatus(&try,domain,afnnum); +(void) fprintf(stdout,"%s\n",spf_spfASCII(spf)); +afnnum=afn_freeipnum(afnnum); +} +/* + +*/ +/********************************************************/ +/* */ +/* Main routine */ +/* Return an SPF status according arguments*/ +/* 1 - Domain name */ +/* 2 - IP */ +/* */ +/********************************************************/ +int main(int argc,char *argv[]) + +{ +int status; +int phase; +ARGTYP *params; +_Bool proceed; + +status=0; +params=(ARGTYP *)0; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //checking parameters + if ((params=par_getparams(argc,argv,"d:hr:v"))==(ARGTYP *)0) + phase=999; //no need to go further + break; + case 1 : //check if we have file to scan + if (params->argc!=2) { + (void) fprintf(stderr,"Unable to proceed with test\n"); + (void) fprintf(stderr,"\tthe test pattern number should be 2\n"); + status=-1; + phase=999; + } + break; + case 2 : + (void) rou_setappname(VALNAME); + (void) afn_modesubafn(true); + (void) rou_modesubrou(true); + (void) par_modeunipar(true); + (void) prc_modeuniprc(true); + (void) spf_modegesspf(true); + (void) prc_preptitle(argc,argv,environ); + foreground=true; + break; + case 3 : //doing main task + (void) checkstatus(params->argv[0],params->argv[1]); + break; + case 4 : //task completed + (void) prc_cleantitle(); + params=par_freeparams(params); + (void) spf_modegesspf(false); + (void) prc_modeuniprc(false); + (void) par_modeunipar(false); + (void) rou_modesubrou(false); + (void) afn_modesubafn(false); + break; + default : //end of task + proceed=false; + break; + } + phase++; + } +(void) exit(status); +} diff --git a/app/emlval.c b/app/emlval.c deleted file mode 100644 index 8bffafa..0000000 --- a/app/emlval.c +++ /dev/null @@ -1,417 +0,0 @@ -// vim: smarttab tabstop=8 shiftwidth=2 expandtab -/********************************************************/ -/* */ -/* Validation program to check SPF extraction */ -/* library. */ -/* */ -/********************************************************/ -#include -#include -#include -#include -#include - -#include "subrou.h" -#include "subafn.h" -#include "unidns.h" -#include "unipar.h" -#include "uniprc.h" -#include "gesspf.h" - -#define VALNAME "emlval" //validator application - -//vocabulary enum -typedef enum { - voc_start, //"start" - voc_end, //"end" - voc_include, //"include" - voc_unknown //unknown keys - }voc_enum; - -//vocabulary (Must be in sync withvoc_enum list) -char *vocable[]={ - "start", - "end", - "include", - (char *)0 - }; -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to detect vocabulary */ -/* */ -/********************************************************/ -static voc_enum getvoc(char *keyword) - -{ -voc_enum voc; - -voc=voc_unknown; -if (keyword!=(char *)0) { - char **ptr; - - ptr=vocable; - for (int i=0;(*ptr)!=(char *)0;i++,ptr++) { - if (strcmp(*ptr,keyword)==0) { - voc=(voc_enum)i; - break; - } - } - } -return voc; -} -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to extrac keywork from line */ -/* */ -/********************************************************/ -static size_t cleanline(FILE *fichier,char *line,size_t max,int *numline) - -{ -size_t got; - -got=(size_t)0; -(void) strcpy(line,""); -while (got==(size_t)0) { - char *ptr; - - if (fgets(line,max,fichier)==(char *)0) - break; - (*numline)++; - if ((ptr=strchr(line,'#'))!=(char *)0) - *ptr='\000'; - if ((ptr=strchr(line,'\n'))!=(char *)0) - *ptr='\000'; - if ((ptr=strchr(line,'\r'))!=(char *)0) - *ptr='\000'; - //replacing HT by space - while ((ptr=strchr(line,'\t'))!=(char *)0) - *ptr=' '; - //removing head space - while (line[0]==' ') - (void) memmove(line,line+1,strlen(line+1)); - got=strlen(line); - } -return got; -} -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to extract keyword from line */ -/* */ -/********************************************************/ -static int getkeyword(char *keyword,char *line) - -{ -char *ptr; - -(void) strcpy(keyword,""); -//removing head space -while (line[0]==' ') - (void) memmove(line,line+1,strlen(line+1)+1); -//Extracting keyword -(void) strcpy(keyword,line); -if ((ptr=strchr(keyword,' '))!=(char *)0) - *ptr='\000'; -//cleaning line -ptr=line+strlen(keyword); -(void) memmove(line,ptr,strlen(ptr)+1); -while (line[0]==' ') - (void) memmove(line,line+1,strlen(line+1)+1); -return strlen(keyword); -} -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to check domain/peerip status */ -/* */ -/********************************************************/ -static int checkstatus(char *domain,char *peerip,char *spfstr) - -{ -_Bool status; -int try; -SPFENU spf; -AFNTYP *afnnum; - -status=true; -try=0; -afnnum=afn_getipnum(peerip); -spf=spf_getstatus(&try,domain,afnnum); -if (strcmp(spfstr,spf_spfASCII(spf))!=0) { - (void) rou_alert(2,"expected SPF status=<%s>, got<%s>", - spfstr,spf_spfASCII(spf)); - status=false; - } -afnnum=afn_freeipnum(afnnum); -return status; -} -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to scan a line from the test file */ -/* */ -/********************************************************/ -static int scanlines(char *testname,FILE *fichier,int *numline) - -{ -#define OPEP "emlval.c:scanlines" -#define MAX 300 - -int status; -char line[MAX]; - -status=0; -while (cleanline(fichier,line,sizeof(line),numline)>0) { - char keyword[MAX]; - - (void) getkeyword(keyword,line); - switch (getvoc(keyword)) { - default : - (void) rou_alert(0,"%s JMPDBG keyword=<%s>",OPEP,keyword); - break; - } - } -return status; - -#undef MAX -#undef OPEP -} -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to scan one file, return -1 if a test */ -/* is not successfull, zero otherwise. */ -/* */ -/********************************************************/ -static int scantest(char *tfile) - -{ -#define OPEP "emlval.c:scantest" - -_Bool status; -int numline; -FILE *fichier; -int phase; -_Bool proceed; - -status=false; -numline=0; -phase=0; -proceed=true; -while (proceed==true) { - (void) rou_alert(0,"%s phase='%d'",OPEP,phase); - switch (phase) { - case 0 : //opening the file - if ((fichier=fopen(tfile,"r"))==(FILE *)0) { - (void) rou_alert(0,"%s Unable to open file <%s> (error=<%s>)", - OPEP,tfile,strerror(errno)); - phase=999; - } - break; - case 1 : //scan the file - switch (scanlines(tfile,fichier,&numline)) { - } - break; - case 2 : //scan the file - (void) fclose(fichier); - break; - default : //SAFE guard - proceed=false; - break; - } - phase++; - } -return status; - -#undef OPEP -} -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to scan one filename to be a pattern */ -/* file to test */ -/* */ -/********************************************************/ -static _Bool testonefile(char *tdir,char *tfile) - -{ -#define OPEP "emlval.c:testonefile" - -_Bool status; -char *curdir; -char *basedir; -int phase; -_Bool proceed; - -status=false; -if (tdir==(char *)0) - tdir=""; -curdir=getcwd((char *)0,0); -basedir=rou_apppath(tdir); -phase=0; -proceed=true; -while (proceed==true) { - (void) rou_alert(0,"%s phase='%d'",OPEP,phase); - switch (phase) { - case 0 : //going to the right directory - if (chdir(basedir)<0) { - (void) rou_alert(0,"%s Unable to chdir to <%s> within <%s> (error=<%s>)", - OPEP,basedir,curdir,strerror(errno)); - phase=999; //Trouble trouble - } - break; - case 1 : //going to the right directory - status=scantest(tfile); - break; - case 2 : //going back to the original directory - if (chdir(curdir)<0) { - (void) rou_alert(0,"%s Unable to reach directory <%s> (error=<%s>) Bug?", - OPEP,curdir,strerror(errno)); - status=false; - phase=999; //Trouble trouble - } - break; - default : //SAFE guard - proceed=false; - break; - } - phase++; - } -basedir=rou_freestr(basedir); -curdir=rou_freestr(curdir); -return status; - -#undef OPEP -} -/* - -*/ -/********************************************************/ -/* */ -/* Procedure to scan filename present within the */ -/* parameter list */ -/* */ -/********************************************************/ -static int testfiles(ARGTYP *params) - -{ -#define OPEP "emlval.c:testfiles" - -_Bool status; -char *curdir; - -status=false; -curdir=getcwd((char *)0,0); -for (int i=0;iargc;i++) { - char *basedir; - char *basepath; - char *fname; - char *ptr; - - basedir=strdup(""); - fname=strdup(params->argv[i]); - ptr=strrchr(fname,'/'); - if (ptr!=(char *)0) { - *ptr='\000'; - (void) free(basedir); - basedir=strdup(fname); - ptr++; - (void) strcpy(fname,ptr); - } - status=testonefile(basedir,fname); - basepath=rou_freestr(basepath); - basedir=rou_freestr(basedir); - if (status==false) { - (void) rou_alert(0,"%s, <%s> test is no successfull exiting", - OPEP,params->argv[i]); - break; - } - } -curdir=rou_freestr(curdir); -return status; - -#undef OPEP -} -/* - -*/ -/********************************************************/ -/* */ -/* Main routine */ -/* Return an SPF status according arguments*/ -/* 1 - Domain name */ -/* 2 - IP */ -/* */ -/********************************************************/ -int main(int argc,char *argv[]) - -{ -int status; -int phase; -ARGTYP *params; -_Bool proceed; - -status=0; -params=(ARGTYP *)0; -phase=0; -proceed=true; -while (proceed==true) { - switch (phase) { - case 0 : //checking parameters - if ((params=par_getparams(argc,argv,"d:hr:v"))==(ARGTYP *)0) - phase=999; //no need to go further - break; - case 1 : //check if we have file to scan - if (params->argc==0) { - (void) fprintf(stderr,"Unable to proceed with test\n"); - (void) fprintf(stderr,"\tthe filenames (of test pattern) are missing\n"); - status=-1; - phase=999; - } - break; - case 2 : - (void) rou_setappname(VALNAME); - (void) afn_modesubafn(true); - (void) rou_modesubrou(true); - (void) par_modeunipar(true); - (void) prc_modeuniprc(true); - (void) spf_modegesspf(true); - (void) prc_preptitle(argc,argv,environ); - foreground=true; - break; - case 3 : //doing main tash - (void) testfiles(params); - break; - case 4 : //doing main tash - (void) prc_cleantitle(); - params=par_freeparams(params); - (void) spf_modegesspf(false); - (void) prc_modeuniprc(false); - (void) par_modeunipar(false); - (void) rou_modesubrou(false); - (void) afn_modesubafn(false); - break; - default : //end of task - proceed=false; - break; - } - phase++; - } -(void) exit(status); -} diff --git a/data-tst/spf.tst b/data-tst/spf.tst index 6b07a30..15b0e0e 100644 --- a/data-tst/spf.tst +++ b/data-tst/spf.tst @@ -1,25 +1,25 @@ #======================================================== #data to check if SPF are properly seen -#NOTE: this test rely on the fact -#"emlval.safe.ca.dns" is accessible via DNS request. +chkmx.spf.example.com#NOTE: this test rely on the fact +#"spf.example.com" is accessible via DNS request. #======================================================== #-------------------------------------------------------- #Checking MX #Acceptable IP number -OK chkmx.emlval.safe.ca 127.0.0.255 +spf_pass chkmx.spf.example.com 127.0.0.255 #wrong MX ip number -BAD chkmx.emlval.safe.ca 127.0.0.1 +spf_fail chkmx.spf.example.com 127.0.0.1 #Checking IP4 -OK chkip4.emlval.safe.ca 127.0.1.255 -BAD chkip4.emlval.safe.ca 127.0.1.1 +spf_pass chkip4.spf.example.com 127.0.1.255 +spf_fail chkip4.spf.example.com 127.0.1.1 #Checking IP6 -OK chkip6.emlval.safe.ca 0:0:0:0:0:ffff:127.0.2.255 -BAD chkip6.emlval.safe.ca 2607:180:1000:795b::127.0.2.1 +spf_pass chkip6.spf.example.com 0:0:0:0:0:ffff:127.0.2.255 +spf_fail chkip6.spf.example.com 0:0:0:0:0:ffff::127.0.2.1 ##checking addr -OK chkaddr.emlval.safe.ca 127.0.1.255 -BAD chkaddr.emlval.safe.ca 127.0.1.1 -OK chkaddr.emlval.safe.ca 2607:180:1000:795b::127.0.2.255 -BAD chkaddr.emlval.safe.ca 2607:180:1000:795b::127.0.2.1 -OK chkaddr.emlval.safe.ca 127.0.3.255 -BAD chkaddr.emlval.safe.ca 127.0.3.1 +spf_pass chkaddr.spf.example.com 127.0.1.255 +spf_fail chkaddr.spf.example.com 127.0.1.1 +spf_pass chkaddr.spf.example.com 127.0.3.255 +spf_fail chkaddr.spf.example.com 127.0.3.1 +spf_pass chkaddr.spf.example.com 0:0:0:0:0:ffff::127.0.2.255 +spf_fail chkaddr.spf.example.com 0:0:0:0:0:ffff::127.0.2.1 #-------------------------------------------------------- diff --git a/data-tst/emlval.dns b/data-tst/zone.example.com similarity index 75% rename from data-tst/emlval.dns rename to data-tst/zone.example.com index f069f8f..f062c1c 100644 --- a/data-tst/emlval.dns +++ b/data-tst/zone.example.com @@ -1,7 +1,21 @@ -;--------------------------------------------------------------------- -;to test SPF dns -$ORIGIN emlval.safe.ca. +$ORIGIN example.com. +$TTL 5m ; 5 min +@ IN SOA dns1.example.com. root.example.com. ( + 0000000000 ; Serial_Marker + 600 ; Refresh (10 min) + 300 ; retry (5 min) + 1209600 ; expiry (1W) + 900 ; minimum (15 min) + ) + + IN NS dns1 + IN NS dns2 +;--------------------------------------------------------------------- +dns1 IN A 127.0.0.1 +dns2 IN A 127.0.0.2 +;--------------------------------------------------------------------- +;test MX using IP 127.0.0.255 @ IN A 127.0.0.127 IN MX 10 mx1 IN MX 20 mx2 @@ -9,20 +23,23 @@ $ORIGIN emlval.safe.ca. mx1 IN A 127.0.0.128 mx2 IN A 127.0.0.129 -;test MX using IP 127.0.0.255 +;--------------------------------------------------------------------- +$ORIGIN example.com. chkmx IN A 127.0.0.255 IN TXT ( + "v=info " "chkmx PASS with 127.0.0.255," "chkmx FAIL with 127.0.0.1" ) IN TXT ( "v=spf1 " - "mx:spf.zoo/25 " + "mx:spf.example.com/25 " "-all" ) chkip4 IN A 127.0.1.255 IN TXT ( + "v=info " "chkip4 PASS with 127.0.1.255," "chkip4 FAIL with 127.0.1.1" ) @@ -35,6 +52,7 @@ chkip4 IN A 127.0.1.255 chkip6 IN AAAA fc00:0:0:0:ffff::7f00:002f IN TXT ( + "v=info " "chkip6 PASS with PREFIX::127.0.2.255, " "chkip6 FAIL with PREFIX::127.0.2.1" ) @@ -46,6 +64,7 @@ chkip6 IN AAAA fc00:0:0:0:ffff::7f00:002f chkaddr IN A 127.0.3.255 IN TXT ( + "v=info " "chkaddr PASS with 127.0.3.255," "chkaddr FAIL with 127.0.3.1" "chkaddr PASS with 127.0.1.255," @@ -63,6 +82,7 @@ chkaddr IN A 127.0.3.255 ;check include chkinc IN TXT ( + "v=info " "chkinc PASS with 127.0.0.255," "chkinc FAIL with 127.0.0.1" "chkinc PASS with 127.0.1.255," diff --git a/lib/subrou.c b/lib/subrou.c index 90ce8c5..5994aa9 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -21,7 +21,7 @@ //version definition #define VERSION "0.4.2" -#define RELEASE "33" +#define RELEASE "34" //Public variables PUBLIC int debug=0; //debug level