/* exchange. */
/* */
/********************************************************/
+#include <openssl/asn1.h>
+#include <openssl/bn.h>
#include <openssl/err.h>
+#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include <sys/socket.h>
+#include <netdb.h>
#include <poll.h>
#include <stdio.h>
#include <unistd.h>
*/
/********************************************************/
/* */
-/* Procedure to wait for character on the TLS */
-/* tls channel. */
+/* Procedure to verify remote certificate */
/* */
/********************************************************/
-static _Bool dowait(TLSTYP *tls,TIMESPEC *attend)
+static int verify(TLSTYP *tls)
{
-#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;
+#define OPEP "unitls.c:verify"
X509 *peer;
-TIMESPEC attend;
-int done;
+int ok;
+int phase;
+_Bool proceed;
-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);
- (void) printf("after SSL_accept status='%d'\n",status);
- 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);
+ok=false;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //get remote certificate
+ if ((peer=SSL_get0_peer_certificate(tls->ssl))==(X509 *)0) {
+ (void) rou_alert(0,"%s, Unable to get certificate from remote [%s]",
+ OPEP,tls->peerip);
+ phase=999;
}
break;
- case SSL_ERROR_WANT_READ :
- done=dowait(tls,&attend);
+ case 1 : //displaying certificate
+ if (peer!=(X509 *)0) { //always
+ char *line;
+
+ line=X509_NAME_oneline(X509_get_subject_name(peer),0,0);
+ (void) rou_alert(2,"Certificate subject=<%s>",line);
+ (void) free(line);
+ line=X509_NAME_oneline(X509_get_issuer_name(peer),0,0);
+ (void) rou_alert(2,"Certificate issuer=<%s>",line);
+ (void) free(line);
+ }
break;
- case SSL_ERROR_WANT_WRITE :
- done=false;
+ case 3 : //verifying certificate
+ if (SSL_get_verify_result(tls->ssl)!=X509_V_OK) {
+ (void) rou_alert(0,"%s, Remote certificate NOT OK",OPEP);
+ phase=999;
+ }
+ (void) X509_free(peer);
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;
+ case 2 : //everything is fine
+ ok=true;
break;
- default :
- (void) showtlserror(tls,status,"%s SSL_accept fatal error (sslerr='%d')",
- OPEP,sslerr);
- status=-1;
+ default : //SAFE Guard
+ proceed=false;
break;
}
+ phase++;
}
-return status;
+return ok;
#undef OPEP
}
/*
{
if (tls!=(TLSTYP *)0) {
+ tls->peerip=rou_freestr(tls->peerip);
+ tls->locip=rou_freestr(tls->locip);
+ tls->locport=rou_freestr(tls->locport);
if (tls->ssl!=(SSL *)0)
(void) free(tls->ssl);
if (tls->ctx!=(SSL_CTX *)0)
break;
case 4 : //verify management
(void) SSL_CTX_set_purpose(ctx,X509_PURPOSE_ANY);
- (void) SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,(int(*)())0);
+ (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) {
*/
/********************************************************/
/* */
+/* Procedure to get peerip, local name and port */
+/* */
+/********************************************************/
+static void getnames(TLSTYP *tls)
+
+{
+#define OPEP "unitls.c:getnames"
+
+socklen_t taille;
+struct sockaddr connip;
+char host[NI_MAXHOST];
+char serv[NI_MAXSERV];
+int phase;
+_Bool proceed;
+
+taille=(socklen_t)(sizeof(connip));
+(void) strcpy(host,"");
+(void) strcpy(serv,"");
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //Checking if everithing is fine
+ if (tls==(TLSTYP *)0) {
+ (void) rou_alert(0,"%s, TLS is NULL (bug?)",OPEP);
+ }
+ break;
+ case 1 : //Getting local name and service
+ (void) strcpy(host,"lochost");
+ (void) strcpy(serv,"locserv");
+ if (getsockname(tls->handle,&connip,&taille)==0) {
+ int mode;
+ int status;
+
+ mode=NI_NAMEREQD|NI_NUMERICSERV;
+ status=getnameinfo(&connip,taille,host,sizeof(host),serv,sizeof(serv),mode);
+ if (status!=0) {
+ (void) strcpy(host,"loc-Unknown");
+ (void) strcpy(serv,"loc-Unknown");
+ }
+ }
+ tls->locip=strdup(host);
+ tls->locport=strdup(serv);
+ break;
+ case 2 : //Getting peer name and service
+ (void) strcpy(host,"remhost");
+ (void) strcpy(serv,"remserv");
+ if (getpeername(tls->handle,&connip,&taille)==0) {
+ int mode;
+ int status;
+
+ mode=NI_NUMERICHOST|NI_NUMERICSERV;
+ status=getnameinfo(&connip,taille,host,sizeof(host),serv,sizeof(serv),mode);
+ if (status!=0) {
+ (void) strcpy(host,"peer-Unknown");
+ (void) strcpy(serv,"peer-Unknown");
+ }
+ tls->peerip=strdup(host);
+ }
+ break;
+ default : //SAFE Guard
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+#undef OPEP
+}
+/*
+^L
+*/
+/********************************************************/
+/* */
/* Procedure to open an SSL channel */
/* */
/********************************************************/
tls=(TLSTYP *)calloc(1,sizeof(TLSTYP));
tls->handle=handle;
tls->server=server;
+ (void) getnames(tls);
(void) SSL_library_init();
(void) SSL_load_error_strings();
(void) ERR_clear_error();
(void) SSL_set_accept_state(tls->ssl);
break;
}
+ break;
+ case 4 : //Setting the TLS channel actif
+ (void) verify(tls);
ready=true;
break;
default : //SAFE guard
*/
/********************************************************/
/* */
-/* 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 */