From 83ed78d06ce50812c671245b54cc2a8986b9e625 Mon Sep 17 00:00:00 2001 From: "Jean-Marc Pigeon (Delson)" Date: Wed, 7 May 2025 09:58:02 -0400 Subject: [PATCH] Data exchange is starting to work --- Makefile | 2 +- app/feeder.c | 115 ++++++++++++++++++++++++++++++++++++++------ data-tst/xxfeed.tst | 14 +++--- lib/lvleml.c | 43 ++++++++++++++++- lib/unieml.c | 2 +- lib/unieml.h | 7 +-- 6 files changed, 152 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index 233921a..6e234f2 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ dbgfeed : debug -c ./conf/feeder.conf.dvl \ $(TESTIP) \ $(TESTPORT) \ - $(DATATST)/feedxx.tst + $(DATATST)/xxfeed.tst valfeed : debug #valgring of emlrcvr @ echo "feed valgrind test" diff --git a/app/feeder.c b/app/feeder.c index c125142..3a2d5ef 100644 --- a/app/feeder.c +++ b/app/feeder.c @@ -24,6 +24,9 @@ #define FNAME "feeder" +#define WRESP 5 //wait 5 sec for SMTP server + //to answer + static char titre[100]; //test title static char testname[100]; //dest description @@ -32,11 +35,13 @@ typedef struct { char *destport; //Port to connect to char *srcip; //IP to be used as source _Bool commented; //feed in comment mode + FILE *datatst; //reference to the data-tst file SOCPTR *socptr; //connection socket }FEEDTYP; typedef enum { //List of command cmd_comment, //Test sequence in int/out comment mode + cmd_data, //start the SMTP data sequence cmd_gotls, //going in tls mode cmd_orgn, //Change peer IP origin cmd_restart, //restart connection with remote server @@ -128,13 +133,86 @@ return done; */ /************************************************/ /* */ +/* procedure to send data to remote SMTP */ +/* server. */ +/* */ +/************************************************/ +static _Bool dosenddata(FEEDTYP *fd) + +{ +int status; +char *line; +char *action; +_Bool empty; +char data[300]; +int phase; +_Bool proceed; + +status=false; +line=(char *)0; +action="data"; +empty=false; +(void) strcpy(data,""); +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //Transmit "DATA" to remote + if (dooutgoing(fd->socptr,action)!=(strlen(action)+2)) + phase=999; //Unable to send STARTTLS sequence + break; + case 1 : //Get STARTTLS command status + if (tcp_getline(fd->socptr,WRESP,&line)<=0) + phase=999; //Didn't get signon + break; + case 2 : //did we received the Proper "proceed" acknoledge + if (line!=(char *)0) { //Always + int code; + + code=0; + (void) sscanf(line,"%d",&code); + if (code!=DATAOK) + phase=999; + line=rou_freestr(line); + } + break; + case 3 : // + while (fgets(data,sizeof(data),fd->datatst)!=(char *)0) { + (void) rou_alert(0,"JMPDBG got <%s>",data); + if ((empty==true)||(strcmp(data,".")==0)) { + phase++; //Eveythin is fine + break; + } + empty=false; + if (strlen(data)==0) + empty=true; + } + break; + case 4 : //phase reached only by data exhaustion + phase=999; //Trouble trouble + break; + case 5 : //we have completed data transmission + status=true; + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return status; +} +/* +^L +*/ +/************************************************/ +/* */ /* procedure to set the link in TLS mode */ /* */ /************************************************/ static _Bool gomodetls(SOCPTR *socptr) { -#define WTLS 5 /*wait 5 sec for TLS */ _Bool status; char *got; @@ -154,7 +232,7 @@ while (proceed==true) { phase=999; //Unable to send STARTTLS sequence break; case 1 : //Get STARTTLS command status - if (tcp_getline(socptr,WTLS,&got)<=0) + if (tcp_getline(socptr,WRESP,&got)<=0) phase=999; //Didn't get signon break; case 2 : //did we received the signon @@ -227,6 +305,7 @@ static struct { const char *cmd; }cmdavail[]={ {cmd_comment,"COMMENT"}, + {cmd_data,"DATA"}, {cmd_gotls,"GOTLS"}, {cmd_orgn,"ORGN"}, {cmd_restart,"RESTART"}, @@ -266,6 +345,14 @@ if ((param=strchr(line,' '))!=(char *)0) { param++; //pointer on parameter } switch (getcmd(line)) { + case cmd_comment : //detect comment flag + if (setcomment(fd,param)==false) + (void) report(numline,line,"Unable to set comment mode"); + break; + case cmd_data : //sending email content to remote + if ((status=dosenddata(fd))==false) + (void) report(numline,line,"Unable to fully send data"); + break; case cmd_gotls : //GOTLS if ((status=gomodetls(fd->socptr))==false) (void) report(numline,line,"Unable to set TLS mode"); @@ -280,6 +367,10 @@ switch (getcmd(line)) { status=false; } break; + case cmd_restart : //restart link + if ((status=dorestart(fd,(char *)0))==false) + (void) report(numline,line,"Unable to restart feed socket!"); + break; case cmd_wait : //SLEEP mode if (param!=(char *)0) (void) sleep(atoi(param)); @@ -288,14 +379,6 @@ switch (getcmd(line)) { status=false; } break; - case cmd_restart : //restart link - if ((status=dorestart(fd,(char *)0))==false) - (void) report(numline,line,"Unable to restart feed socket!"); - break; - case cmd_comment : //restart link - if (setcomment(fd,param)==false) - (void) report(numline,line,"Unable to set comment mode"); - break; case cmd_unknown : default : (void) report(numline,line,"Unknown command"); @@ -476,7 +559,6 @@ static _Bool scanonefile(FEEDTYP *fd,const char *filename) { _Bool status; -FILE *fichier; int numline; char line[200]; int phase; @@ -484,7 +566,6 @@ _Bool proceed; status=false; (void) strcpy(testname,""); -fichier=(FILE *)0; numline=0; (void) strcpy(line,""); phase=0; @@ -503,7 +584,7 @@ while (proceed==true) { ptr=filename; (void) snprintf(titre,sizeof(titre),"%s:",ptr); } - if ((fichier=fopen(filename,"r"))==(FILE *)0) { + if ((fd->datatst=fopen(filename,"r"))==(FILE *)0) { (void) rou_alert(0,"Unable to open file <%s> (error=<%s>", filename,strerror(errno)); proceed=false; @@ -514,12 +595,13 @@ while (proceed==true) { if (fd->socptr==(SOCPTR *)0) { (void) rou_alert(0,"Unable to open link to [%s:%s]", fd->destip,fd->destport); - (void) fclose(fichier); + (void) fclose(fd->datatst); + fd->datatst=(FILE *)0; proceed=false; //Can not scan file } break; case 2 : //reading line; - while (fgets(line,sizeof(line),fichier)!=(char *)0) { + while (fgets(line,sizeof(line),fd->datatst)!=(char *)0) { char *ptr; numline++; @@ -538,7 +620,8 @@ while (proceed==true) { break; default : //SAFE Guard fd->socptr=soc_closefeedsock(fd->socptr); - (void) fclose(fichier); + (void) fclose(fd->datatst); + fd->datatst=(FILE *)0; proceed=false; break; } diff --git a/data-tst/xxfeed.tst b/data-tst/xxfeed.tst index ba9621c..9138616 100644 --- a/data-tst/xxfeed.tst +++ b/data-tst/xxfeed.tst @@ -14,13 +14,13 @@ R:250 2.6.2 Address accepted #------------------------------------------------------------------------- #-sending data C:DATA -R:354 Enter mail, end with "." on a line by itself -D:Subject: test clmfd30 (Checking dynamic override) -D: -D:FIRST Line -D:SECOND Line -D:LAST Line -D:. +Subject: test clmfd30 (Checking dynamic override) + +FIRST Line +SECOND Line +LAST Line + +. R:250 Message accepted for delivery S:QUIT R:221 2.0.0 Bye, closing connection... diff --git a/lib/lvleml.c b/lib/lvleml.c index 6b3deeb..1776d7a 100644 --- a/lib/lvleml.c +++ b/lib/lvleml.c @@ -143,7 +143,7 @@ done=false; phase=0; proceed=true; while (proceed==true) { - (void) rou_alert(0,"JMPDBG %s phase='%d' parm=<%s>",OPEP,phase,parameter); + //(void) rou_alert(0,"JMPDBG %s phase='%d' parm=<%s>",OPEP,phase,parameter); switch (phase) { case 0 : //checking if we have a parameter if ((parameter==(char *)0)||(strlen(parameter)==0)) @@ -168,6 +168,44 @@ return done; */ /************************************************/ /* */ +/* Procedure to accept EMAIL contents from */ +/* SMTP peers. */ +/* Return true, if everything is fine */ +/* */ +/************************************************/ +static _Bool getdata(CONTYP *contact) + +{ +#define OPEP "lvleml.c:getdata," + +_Bool done; +int phase; +_Bool proceed; + +done=false; +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d'",OPEP,phase); + switch (phase) { + case 0 : //Do we have a parameter + (void) transmit(contact,"%d 3.5.0 %s", + DATAOK,"End data with ."); + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return done; +#undef OPEP +} +/* + +*/ +/************************************************/ +/* */ /* Procedure to send an "HELO" message */ /* if EHLO message is not accepted. */ /* */ @@ -438,6 +476,9 @@ while (proceed==true) { (void) log_fprintlog(contact->logptr,false,"%s",line); code=eml_getcode(line); switch (code) { + case c_data : //Peer request to transfer email corps. + proceed=getdata(contact); + break; case c_helo : //HELO SMTP protocol proceed=dohelo(contact,line); break; diff --git a/lib/unieml.c b/lib/unieml.c index 2bedf6f..41baffc 100644 --- a/lib/unieml.c +++ b/lib/unieml.c @@ -20,6 +20,7 @@ typedef struct { //this list order by key length static VOCTYP vocsmtp[]={ + {c_data,"DATA"}, {c_ehlo,"EHLO"}, {c_helo,"HELO"}, {c_mail,"MAIL FROM:"}, @@ -108,7 +109,6 @@ for (ptr=vocsmtp;ptr->key!=(char *)0;ptr++) { break; } } -(void) rou_alert(0,"%s JMPDBG code='%d'",OPEP,code); return code; #undef OPEP } diff --git a/lib/unieml.h b/lib/unieml.h index bb007b9..a50656b 100644 --- a/lib/unieml.h +++ b/lib/unieml.h @@ -13,21 +13,18 @@ #define SIGNON 220 //signon information #define QUITOK 221 //status on quit #define CMDOK 250 //Everything OK +#define DATAOK 354 //Ready to accept EMAIL data #define BADPAR 501 //error in parameters #define CMDBAD 502 //command not implemented -//SMTP avail command -//#define MAILF "MAIL FROM:" //Mail from a sender -//#define GOTLS "STARTTLS" //Requesting crypted mode - //list of keyword typedef enum { //list of SMTP protocol keyword + c_data, //DATA email contents transfer request c_ehlo, //EHLO command c_helo, //Basic Helo command c_mail, //'mail from:' sequence detected c_noop, //No Operation request - c_orgn, //DEBUG PEERIP override c_quit, //quit exchange c_rcpt, //'rcpt to:' sequence detected c_rset, //resetting session -- 2.47.3