From 12aa166098388b408fcddc103a7ff53f90df9ca2 Mon Sep 17 00:00:00 2001 From: "Jean-Marc Pigeon (Delson)" Date: Wed, 7 Aug 2024 06:41:16 -0400 Subject: [PATCH] Working out the TLS contact sequence --- lib/gestcp.c | 3 + lib/subrou.c | 2 +- lib/unitls.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++-- lib/unitls.h | 5 ++ 4 files changed, 168 insertions(+), 5 deletions(-) diff --git a/lib/gestcp.c b/lib/gestcp.c index a6ca573..bd29a32 100644 --- a/lib/gestcp.c +++ b/lib/gestcp.c @@ -79,6 +79,9 @@ while (proceed==true) { case 2 : //waiting for new character presence switch (soc_waitforchar(contact->socptr,attend)) { case -1 : //trouble? signal? + if ((hangup==true)||(reload==true)) + phase=999; //we got a real signal + break; //no need to read line case 0 : //normal time out break; //no need to read line default : //char available diff --git a/lib/subrou.c b/lib/subrou.c index 868e65f..24f8c8a 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -20,7 +20,7 @@ //version definition #define VERSION "0.3" -#define RELEASE "28" +#define RELEASE "29" //Public variables PUBLIC int debug=0; //debug level diff --git a/lib/unitls.c b/lib/unitls.c index 211de2f..067305a 100644 --- a/lib/unitls.c +++ b/lib/unitls.c @@ -7,6 +7,7 @@ /********************************************************/ #include #include +#include #include #include "subrou.h" @@ -45,13 +46,17 @@ while ((error=ERR_get_error())!=0) { /* fatal error found. */ /* */ /********************************************************/ -static _Bool showtlserror(TLSTYP *tls,int sslerror,char *msg) +static _Bool showtlserror(TLSTYP *tls,int sslerror,char *msg,...) { #define OPEP "unitls.c:showtlserror" _Bool good; +va_list args; +char info[300]; good=true; +va_start(args,msg); +(void) vsnprintf(info,sizeof(info),msg,args); if (sslerror<=0) { char *detail; int code; @@ -60,7 +65,7 @@ if (sslerror<=0) { detail="Unexpected error"; switch (sslerror) { case 0 : - (void) showerrorstack(msg); + (void) showerrorstack(info); break; default : if (tls->ssl==(SSL *)0) //in case of trouble @@ -94,15 +99,16 @@ if (sslerror<=0) { break; default : (void) rou_alert(0,"%s, caused by <%s> Unexpected ssl error='%d'", - OPEP,msg,code); + OPEP,info,code); detail=(char *)0; break; } break; } if (detail!=(char *)0) - (void) rou_alert(4,"%s, caused by <%s>, error=<%s>",OPEP,msg,detail); + (void) rou_alert(4,"%s, caused by <%s>, error=<%s>",OPEP,info,detail); } +va_end(args); return good; #undef OPEP } @@ -111,6 +117,106 @@ return good; */ /********************************************************/ /* */ +/* Procedure to wait for character on the TLS */ +/* tls channel. */ +/* */ +/********************************************************/ +static _Bool dowait(TLSTYP *tls,TIMESPEC *attend) + +{ +#define OPEP "unitls.c:dowait" + +_Bool done; +struct pollfd polling[1]; + +done=false; +polling[0].events=POLLIN|POLLPRI; +polling[0].revents=(short)0; +polling[0].fd=SSL_get_fd(tls->ssl); +switch (ppoll(polling,1,attend,(sigset_t *)0)) { + case -1 : + switch(errno) { //received a signal, lets see...* + case EINTR: //Yes could be a TERM/HANGUP signal + break; + default : //real problem + (void) rou_alert(0,"%s poll error '%s'",OPEP,strerror(errno)); + done=true; //No need to wait any more + break; + } + break; + case 0 : //standard timeout + done=true; + break; + default : + break; + } +return done; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to "accept" link on an SSL channel */ +/* */ +/********************************************************/ +static int doaccept(TLSTYP *tls) + +{ +#define OPEP "unitls.c:doaccept" +int status; +X509 *peer; +TIMESPEC attend; +int done; + +status=-1; +peer=(X509 *)0; +attend.tv_sec=30; //waiting 30 second to have a full SSL +attend.tv_nsec=0; +done=false; +while (done==false) { + int sslerr; + + status=SSL_accept(tls->ssl); + done=true; + switch (sslerr=SSL_get_error(tls->ssl,status)) { + case SSL_ERROR_NONE : + status=0; + if ((peer=SSL_get_peer_certificate(tls->ssl))!=(X509 *)0) { + if (SSL_get_verify_result(tls->ssl)!=X509_V_OK) + status=-1; + (void) X509_free(peer); + } + break; + case SSL_ERROR_WANT_READ : + done=dowait(tls,&attend); + break; + case SSL_ERROR_WANT_WRITE : + done=false; + break; + case SSL_ERROR_SYSCALL : //EOF received? + if (ERR_get_error()==0) + tls->goteof=true; //EOF received! + else + (void) showtlserror(tls,status,"%s SSL_SYSCALL pbs",OPEP); + status=-1; + break; + default : + (void) showtlserror(tls,status,"%s SSL_accept fatal error (sslerr='%d')", + OPEP,sslerr); + status=-1; + break; + } + } +return status; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to open an SSL channel */ /* */ /********************************************************/ @@ -148,6 +254,7 @@ certpub[2]="./kleenex/key.pem"; //JMPDBG test phase=0; proceed=true; while (proceed==true) { + (void) fprintf(stderr,"JMPDBG set_server_certificate phase='%d'\n",phase); switch (phase) { case 0 : //load CA trusted file if (SSL_CTX_use_certificate_chain_file(ctx,certpub[0])!=1) { @@ -222,9 +329,11 @@ if (server==true) phase=0; proceed=true; while (proceed==true) { + (void) fprintf(stderr,"JMPDBG tlsopentls phase='%d'\n",phase); switch (phase) { case 0 : //prepare the structure first; tls=(TLSTYP *)calloc(1,sizeof(TLSTYP)); + tls->handle=handle; tls->server=server; if ((tls->ctx=SSL_CTX_new(tls_methode()))==(SSL_CTX *)0) { (void) showtlserror(tls,0,"Get CTX"); @@ -312,6 +421,52 @@ return got; */ /********************************************************/ /* */ +/* Procedure to accept a TLS connection from peer. */ +/* */ +/********************************************************/ +PUBLIC int tls_accept(TLSTYP *tls) + +{ +#define OPEP "unitls.c:tls_accept" +int status; +int phase; +int proceed; + +status=-1; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //checking TLS + if (tls==(TLSTYP *)0) { + (void) rou_core_dump("%s, TLS pointer is NULL! (bug?)",OPEP); + phase=000; //trouble trouble + } + break; + case 1 : //checking TLS + if ((tls->bio=BIO_new_fd(tls->handle,BIO_NOCLOSE))==(BIO *)0) { + (void) rou_core_dump("%s, Unable to get the BIO (error=<%s>)", + OPEP,strerror(errno)); + } + break; + case 2 : //set BIO properly + (void) SSL_set_bio(tls->ssl,tls->bio,tls->bio); + status=doaccept(tls); + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return status; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to check if remote certificat is a */ /* valide one. */ /* return -1if trouble, 0 otherwise */ diff --git a/lib/unitls.h b/lib/unitls.h index aeb1d1a..f462901 100644 --- a/lib/unitls.h +++ b/lib/unitls.h @@ -13,6 +13,8 @@ typedef struct { _Bool server; //SSL server/client mode + _Bool goteof; //SSL End Of File + int handle; //device handle SSL_CTX *ctx; //SSL context SSL *ssl; //SSL link BIO *bio; //SSL Basic input output @@ -30,6 +32,9 @@ extern int tls_write(TLSTYP *tls,char *buffer,int tosend); //read from the SSL channel extern int tls_read(TLSTYP *tls,char *buffer,int maxread); +//accept a TLS connection +extern int tls_accept(TLSTYP *tls); + //check peer certificat extern int tls_check_peer(TLSTYP *tls); -- 2.47.3