From 121fbdd822f5ddbc882ce978ef49c62821b603cc Mon Sep 17 00:00:00 2001 From: Jean-Marc Pigeon Date: Tue, 18 Nov 2025 15:09:12 -0500 Subject: [PATCH] Better check about helo fqdn --- data-feed/feed010.tst | 17 +++-- data-feed/feed10.tst | 2 +- lib/lvleml.c | 155 ++++++++++++++++++++++++------------------ 3 files changed, 104 insertions(+), 70 deletions(-) diff --git a/data-feed/feed010.tst b/data-feed/feed010.tst index e176510..67d730c 100644 --- a/data-feed/feed010.tst +++ b/data-feed/feed010.tst @@ -2,20 +2,29 @@ T:(feed010) Testing if helo and ehlo fdqdn is OK C:CONNECT R:220 mailleur.example.com, ESMTP (cleartext) mailleur... -S:HELO [129.219.254.34] +S:HELO [192.219.254.34] R:250 mailleur.example.com, link (cleartext) ready,... #==================================================== -S:HELO domain +S:HELO 192.219.254.35 +R:250 mailleur.example.com, link (cleartext) ready,... +QUIT +#==================================================== +S:HELO domain R:250 mailleur.example.com, link (cleartext) ready,... #==================================================== S:HELO 8.8.8.8 R:250 mailleur.example.com, link (cleartext) ready,... #==================================================== S:EHLO .com -R:501 5.5.4 syntax error (domain part missing), closing connection. +R:501 5.5.4 HELO argument is incorrect, closing connection. #==================================================== C:CONNECT R:220 mailleur.example.com, ESMTP (cleartext) mailleur... S:EHLO domain..com -R:501 5.5.4 syntax error (domain part missing), closing connection. +R:501 5.5.4 HELO argument is incorrect, closing connection. +#==================================================== +C:CONNECT +R:220 mailleur.example.com, ESMTP (cleartext) mailleur... +S:EHLO [.192.219.254.1] +R:501 5.5.4 HELO argument is incorrect, closing connection. #==================================================== diff --git a/data-feed/feed10.tst b/data-feed/feed10.tst index d4ab7a0..50c2f0b 100644 --- a/data-feed/feed10.tst +++ b/data-feed/feed10.tst @@ -3,7 +3,7 @@ T:(feed10) Testing if MX is found R:220 mailleur.example.com, ESMTP (cleartext) mailleur... #==================================================== -S:HELO example.com +S:HELO example.com R:250 mailleur.example.com, link (cleartext) ready,... S:MAIL FROM: R:250 2.1.3 postmaster@example.com sender ok diff --git a/lib/lvleml.c b/lib/lvleml.c index 29e350d..abeaa7f 100644 --- a/lib/lvleml.c +++ b/lib/lvleml.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -1116,62 +1117,48 @@ static _Bool isgoodfqdn(CONTYP *contact,char *parameter) { #define OPEP "lvleml.c:isgoodfqdn" +#define HELL " !@#$%^&*()=+[]{}|\\:;'\"<>,?" -_Bool done; +_Bool good; int phase; _Bool proceed; -done=false; +good=false; phase=0; proceed=true; while (proceed==true) { //(void) rou_alert(0,"JMPDBG %s phase='%d' parm=<%s>",OPEP,phase,parameter); + (void) rou_dbglive(7,OPEP,"phase='%d' parm=<%s>",phase,parameter); switch (phase) { - case 0 : //do we start with a dot or 2 dot - if ((parameter[0]=='.')||(strstr(parameter,"..")!=(char *)0)) { - (void) rou_alert(0,"%s sesid=<%s> fqdn <%s> not a good domain", - OPEP,contact->mainsesid,parameter); - phase=999; //bad parameter - } - break; - case 1 : //could it be localhost or localdomain - if (strcasecmp(parameter,"localhost.localdomain")==0) { - (void) rou_alert(0,"%s sesid=<%s> fqdn <%s> local!", - OPEP,contact->mainsesid,parameter); - phase=999; - } - break; - case 2 : //check if it only a hostname - if (strstr(parameter,".")==(char *)0) { - (void) rou_alert(0,"%s sesid=<%s> fqdn <%s> is an host name!", - OPEP,contact->mainsesid,parameter); - phase=999; - } - break; - case 3 : //could it be an IP - if (parameter[0]=='[') { - (void) rou_alert(0,"%s sesid=<%s> fqdn <%s> could be an ip", - OPEP,contact->mainsesid,parameter); - phase=999; //bad parameter - } - break; - case 4 : //is is an ip - if (strlen(parameter)==strspn(parameter,".0123456789")) { - (void) rou_alert(0,"%s sesid=<%s> fqdn <%s> is an ip", - OPEP,contact->mainsesid,parameter); - phase=999; //bad parameter + case 0 : //is parameter starting with '.' + if ((parameter[0]=='.')||(parameter[0]=='-')) + phase=999; //no allowed to start with dot or dash + break; + case 1 : //do we have '..' somewehre + if ((strstr(parameter,"..")!=(char *)0)|| + (strstr(parameter,"-.")!=(char *)0)|| + (strstr(parameter,".-")!=(char *)0)) + phase=999; //no allowed to start with dot + break; + case 2 : //check if char set is allowed + if (strpbrk(parameter,HELL)!=(char *)0) + phase=999; //no a good charset + break; + case 3 : //checking if parameter is only ascii + int taille; + + taille=strlen(parameter); + for (int i=0;ifqdn; //parameter could be the SAME! + case 4 : //seems to be a good fqdn + good=true; + contact->fqdn=rou_freestr(contact->fqdn); contact->fqdn=strdup(parameter); - ptr=rou_freestr(ptr); - break; - case 6 : //check if we can resolve fqdn - break; - case 7 : //is resolved IP is the same as remote break; default : //SAFE guard proceed=false; @@ -1179,7 +1166,9 @@ while (proceed==true) { } phase++; } -return done; +return good; + +#undef HELL #undef OPEP } /* @@ -1187,7 +1176,7 @@ return done; */ /********************************************************/ /* */ -/* Procedure to check if helo or ehlo paatmeter */ +/* Procedure to check if helo or ehlo parameter */ /* is an acceptable one */ /* */ /********************************************************/ @@ -1195,42 +1184,83 @@ static _Bool isgoodhelo(CONTYP *contact,char *parameter) { #define OPEP "lvleml.c:isgoodhelo" +#define DETAIL "HELO argument is incorrect, closing connection" -_Bool done; +_Bool good; +int last; +char original[100]; int phase; _Bool proceed; -done=false; +good=false; +last=0; +(void) memset(original,'\000',sizeof(original)); phase=0; proceed=true; while (proceed==true) { - //(void) rou_alert(0,"JMPDBG %s phase='%d' parm=<%s>",OPEP,phase,parameter); + (void) rou_alert(0,"%s phase='%d' domain=<%s> last='%d'",OPEP,phase,parameter,last); + (void) rou_dbglive(7,OPEP,"phase='%d' domain=<%s>",phase,parameter); switch (phase) { case 0 : //checking if we have a parameter - if ((parameter==(char *)0)||(strlen(parameter)==0)) { + if (parameter==(char *)0) { (void) rou_alert(0,"%s sesid=<%s> fqdn is missing!", OPEP,contact->mainsesid); phase=999; //no parameter } break; - case 1 : //do we have only good character - if (strpbrk(parameter,"@(&$")!=(char *)0) { - (void) rou_alert(0,"%s sesid=<%s> fqdn <%s> wrong contents", - OPEP,contact->mainsesid,parameter); - phase=999; //bad parameter + case 1 : //strip possible space at the end pf parameter + (void) strncpy(original,parameter,sizeof(original)-1); + last=strlen(parameter)-1; + while ((parameter[last]==' ')&&(last>=0)) { + parameter[last]='\000'; + last--; } break; - case 2 : //ehlo is acceptable, lets check if fqdn - done=true; - contact->isgoodfqdn=isgoodfqdn(contact,parameter); + case 2 : //cannot start with '.' + if (parameter[0]=='.') { + (void) rou_alert(0,"%s sesid=<%s> wrong fqdn=<%s>" + OPEP,contact->mainsesid,parameter); + phase=999; //wrong parameter + } + break; + case 3 : //check if we have an fqdn + if ((good=isgoodfqdn(contact,parameter))==true) + phase=999; + break; + case 4 : //is it an enclosed IP + if ((parameter[0]=='[')&&(parameter[last]==']')) { + parameter[last]='\000'; + (void) memmove(parameter,parameter+1,last); + last--; + last--; + if (strlen(parameter)==0) { + phase=999; + } + } + break; + case 5 : //checking if it is starting or endig with dot + if ((parameter[0]=='.')||(parameter[last]=='.')) + phase=999; //yes but not acceptable + break; + case 6 : //checking fi double dot inside + if (strstr(parameter,"..")!=(char *)0) + phase=999; //yes but not acceptable + break; + case 7 : //are all character good + if (strlen(parameter)==strspn(parameter,".0123456789")) + good=true; break; default : //SAFE guard + if (good==false) + (void) note_status(contact,BADPAR,NULL," 5.5.4 %s.",DETAIL); proceed=false; break; } phase++; } -return done; +return good; + +#undef DETAIL #undef OPEP } /* @@ -1525,19 +1555,16 @@ static _Bool dohelo(CONTYP *contact,char *parameter) { #define OPEP "lvleml.c:dohelo" -#define DETAIL "HELO argument is mandatory, closing connection" _Bool done; if ((done=isgoodhelo(contact,parameter))==false) { - (void) eml_transmit(contact,true,"%d 5.5.4 %s.",BADPAR,DETAIL); (void) setterminator(contact,"HELO parameter missing"); contact->credit-=2; } else (void) linkready(contact,false); return done; -#undef DETAIL #undef OPEP } /* @@ -1566,7 +1593,6 @@ static struct { }; #define OPEP "lvleml.c:doehlo" -#define DETAIL "syntax error (domain part missing), closing connection" _Bool done; int strstart; @@ -1582,8 +1608,7 @@ while (proceed==true) { switch (phase) { case 0 : //Do we have a parameter if ((done=isgoodhelo(contact,parameter))==false) { - (void) eml_transmit(contact,true,"%d 5.5.4 %s.",BADPAR,DETAIL); - (void) setterminator(contact,"EHLO parameter missing"); + (void) setterminator(contact,"HELO parameter incorrect"); contact->credit-=2; //penalty phase=999; //Trouble trouble } -- 2.47.3