From cd83c5c055d435395f32526b643ffe7a3605778d Mon Sep 17 00:00:00 2001 From: "Jean-Marc Pigeon (Delson)" Date: Tue, 6 Aug 2024 09:59:34 -0400 Subject: [PATCH] Working to have good SSL code --- lib/devsoc.c | 14 ++-- lib/subrou.c | 2 +- lib/unissl.c | 208 +++++++++++++++++++++++++++++++++++---------------- lib/unissl.h | 17 +++-- 4 files changed, 161 insertions(+), 80 deletions(-) diff --git a/lib/devsoc.c b/lib/devsoc.c index a8baf57..061178a 100644 --- a/lib/devsoc.c +++ b/lib/devsoc.c @@ -34,8 +34,7 @@ typedef struct { PROTYP proto; //Connexion protocol type int handle; //connexion handle - SSL *ssl; //ssl channel - SSL_CTX *ctx; //encryption context + SSLTYP *ssl; //full SSL channel int maxcarin; //absolute number within carin char *EOL; //End of line marker int carin; //number of char within incpt; @@ -703,12 +702,11 @@ while (proceed==true) { phase=999; break; case pro_smtps : //set secure socket - newsoc->ctx=ssl_getctx(true); //ssl in server mode - newsoc->ssl=ssl_setsocket(newsoc->handle,newsoc->ctx); - if (newsoc->ssl!=(SSL *)0) - (void) SSL_set_accept_state(newsoc->ssl); - else + if ((newsoc->ssl=ssl_openssl(newsoc->handle,true))==(SSLTYP *)0) { newsoc=soc_release(newsoc); //trouble trouble + break; + } + (void) ssl_check_peer(newsoc->ssl); break; default : //undefined socket type??? (void) rou_alert(0,"%s, Undefined socket protocol='%d' (Bug?)", @@ -835,7 +833,7 @@ while (proceed==true) { } break; case 3 : //freeing the SSL contaxt - soc->ctx=ssl_releasectx(soc->ctx); + soc->ssl=ssl_closessl(soc->ssl); break; case 4 : //fee memory used by socket soc=freesocket(soc); diff --git a/lib/subrou.c b/lib/subrou.c index fb3543a..8e79d90 100644 --- a/lib/subrou.c +++ b/lib/subrou.c @@ -20,7 +20,7 @@ //version definition #define VERSION "0.3" -#define RELEASE "25" +#define RELEASE "26" //Public variables PUBLIC int debug=0; //debug level diff --git a/lib/unissl.c b/lib/unissl.c index 744530a..208dde0 100644 --- a/lib/unissl.c +++ b/lib/unissl.c @@ -18,78 +18,157 @@ static _Bool modopen; //module open/close status */ /********************************************************/ /* */ -/* Procedure to realease all SSL contaxt */ +/* Procedure to report display ALL ssl error queue */ /* */ /********************************************************/ -PUBLIC SSL_CTX *ssl_releasectx(SSL_CTX *ctx) +static void showerrorstack(char *msg) { -(void) SSL_CTX_free(ctx); -return (SSL_CTX *)0; +int error; + +(void) rou_alert(0,"SSL error queue caused by <%s>",msg); +while ((error=ERR_get_error())!=0) { + (void) rou_alert(0,"\t%s",ERR_error_string(error,(char *)0)); + } } /* ^L */ /********************************************************/ /* */ -/* Procedure to establish a working SSL context */ -/* Return SLL context or a NULL pointer */ +/* Procedure to report display all erro queue */ +/* after afyer an ssl action. Return true if no */ +/* fatal error found. */ /* */ /********************************************************/ -PUBLIC SSL_CTX *ssl_getctx(_Bool server_mode) +static _Bool showsslerror(SSLTYP *ssl,int sslerror,char *msg) { -#define OPEP "unissl.c:ssl_getctx" +#define OPEP "unissl.c:showsslerror" +_Bool good; -SSL_CTX *ctx; -const SSL_METHOD *(*tls_methode)(); +good=true; +if (sslerror<=0) { + char *detail; + int code; + + good=false; + detail="Unexpected error"; + switch (sslerror) { + case 0 : + (void) showerrorstack(msg); + break; + default : + if (ssl->ssl==(SSL *)0) //in case of trouble + (void) rou_core_dump("%s Unexpected NULL SSL (Bug?)",OPEP); + code=SSL_get_error(ssl->ssl,sslerror); + switch (code) { + case SSL_ERROR_ZERO_RETURN : + detail="zero return"; + break; + case SSL_ERROR_WANT_READ : + detail="want read"; + break; + case SSL_ERROR_WANT_WRITE : + detail="want write"; + break; + case SSL_ERROR_WANT_CONNECT : + detail="want connect"; + break; + case SSL_ERROR_WANT_X509_LOOKUP : + detail="want X509 lookup"; + break; + case SSL_ERROR_SYSCALL : + if (ERR_get_error()==0) + detail="Premature EOF"; + else + detail="syscall error"; + break; + case SSL_ERROR_SSL : + detail=ERR_error_string(ERR_get_error(),(char *)0); + break; + default : + (void) rou_alert(0,"%s, caused by <%s> Unexpected ssl error='%d'", + OPEP,msg,code); + detail=(char *)0; + break; + } + break; + } + if (detail!=(char *)0) + (void) rou_alert(4,"%s, caused by <%s>, error=<%s>",OPEP,msg,detail); + } +return good; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to open an SSL channel */ +/* */ +/********************************************************/ +static SSLTYP *freessl(SSLTYP *ssl) + +{ +if (ssl!=(SSLTYP *)0) { + if (ssl->ctx!=(SSL_CTX *)0) + (void) SSL_CTX_free(ssl->ctx); + (void) free(ssl); + ssl=(SSLTYP *)0; + } +return ssl; +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to open an SSL channel */ +/* */ +/********************************************************/ +PUBLIC SSLTYP *ssl_openssl(int handle,_Bool server) + +{ +#define OPEP "unissl.c:ssl_openssl" + +SSLTYP *ssl; const char *certpub[2]; +const SSL_METHOD *(*tls_methode)(); int phase; _Bool proceed; -ctx=(SSL_CTX *)0; +ssl=(SSLTYP *)0; +certpub[0]="./kleenex/cert.pem"; //JMPDBG test +certpub[1]="./kleenex/key.pem"; //JMPDBG test tls_methode=TLS_client_method; -if (server_mode==true) +if (server==true) tls_methode=TLS_server_method; phase=0; proceed=true; while (proceed==true) { switch (phase) { - case 0 : //Setting inital context - if ((ctx=SSL_CTX_new(tls_methode()))==(SSL_CTX *)0) { - char reason[200]; - - (void) ERR_error_string(ERR_get_error(),reason); - (void) rou_core_dump("%s, Unable to set the SSL context err=<%s> (system?)", - OPEP,reason); - phase=999; //Useless, cire dump never return + case 0 : //prepare the structure first; + ssl=(SSLTYP *)calloc(1,sizeof(SSLTYP)); + ssl->server=server; + if ((ssl->ctx=SSL_CTX_new(tls_methode()))==(SSL_CTX *)0) { + (void) showsslerror(ssl,0,"Get CTX"); + ssl=freessl(ssl); + phase=999; //no need to go furter } break; - case 1 : //getting certificat name - certpub[0]="./kleenex/cert.pem"; //JMPDBG test - certpub[1]="./kleenex/key.pem"; //JMPDBG test - break; - case 2 : //set certificate - if (SSL_CTX_use_certificate_file(ctx,certpub[0],SSL_FILETYPE_PEM)!=1) { - char reason[200]; - - (void) ERR_error_string(ERR_get_error(),reason); - (void) rou_alert(0,"Unable to use certificate <%s> (error=<%s>)", - certpub[0],reason); - (void) SSL_CTX_free(ctx); - ctx=(SSL_CTX *)0; - phase=999; + case 1 : //set certificate + if (SSL_CTX_use_certificate_file(ssl->ctx,certpub[0],SSL_FILETYPE_PEM)!=1) { + (void) showsslerror(ssl,0,"Get local Certificate"); + ssl=freessl(ssl); + phase=999; //no need to go furter } break; - case 3 : //set key - if (SSL_CTX_use_PrivateKey_file(ctx,certpub[1],SSL_FILETYPE_PEM)!=1) { - char reason[200]; - - (void) ERR_error_string(ERR_get_error(),reason); - (void) rou_alert(0,"Unable to use certificate key <%s> (error=<%s>)", - certpub[0],reason); - (void) SSL_CTX_free(ctx); - ctx=(SSL_CTX *)0; + case 2 : //set key + if (SSL_CTX_use_PrivateKey_file(ssl->ctx,certpub[1],SSL_FILETYPE_PEM)!=1) { + (void) showsslerror(ssl,0,"Get Private Key"); + ssl=freessl(ssl); phase=999; } break; @@ -99,7 +178,7 @@ while (proceed==true) { } phase++; } -return ctx; +return ssl; #undef OPEP } /* @@ -107,12 +186,25 @@ return ctx; */ /********************************************************/ /* */ +/* Procedure to close an SSL channel */ +/* */ +/********************************************************/ +PUBLIC SSLTYP *ssl_closessl(SSLTYP *ssl) + +{ +return ssl; +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to check if remote certificat is a */ /* valide one. */ /* return -1if trouble, 0 otherwise */ /* */ /********************************************************/ -PUBLIC int ssl_check_peer(SSL *ssl) +PUBLIC int ssl_check_peer(SSLTYP *ssl) { #define OPEP "unissl.c:ssl_check_peer" @@ -130,27 +222,19 @@ while (proceed==true) { (void) printf("JMPDBG phase='%d', check peer\n",phase); switch (phase) { case 0 : //check SSL - if (ssl==(SSL *)0) { + if ((ssl==(SSLTYP *)0)||(ssl->ssl=(SSL *)0)) { phase=999; //trouble trouble (Bug?) } break; case 1 : //get peer - if ((peer=SSL_get_peer_certificate(ssl))==(X509 *)0) { - char reason[200]; - - (void) ERR_error_string(ERR_get_error(),reason); - (void) rou_alert(2,"%s Unable to get peer certificate (error=<%s>)", - OPEP,reason); + if ((peer=SSL_get_peer_certificate(ssl->ssl))==(X509 *)0) { + (void) showsslerror(ssl,0,"Get peer Certificate"); phase=999; //trouble trouble } break; case 2 : //is peer valid? - if (SSL_get_verify_result(ssl)!=X509_V_OK) { - char reason[200]; - - (void) ERR_error_string(ERR_get_error(),reason); - (void) rou_alert(2,"%s Unable to verify certificate (error=<%s>)", - OPEP,reason); + if (SSL_get_verify_result(ssl->ssl)!=X509_V_OK) { + (void) showsslerror(ssl,0,"Get Verify peer Certificate"); phase=999; //trouble trouble } (void) X509_free(peer); @@ -213,14 +297,6 @@ while (proceed==true) { phase=999; } break; - case 2 : //verifying SSL channel - if (ssl_check_peer(ssl)<0) { - (void) rou_alert(0,"%s Unable to check peer certificat",OPEP); - (void) free(ssl); - ssl=(SSL *)0; - phase=999; - } - break; default : //SAFE guard proceed=false; break; diff --git a/lib/unissl.h b/lib/unissl.h index 3b38e10..60a07cb 100644 --- a/lib/unissl.h +++ b/lib/unissl.h @@ -10,14 +10,21 @@ #include #include -//releasing current SSL context; -extern SSL_CTX *ssl_releasectx(SSL_CTX *ctx); +typedef struct { + _Bool server; //SSL server/client mode + SSL_CTX *ctx; //SSL context + SSL *ssl; //SSL link + BIO *bio; //SSL Basic input output + }SSLTYP; -//establishing SSL working context -extern SSL_CTX *ssl_getctx(_Bool server_mode); +//procedure to open an ssl channel +extern SSLTYP *ssl_openssl(int handle,_Bool server); + +//procedure to close an ssl channel +extern SSLTYP *ssl_closessl(SSLTYP *ssl); //check peer certificat -extern int ssl_check_peer(SSL *ssl); +extern int ssl_check_peer(SSLTYP *ssl); //set socket as an ssl socket extern SSL *ssl_setsocket(int handle,SSL_CTX *ctx); -- 2.47.3