From: Jean-Marc Pigeon (Delson) Date: Wed, 2 Apr 2025 00:55:50 +0000 (-0400) Subject: Starting to implement the "STARTTLS" smtp command X-Git-Tag: tag-0.7~32 X-Git-Url: https://jmp-git.ovh.safe.ca/?a=commitdiff_plain;h=0403b7847817d6c6c050abd192c4e22cebce2e27;p=jmp%2Fmailleur Starting to implement the "STARTTLS" smtp command --- diff --git a/app/Makefile b/app/Makefile index ffae341..4ca6c77 100644 --- a/app/Makefile +++ b/app/Makefile @@ -66,10 +66,12 @@ emlrec.o: emlrec.c \ ../lib/subrou.h feeder.o: feeder.c \ + ../lib/gestcp.h \ + ../lib/devsoc.h \ + ../lib/unieml.h \ ../lib/unipar.h \ ../lib/subrou.h - toremake: Makefile $(LIBAI) touch toremake - rm -f $(EXE) *.o diff --git a/app/feeder.c b/app/feeder.c index e076379..4c9ca37 100644 --- a/app/feeder.c +++ b/app/feeder.c @@ -18,6 +18,7 @@ #include "subrou.h" #include "unipar.h" +#include "unieml.h" #include "devsoc.h" #include "gestcp.h" @@ -71,11 +72,71 @@ static void report(int numline,char *line,char *trouble) /* Procedure to send a line to remote */ /* */ /********************************************************/ -static void dooutgoing(SOCPTR *socptr,char *line) +static int dooutgoing(SOCPTR *socptr,char *line) { -(void) soc_writebuffer(socptr,line,strlen(line)); -(void) soc_writebuffer(socptr,"\r\n",2); +int count; + +count=soc_writebuffer(socptr,line,strlen(line)); +count+=soc_writebuffer(socptr,"\r\n",2); +return count; +} +/* +^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; +int phase; +_Bool proceed; + +status=false; +got=(char *)0; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //Sending START TLS command + if (dooutgoing(socptr,GOTLS)!=(strlen(GOTLS)+2)) + phase=999; //Unable to send STARTTLS sequence + break; + case 1 : //Get STARTTLS command status + if (tcp_getline(socptr,WTLS,&got)<=0) + phase=999; //Didn't get signon + break; + case 2 : //did we received the signon + if (got!=(char *)0) { //Always + int code; + + code=0; + (void) sscanf(got,"%d",&code); + if (code!=SIGNON) + phase=999; + got=rou_freestr(got); + } + break; + case 3 : //initiating TLS-Crypted mode + if (soc_starttls(socptr)==false) + phase=999; + break; + case 4 : //eveythin is fine SOC in crypted mode + status=true; + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return status; } /* @@ -132,8 +193,8 @@ if ((param=strchr(line,' '))!=(char *)0) { } switch (getcmd(line)) { case 1 : //GOTLS - (void) rou_alert(0,"JMPDBG got GOTTLS"); - status=true; + if ((status=gomodetls(socptr))==false) + (void) report(numline,line,"Unable to set TLS mode"); break; case 2 : //GOTLS if (param==(char *)0) diff --git a/lib/devsoc.c b/lib/devsoc.c index f683b79..ab16cdb 100644 --- a/lib/devsoc.c +++ b/lib/devsoc.c @@ -1371,7 +1371,7 @@ return socptr; /* crypted channel, return true is successful. */ /* */ /********************************************************/ -_Bool soc_starttls(SOCPTR *socptr,const char *peerip) +_Bool soc_starttls(SOCPTR *socptr) { _Bool ok; @@ -1381,8 +1381,10 @@ ok=false; soc=(SOCTYP *)socptr; if ((soc!=(SOCTYP *)0)&&(soc->modtls==false)) { int tosend; + char *peerip; char buffer[100]; + peerip=soc_getaddrinfo(socptr,false,false); (void) socpurge(soc,peerip); tosend=snprintf(buffer,sizeof(buffer),"%d 2.0.0 Ready to start TLS%s", SIGNON,CRLF); @@ -1393,6 +1395,7 @@ if ((soc!=(SOCTYP *)0)&&(soc->modtls==false)) { (void) socpurge(soc,peerip); ok=true; } + peerip=rou_freestr(peerip); } return ok; } diff --git a/lib/devsoc.h b/lib/devsoc.h index 01643e3..d8cffbe 100644 --- a/lib/devsoc.h +++ b/lib/devsoc.h @@ -76,6 +76,6 @@ extern char *soc_getaddrinfo(SOCPTR *socptr,_Bool local,_Bool getname); extern SOCPTR *soc_release(SOCPTR *socptr); //procedure to initiate crypted mode on plain channel -extern _Bool soc_starttls(SOCPTR *socptr,const char *peerip); +extern _Bool soc_starttls(SOCPTR *socptr); #endif diff --git a/lib/lvleml.c b/lib/lvleml.c index 3293893..a8f3f53 100644 --- a/lib/lvleml.c +++ b/lib/lvleml.c @@ -375,7 +375,7 @@ while (proceed==true) { proceed=doreset(contact,line); break; case c_starttls : //EHLO start encryptel link - switch (soc_starttls(contact->socptr,contact->peerip)) { + switch (soc_starttls(contact->socptr)) { case true : //link now in TLS crypted mode contact->tlsok=true; (void) signon(contact); diff --git a/lib/subrou.c b/lib/subrou.c index abd6889..3e8e934 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -21,7 +21,7 @@ //version definition #define VERSION "0.6" -#define RELEASE "42" +#define RELEASE "43" #define BRANCH "dvl" //Public variables diff --git a/lib/unieml.h b/lib/unieml.h index ebcf180..be4e9a6 100644 --- a/lib/unieml.h +++ b/lib/unieml.h @@ -19,6 +19,7 @@ //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 diff --git a/lib/unitls.c b/lib/unitls.c index 9aecd74..e677e71 100644 --- a/lib/unitls.c +++ b/lib/unitls.c @@ -212,12 +212,13 @@ return tls; */ /********************************************************/ /* */ -/* Procedure to set the serevr cerificate */ +/* Procedure to set the link certificate */ /* */ /********************************************************/ -static int set_server_certificate(SSL_CTX *ctx) +static int set_server_certificate(TLSTYP *tls) { +#define OPEP "unitls.c:set_link_certificate" int done; const char *certpub[3]; int phase; @@ -232,52 +233,59 @@ proceed=true; while (proceed==true) { switch (phase) { case 0 : //load CA trusted file - if (SSL_CTX_use_certificate_chain_file(ctx,certpub[0])!=1) { - (void) showtlserror((TLSTYP *)0,0,"Get trusted file"); + if (SSL_CTX_use_certificate_chain_file(tls->ctx,certpub[0])!=1) { + (void) showtlserror(tls,0,"No chain Certificate"); phase=999; //no need to go furter } break; case 1 : //loading default CA verify dir - if (SSL_CTX_set_default_verify_paths(ctx)==0) { - (void) showtlserror((TLSTYP *)0,0,"Get trusted file"); + if (SSL_CTX_set_default_verify_paths(tls->ctx)==0) { + (void) showtlserror(tls,0,"No CA certificate"); phase=999; //no need to go furter } break; case 2 : //set certificate - if (SSL_CTX_use_certificate_file(ctx,certpub[1],SSL_FILETYPE_PEM)!=1) { - (void) showtlserror((TLSTYP *)0,0,"Get local Certificate"); + if (SSL_CTX_use_certificate_file(tls->ctx,certpub[1],SSL_FILETYPE_PEM)!=1) { + (void) showtlserror(tls,0,"No local Certificate"); phase=999; //no need to go furter } break; case 3 : //set key - if (SSL_CTX_use_PrivateKey_file(ctx,certpub[2],SSL_FILETYPE_PEM)!=1) { - (void) showtlserror((TLSTYP *)0,0,"Get Private Key"); + if (SSL_CTX_use_PrivateKey_file(tls->ctx,certpub[2],SSL_FILETYPE_PEM)!=1) { + (void) showtlserror(tls,0,"No local Certificate"); phase=999; } break; case 4 : //verify management - (void) SSL_CTX_set_purpose(ctx,X509_PURPOSE_ANY); - (void) SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,(int(*)())0); - (void) SSL_CTX_set_verify_depth(ctx,5); - (void) SSL_CTX_set_options(ctx,SSL_OP_ALL); - if (SSL_CTX_set_cipher_list(ctx,SSL_CIPHER_LIST)==0) { - (void) showtlserror((TLSTYP *)0,0,"set cipher list"); + (void) SSL_CTX_set_purpose(tls->ctx,X509_PURPOSE_ANY); + (void) SSL_CTX_set_verify(tls->ctx,SSL_VERIFY_PEER,(int(*)())0); + (void) SSL_CTX_set_verify_depth(tls->ctx,5); + (void) SSL_CTX_set_options(tls->ctx,SSL_OP_ALL); + if (SSL_CTX_set_cipher_list(tls->ctx,SSL_CIPHER_LIST)==0) { + (void) showtlserror(tls,0,"No cipher list"); phase=999; } break; case 5 : //allowing partial write - (void) SSL_CTX_set_mode(ctx,SSL_MODE_ENABLE_PARTIAL_WRITE); + (void) SSL_CTX_set_mode(tls->ctx,SSL_MODE_ENABLE_PARTIAL_WRITE); break; case 6 : //everything fine done=true; break; default : //SAFE Guard + if (done==false) { + if (tls->ctx!=(SSL_CTX *)0) { + (void) SSL_CTX_free(tls->ctx); + tls->ctx=(SSL_CTX *)0; + } + } proceed=false; break; } phase++; } return done; +#undef OPEP } /* ^L @@ -393,7 +401,7 @@ while (proceed==true) { break; case 1 : //set certificate if (server==true) { - if (set_server_certificate(tls->ctx)==false) + if (set_server_certificate(tls)==false) phase=999; //trouble, trouble no need to go furter } break;