/********************************************************/
#include <openssl/err.h>
#include <openssl/x509v3.h>
+#include <poll.h>
#include <stdio.h>
#include "subrou.h"
/* 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;
detail="Unexpected error";
switch (sslerror) {
case 0 :
- (void) showerrorstack(msg);
+ (void) showerrorstack(info);
break;
default :
if (tls->ssl==(SSL *)0) //in case of trouble
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
}
*/
/********************************************************/
/* */
+/* 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 */
/* */
/********************************************************/
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) {
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");
*/
/********************************************************/
/* */
+/* 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 */