From edad5cf6e2b7604204d6246be5fe6b6dd8532fa0 Mon Sep 17 00:00:00 2001
From: erdgeist <>
Date: Fri, 27 Aug 2010 13:20:16 +0000
Subject: Tidy up ssl code, move all ssl related stuff to vchat-ssl and clean
 up some wrinkles in cert verification

---
 vchat-config.h   |   3 +-
 vchat-protocol.c |  42 +++++++---------
 vchat-ssl.c      | 144 +++++++++----------------------------------------------
 vchat-ssl.h      |   8 +---
 4 files changed, 41 insertions(+), 156 deletions(-)

diff --git a/vchat-config.h b/vchat-config.h
index 3511c68..4409107 100755
--- a/vchat-config.h
+++ b/vchat-config.h
@@ -23,7 +23,6 @@
 #endif
 
 /* configuration array with structure as defined in vchat.h */
-extern unsigned int ignssl;
 extern unsigned int usetime;
 extern unsigned int hscroll;
 
@@ -41,7 +40,7 @@ static volatile configoption configoptions[] = {
   {CF_LOGINSCRIPT, CO_STR, "loginscript","~/.vchat/loginscript", NULL,       { NULL }  },
   {CF_ENCODING,    CO_STR, "encoding",   NULL,                   NULL,       { .pstr = &encoding }},
   {CF_USESSL,      CO_INT, "usessl",     (char *) 1,             (char *)-1, { NULL }  },
-  {CF_IGNSSL,      CO_INT, "ignssl",     (char *) 0,             (char *)-1, { .pint = &ignssl }  },
+  {CF_IGNSSL,      CO_INT, "ignssl",     (char *) 0,             (char *)-1, { NULL }  },
   {CF_USECERT,     CO_INT, "usecert",    (char *) 1,             (char *)-1, { NULL }  },
   {CF_USETIME,     CO_INT, "usetime",    (char *) 1,             (char *)-1, { .pint = &usetime } },
   {CF_USETOPIC,    CO_INT, "usetopicbar",(char *) 1,             (char *)-1, { NULL }  },
diff --git a/vchat-protocol.c b/vchat-protocol.c
index 700f6c7..ef035fe 100755
--- a/vchat-protocol.c
+++ b/vchat-protocol.c
@@ -70,7 +70,6 @@ static void pmnotsent (char *message);
 /* status-variable from vchat-client.c
  * eventloop is done as long as this is true */
 extern int status;
-int ignssl = 0;
 char *encoding;
 
 static int connect_socket( char *server, char *port ) {
@@ -107,9 +106,6 @@ vcconnect (char *server, char *port)
   /* vchat connection x509 store */
   vc_x509store_t vc_store;
 
-  /* SSL-context */
-  SSL_CTX *sslctx = NULL;
-
   /* pointer to tilde-expanded certificate/keyfile-names */
   char *certfile = NULL, *keyfile = NULL;
 
@@ -164,10 +160,9 @@ vcconnect (char *server, char *port)
       vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt);
       vc_x509store_setkeyfile(&vc_store, tildex);
     }
-    vc_x509store_setignssl(&vc_store, getintoption(CF_IGNSSL));
 
     /* upgrade our plain BIO to ssl */
-    if( vc_connect_ssl( &server_conn, &vc_store, &sslctx ) )
+    if( vc_connect_ssl( &server_conn, &vc_store ) )
       BIO_free_all( server_conn );
   }
 
@@ -279,7 +274,7 @@ topicinfo (char *message)
 {
   char *channel = NULL, *topic = NULL;
   int tmpchan = 0;
-  
+
   /* search start of channel number */
   channel = strchr (message, ' ');
   channel++;
@@ -443,7 +438,7 @@ nickerr (char *message)
       setstroption(CF_NICK,NULL);
       /* get new nick via vchat-ui.c */
       nickprompt ();
-      
+
       /* form login message and send it to server */
       snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", nick, getstroption (CF_FROM), getintoption (CF_CHANNEL));
       networkoutput (tmpstr);
@@ -455,8 +450,7 @@ nickerr (char *message)
  *    vars: %s      - this users registered nick
  *          %s msg  - server message */
 static void
-login (char *message)
-{
+login (char *message) {
   char *msg = NULL;
 
   /* mutate message for output */
@@ -465,23 +459,19 @@ login (char *message)
   writecf (FS_SERV,&message[2]);
 
   /* we don't know our nick? */
-  if (!nick)
-    {
-      /* find message after nick */
-      msg = strchr (&message[4], ' ');
-      if (msg)
-	{
-          /* terminate string before message and copy nick */
-	  msg[0] = '\0';
-	  setstroption(CF_NICK,&message[4]);
-	}
-      else
-	{
-          /* no string in servers message (huh?), ask user for nick */
-	  nickprompt ();
-	}
+  if (!nick) {
+    /* find message after nick */
+    msg = strchr (&message[4], ' ');
+    if (msg) {
+      /* terminate string before message and copy nick */
+      msg[0] = '\0';
+      setstroption(CF_NICK,&message[4]);
+    } else {
+      /* no string in servers message (huh?), ask user for nick */
+      nickprompt ();
     }
-  
+  }
+
   /* form login message and send it to server */
   snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", nick, getstroption (CF_FROM), getintoption (CF_CHANNEL));
   networkoutput (tmpstr);
diff --git a/vchat-ssl.c b/vchat-ssl.c
index 1a1ff16..652ca09 100755
--- a/vchat-ssl.c
+++ b/vchat-ssl.c
@@ -27,13 +27,13 @@
 #include <openssl/x509v3.h>
 #include <openssl/conf.h>
 
+#include <readline/readline.h>
+
 #include "vchat.h"
 #include "vchat-ssl.h"
 
 char *vchat_ssl_version = "$Id$";
 
-static int ignore_ssl;
-
 #define VC_CTX_ERR_EXIT(se, cx) do { \
       snprintf(tmpstr, TMPSTRSIZE, "CREATE CTX: %s", \
             ERR_error_string (ERR_get_error (), NULL)); \
@@ -119,25 +119,16 @@ SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store )
    return(ctx);
 }
 
-int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store, SSL_CTX **ctx)
+int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store )
 {
-   BIO *ssl_conn = NULL;
-   int _ctx      = 0;
-
-   if(*ctx) {
-      CRYPTO_add( &((*ctx)->references), 1, CRYPTO_LOCK_SSL_CTX );
-      if( vc_store && vc_store != SSL_CTX_get_app_data(*ctx) ) {
-         SSL_CTX_set_cert_store(*ctx, vc_x509store_create(vc_store));
-         SSL_CTX_set_app_data(*ctx, vc_store);
-      }
-   } else {
-      *ctx = vc_create_sslctx(vc_store);
-      _ctx = 1;
-   }
+  BIO *ssl_conn = NULL;
+  SSL_CTX * ctx = vc_create_sslctx(vc_store);
+
+  if( !ctx )
+    return 1;
 
-  ssl_conn = BIO_new_ssl(*ctx, 1);
-  if(_ctx)
-    SSL_CTX_free(*ctx);
+  ssl_conn = BIO_new_ssl(ctx, 1);
+  SSL_CTX_free(ctx);
 
   if( ssl_conn ) {
     BIO_push( ssl_conn, *conn );
@@ -153,88 +144,6 @@ int vc_connect_ssl( BIO **conn, vc_x509store_t *vc_store, SSL_CTX **ctx)
   return 1;
 }
 
-int vc_verify_cert_hostname(X509 *cert, char *host)
-{
-   int i          = 0;
-   int j          = 0;
-   int n          = 0;
-   int extcount   = 0;
-   int ok         = 0;
-
-   X509_NAME            *subj    = NULL;
-   const char           *extstr  = NULL;
-   CONF_VALUE           *nval    = NULL;
-   const unsigned char  *data    = NULL;
-   X509_EXTENSION       *ext     = NULL;
-   X509V3_EXT_METHOD    *meth    = NULL;
-   STACK_OF(CONF_VALUE) *val     = NULL;
-
-   char name[256];
-   memset(&name, 0, sizeof(name));
-
-   if((extcount = X509_get_ext_count(cert)) > 0) {
-
-      for(i=0; !ok && i < extcount; i++) {
-
-         meth = NULL;
-
-         ext = X509_get_ext(cert, i);
-         extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
-
-         if(!strcasecmp(extstr, "subjectAltName")) {
-
-            if( !(meth = X509V3_EXT_get(ext)) )
-               break;
-
-            if( !(meth->d2i) )
-               break;
-
-            data = ext->value->data;
-
-            val = meth->i2v(meth, meth->d2i(0, &data, ext->value->length), 0);
-            for( j=0, n=sk_CONF_VALUE_num(val); j<n; j++ ) {
-               nval = sk_CONF_VALUE_value(val, j);
-               if( !strcasecmp(nval->name, "DNS") &&
-                     !strcasecmp(nval->value, host) ) {
-                  ok = 1;
-                  break;
-               }
-            }
-         }
-      }
-   }
-
-   if( !ok && (subj = X509_get_subject_name(cert)) &&
-         X509_NAME_get_text_by_NID(subj, NID_commonName,
-            name, sizeof(name)) > 0 ) {
-      name[sizeof(name)-1] = '\0';
-      if(!strcasecmp(name, host))
-         ok = 1;
-   }
-
-   //printf("[*] vc_verify_cert_hostname() return: %d\n", ok);
-   return(ok);
-}
-
-int vc_verify_cert(X509 *cert, vc_x509store_t *vc_store)
-{
-   int result           = -1;
-   X509_STORE  *store   = NULL;
-   X509_STORE_CTX *ctx  = NULL;
-
-   if( !(store = vc_x509store_create(vc_store)) )
-      return(result);
-
-   if( (ctx = X509_STORE_CTX_new()) != 0 ) {
-      if(X509_STORE_CTX_init(ctx, store, cert, 0) == 1)
-         result = (X509_verify_cert(ctx) == 1);
-      X509_STORE_CTX_free(ctx);
-   }
-
-   X509_STORE_free(store);
-   return(result);
-}
-
 #define VC_STORE_ERR_EXIT(s) do { \
       fprintf(stderr, "[E] SSL_STORE: %s\n", ERR_error_string (ERR_get_error (), NULL)); \
       if(s)  X509_STORE_free(s); \
@@ -300,7 +209,7 @@ int vc_verify_callback(int ok, X509_STORE_CTX *store)
 {
    if(!ok) {
       /* XXX handle action/abort */
-      if(!ignore_ssl)
+      if(!(ok=getintoption(CF_IGNSSL)))
          snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR] %s", 
                X509_verify_cert_error_string(store->error));
       else
@@ -308,7 +217,6 @@ int vc_verify_callback(int ok, X509_STORE_CTX *store)
                X509_verify_cert_error_string(store->error));
 
       writecf(FS_ERR, tmpstr);
-      ok = ignore_ssl;
    }
    return(ok);
 }
@@ -318,12 +226,6 @@ void vc_x509store_setflags(vc_x509store_t *store, int flags)
    store->flags |= flags;
 }
 
-void vc_x509store_setignssl(vc_x509store_t *store, int ignore)
-{
-   store->ignore_ssl |= ignore;
-   ignore_ssl = ignore;
-}
-
 void vc_x509store_clearflags(vc_x509store_t *store, int flags)
 {
    store->flags &= ~flags;
@@ -348,31 +250,31 @@ void vc_x509store_addcert(vc_x509store_t *store, X509 *cert)
 
 void vc_x509store_setcafile(vc_x509store_t *store, char *file) 
 {
-   if( store->cafile) free(store->cafile);
+   free(store->cafile);
    store->cafile = ( file ? strdup(file) : 0 );
 }
 
 void vc_x509store_setcapath(vc_x509store_t *store, char *path) 
 {
-   if( store->capath) free(store->capath);
+   free(store->capath);
    store->capath = ( path ? strdup(path) : 0 );
 }
 
 void vc_x509store_setcrlfile(vc_x509store_t *store, char *file) 
 {
-   if( store->crlfile) free(store->crlfile);
+   free(store->crlfile);
    store->crlfile = ( file ? strdup(file) : 0 );
 }
 
 void vc_x509store_setkeyfile(vc_x509store_t *store, char *file) 
 {
-   if( store->use_keyfile) free(store->use_keyfile);
+   free(store->use_keyfile);
    store->use_keyfile = ( file ? strdup(file) : 0 );
 }
 
 void vc_x509store_setcertfile(vc_x509store_t *store, char *file) 
 {
-   if( store->use_certfile) free(store->use_certfile);
+   free(store->use_certfile);
    store->use_certfile = ( file ? strdup(file) : 0 );
 }
 
@@ -391,19 +293,17 @@ void vc_init_x509store(vc_x509store_t *s)
    s->use_keyfile    = NULL;
    s->use_key        = NULL;
    s->flags          = 0;
-   s->ignore_ssl     = 0;
 }
 
 void vc_cleanup_x509store(vc_x509store_t *s)
 {
-   if(s->cafile)        free(s->cafile);
-   if(s->capath)        free(s->capath);
-   if(s->crlfile)       free(s->crlfile);
-   if(s->use_certfile)  free(s->use_certfile);
-   if(s->use_keyfile)   free(s->use_keyfile);
-   if(s->use_key)       free(s->use_key);
+   free(s->cafile);
+   free(s->capath);
+   free(s->crlfile);
+   free(s->use_certfile);
+   free(s->use_keyfile);
+   free(s->use_key);
    sk_X509_free(s->certs);
    sk_X509_free(s->crls);
    sk_X509_free(s->use_certs);
-   s->ignore_ssl     = 0;
 }
diff --git a/vchat-ssl.h b/vchat-ssl.h
index c745c97..baaa3c4 100755
--- a/vchat-ssl.h
+++ b/vchat-ssl.h
@@ -16,12 +16,11 @@ typedef struct {
    char                 *use_keyfile;
    EVP_PKEY             *use_key;
    int                  flags;
-   int                  ignore_ssl;
 } vc_x509store_t;
 
 /* prototypes */
 
-int  vc_connect_ssl(BIO **conn, vc_x509store_t *, SSL_CTX **);
+int  vc_connect_ssl(BIO **conn, vc_x509store_t * );
 SSL_CTX * vc_create_sslctx( vc_x509store_t *);
 void vc_init_x509store(vc_x509store_t *);
 void vc_cleanup_x509store(vc_x509store_t *);
@@ -34,15 +33,12 @@ void vc_x509store_addcert(vc_x509store_t *, X509 *);
 void vc_x509store_setcb(vc_x509store_t *, vc_x509verify_cb_t);
 void vc_x509store_set_pkeycb(vc_x509store_t *, vc_askpass_cb_t); 
 void vc_x509store_setflags(vc_x509store_t *, int);
-void vc_x509store_setignssl(vc_x509store_t *, int);
 void vc_x509store_clearflags(vc_x509store_t *, int);
-int vc_verify_cert(X509 *, vc_x509store_t *);
-int vc_verify_cert_hostname(X509 *, char *);
 int vc_verify_callback(int, X509_STORE_CTX *);
 X509_STORE * vc_x509store_create(vc_x509store_t *);
 
 #define VC_X509S_NODEF_CAFILE                      0x01
-#define VC_X509S_NODEF_CAPATH                      0x02 
+#define VC_X509S_NODEF_CAPATH                      0x02
 #define VC_X509S_USE_CERTIFICATE                   0x04
 #define VC_X509S_SSL_VERIFY_NONE                   0x10
 #define VC_X509S_SSL_VERIFY_PEER                   0x20
-- 
cgit v1.2.3