[pan2/testing: 239/279] moved blacklist for server connections from nntp-pool to certstore (servers are blacklisted on faile



commit 2ad72e3180cf9d887eefbf6e7d66bca70eea3b25
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Wed Nov 9 21:49:03 2011 +0100

    moved blacklist for server connections from nntp-pool to certstore
    (servers are blacklisted on failed connection attempts and whitelisted
    on succesful addition of a valid SSL certificate)

 pan/gui/gui.cc                   |    5 +-
 pan/tasks/cert-store.cc          |  183 +++++++++++++++++++++++++++++++++-----
 pan/tasks/cert-store.h           |   16 +++-
 pan/tasks/nntp-pool.cc           |   14 ++--
 pan/tasks/socket-impl-openssl.cc |   21 ++++-
 pan/tasks/socket-impl-openssl.h  |    4 +
 6 files changed, 210 insertions(+), 33 deletions(-)
---
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index 1749ac7..1838ee3 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -1307,6 +1307,7 @@ bool GUI::deletion_confirmation_dialog()
 bool GUI :: confirm_accept_new_cert_dialog(GtkWindow * parent, X509* cert, const Quark& server)
 {
   bool ret(false);
+
   char buf[4096];
   CertStore::pretty_print_x509(buf,sizeof(buf), server, cert);
   gdk_threads_enter();
@@ -2103,7 +2104,7 @@ GUI :: on_verify_cert_failed(X509* cert, std::string server, int nr)
 
 void
 GUI :: on_valid_cert_added (X509* cert, std::string server)
-{
+{}
+
 
-}
 #endif
diff --git a/pan/tasks/cert-store.cc b/pan/tasks/cert-store.cc
index dbb33aa..d911a7c 100644
--- a/pan/tasks/cert-store.cc
+++ b/pan/tasks/cert-store.cc
@@ -60,14 +60,11 @@ namespace pan
 
   int
   verify_callback(int ok, X509_STORE_CTX *store)
-//  verify_callback(X509_STORE_CTX *store, void* args)
   {
 
     SSL * ssl = (SSL*)X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
     mydata_t* mydata = (mydata_t*)SSL_get_ex_data(ssl, SSL_get_fd(ssl));
 
-//    CertStore * me = (CertStore*)args;
-
     if (!ok)
     {
       if (mydata->ignore_all==1) return 1;
@@ -76,20 +73,16 @@ namespace pan
       int depth = X509_STORE_CTX_get_error_depth(store);
       int err = X509_STORE_CTX_get_error(store);
 
-      if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)
+      /* accept user-override on self-signed certificates */
+      if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
+          err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
         mydata->cs->verify_failed(cert, mydata->server, err);
     }
     return ok;
 
-//      SSL_CTX_set_verify(me->get_ctx(), SSL_VERIFY_PEER, store->verify_cb);
-//
-//      int ok =
-//
-//  }
-
 }
 
-void
+int
 CertStore :: get_all_certs_from_disk(std::set<X509*>& setme)
 {
   char filename[PATH_MAX];
@@ -122,7 +115,7 @@ CertStore :: get_all_certs_from_disk(std::set<X509*>& setme)
   }
   g_dir_close (dir);
 
-  if (cnt != 0) Log::add_info_va(_("Succesfully added %d SSL PEM certificate(s) to Certificate Store."), cnt);
+  return cnt;
 }
 
 void
@@ -133,11 +126,12 @@ CertStore :: init_me()
   _store = SSL_CTX_get_cert_store(_ctx);
 
   std::set<X509*> certs;
+  int r(0);
   get_all_certs_from_disk (certs);
   foreach_const (std::set<X509*>, certs, it)
-    X509_STORE_add_cert(_store, *it);
-//  SSL_CTX_set_cert_verify_callback(_ctx, verify_callback, (void*)this);
-  SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_callback);
+    if (X509_STORE_add_cert(_store, *it) != 0) ++r;
+  if (r != 0) Log::add_info_va(_("Succesfully added %d SSL PEM certificate(s) to Certificate Store."), r);
+  SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback);
 
 }
 
@@ -229,7 +223,7 @@ namespace
     unsigned int n;
 
     if (! X509_digest(cert, EVP_md5(), md, &n))
-			res += _("Not available.");
+			res = _("Not available.");
 		else {
 			char hex[] = "0123456789ABCDEF";
 			char fp[EVP_MAX_MD_SIZE*3];
@@ -240,26 +234,173 @@ namespace
 					fp[i*3+1] = hex[(md[i] >> 0) & 0xF];
 					fp[i*3+2] = i == n - 1 ? '\0' : ':';
 				}
-				res += fp;
+				res = fp;
 			}
 		}
     return res;
   }
 
+  std::string
+  get_x509_enddate(X509* cert)
+  {
+    std::string res;
+
+    return res;
+  }
+
+}
+
+time_t
+getTimeFromASN1(const ASN1_TIME * aTime)
+{
+  time_t lResult = 0;
+
+
+  char lBuffer[24];
+  char * pBuffer = lBuffer;
+
+
+  size_t lTimeLength = aTime->length;
+  char * pString = (char *)aTime->data;
+
+
+  if (aTime->type == V_ASN1_UTCTIME)
+  {
+    if ((lTimeLength < 11) || (lTimeLength > 17))
+    {
+      return 0;
+    }
+
+
+    memcpy(pBuffer, pString, 10);
+    pBuffer += 10;
+    pString += 10;
+  }
+  else
+  {
+    if (lTimeLength < 13)
+    {
+      return 0;
+    }
+
+
+    memcpy(pBuffer, pString, 12);
+    pBuffer += 12;
+    pString += 12;
+  }
+
+
+  if ((*pString == 'Z') || (*pString == '-') || (*pString == '+'))
+  {
+    *(pBuffer++) = '0';
+    *(pBuffer++) = '0';
+  }
+  else
+  {
+    *(pBuffer++) = *(pString++);
+    *(pBuffer++) = *(pString++);
+    // Skip any fractional seconds...
+    if (*pString == '.')
+    {
+      pString++;
+      while ((*pString >= '0') && (*pString <= '9'))
+      {
+        pString++;
+      }
+    }
+  }
+
+
+  *(pBuffer++) = 'Z';
+  *(pBuffer++) = '\0';
+
+
+  time_t lSecondsFromUCT;
+  if (*pString == 'Z')
+  {
+    lSecondsFromUCT = 0;
+  }
+  else
+  {
+    if ((*pString != '+') && (pString[5] != '-'))
+    {
+      return 0;
+    }
+
+
+    lSecondsFromUCT = ((pString[1]-'0') * 10 + (pString[2]-'0')) * 60;
+    lSecondsFromUCT += (pString[3]-'0') * 10 + (pString[4]-'0');
+    if (*pString == '-')
+    {
+      lSecondsFromUCT = -lSecondsFromUCT;
+    }
+  }
+
+
+  tm lTime;
+  lTime.tm_sec  = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
+  lTime.tm_min  = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
+  lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
+  lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0');
+  lTime.tm_mon  = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1;
+  lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0');
+  if (lTime.tm_year < 50)
+  {
+    lTime.tm_year += 100; // RFC 2459
+  }
+  lTime.tm_wday = 0;
+  lTime.tm_yday = 0;
+  lTime.tm_isdst = 0;  // No DST adjustment requested
+
+  lResult = mktime(&lTime);
+
+  if ((time_t)-1 != lResult)
+  {
+    if (0 != lTime.tm_isdst)
+      lResult -= 3600; // mktime may adjust for DST (OS dependent)
+    lResult += lSecondsFromUCT;
+  }
+  else
+    lResult = 0;
+
+  return lResult;
 }
 
 void
 CertStore :: pretty_print_x509 (char* buf, size_t size, const Quark& server, X509* cert)
 {
   if (!cert) return;
+//  char buffer[4096];
+//  int len;
+//  int i = X509_get_ext_by_NID(cert, NID_invalidity_date, -1);
+//  BIO *bio = BIO_new(BIO_s_mem());
+//  X509_EXTENSION * ex = X509_get_ext( cert,i);
+//  std::cerr<<"pretty "<<i<<" "<<ex<<" "<<bio<<std::endl;
+//  if(!X509V3_EXT_print(bio, ex, 0, 0))
+//    M_ASN1_OCTET_STRING_print(bio,ex->value);
+//  len = BIO_read(bio, buffer, 4096);
+//  buffer[len] = '\0';
+//  BIO_free(bio);
+
+  time_t t = getTimeFromASN1(cert->cert_info->validity->notAfter);
+  time_t t2 = getTimeFromASN1(cert->cert_info->validity->notBefore);
+  EvolutionDateMaker date_maker;
+  char * until = date_maker.get_date_string (t);
+  char * before = date_maker.get_date_string (t2);
+
   g_snprintf(buf,size, _("The current server <b>'%s'</b> sent this security certificate :\n\n"
-                              "<b>Issuer :</b> \n%s\n\n"
+                              "<b>Issuer :</b>\n%s\n\n"
                               "<b>Subject : </b>\n%s\n\n"
-                              "<b>Fingerprint : </b>\n%s\n\n"),
+                              "<b>Valid until : </b>%s\n\n"
+                              "<b>Not valid before : </b>%s\n\n"
+                              "<b>Fingerprint (MD5) : </b>\n%s\n\n"),
                               server.c_str(),
-                              X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0),
-                              X509_NAME_oneline(X509_get_subject_name(cert), 0, 0),
+                              X509_NAME_oneline(cert->cert_info->issuer, 0, 0),
+                              X509_NAME_oneline(cert->cert_info->subject, 0, 0),
+                              until,
+                              before,
                               get_x509_fingerpint_md5(cert).c_str());
+
 }
 
 
diff --git a/pan/tasks/cert-store.h b/pan/tasks/cert-store.h
index 9105b8e..3794acd 100644
--- a/pan/tasks/cert-store.h
+++ b/pan/tasks/cert-store.h
@@ -58,11 +58,12 @@ namespace pan
       X509_STORE* _store;
       std::string _path;
       std::vector<SSL_SESSION*> _sessions;
+      certs_t _blacklist;
 
     public:
       SSL_CTX* get_ctx() { return _ctx; }
       X509_STORE* get_store() const { return _store; }
-      void get_all_certs_from_disk(std::set<X509*>& setme);
+      int get_all_certs_from_disk(std::set<X509*>& setme);
       const X509* get_cert_to_server(const Quark& server) const;
       static void pretty_print_x509 (char* buf, size_t size, const Quark& server, X509* cert);
       SSL_SESSION* get_session()
@@ -81,6 +82,19 @@ namespace pan
         _sessions.push_back(s);
       }
 
+      bool in_blacklist (const Quark& s)
+      {
+        return _blacklist.count(s) != 0;
+      }
+      void blacklist (const Quark& s)
+      {
+        _blacklist.insert(s);
+      }
+      void whitelist (const Quark& s)
+      {
+        _blacklist.erase(s);
+      }
+
     private:
       void remove_hard(const Quark&);
 
diff --git a/pan/tasks/nntp-pool.cc b/pan/tasks/nntp-pool.cc
index 7b03538..89aed74 100644
--- a/pan/tasks/nntp-pool.cc
+++ b/pan/tasks/nntp-pool.cc
@@ -275,14 +275,13 @@ NNTP_Pool :: request_nntp (WorkerPool& threadpool)
     std::string address;
     int port;
     if (_server_info.get_server_addr (_server, address, port))
-    {
-      if (_blacklist.count(address) == 0)
+      if (!_certstore.in_blacklist(address))
+//      if (_blacklist.count(address)  == 0)
       {
         ++_pending_connections;
         const bool ssl(_server_info.get_server_ssl_support(_server));
         _socket_creator->create_socket (address, port, threadpool, this, ssl);
       }
-    }
   }
 }
 
@@ -348,13 +347,16 @@ NNTP_Pool :: idle_upkeep ()
 void
 NNTP_Pool :: on_verify_cert_failed (X509* cert, std::string server, int nr)
 {
-  _blacklist.insert(server);
-  abort_tasks();
+//  _blacklist.erase(server);
+  _certstore.blacklist(server);
+  std::cerr<<"adding "<<server<<" to blacklist ("<<cert<<", "<<nr<<")"<<std::endl;
 }
 
 void
 NNTP_Pool :: on_valid_cert_added (X509* cert, std::string server)
 {
-  _blacklist.erase(server);
+//  _blacklist.insert(server);
+  _certstore.whitelist(server);
+  std::cerr<<"removing "<<server<<" from blacklist ("<<cert<<")"<<std::endl;
 }
 #endif
diff --git a/pan/tasks/socket-impl-openssl.cc b/pan/tasks/socket-impl-openssl.cc
index aea118e..054650d 100644
--- a/pan/tasks/socket-impl-openssl.cc
+++ b/pan/tasks/socket-impl-openssl.cc
@@ -121,7 +121,8 @@ GIOChannelSocketSSL :: GIOChannelSocketSSL (SSL_CTX* ctx, CertStore& cs):
    _in_buf (g_string_new (0)),
    _io_performed (false),
    _ctx(ctx),
-   _certstore(cs)
+   _certstore(cs),
+   _rehandshake(false)
 {
 //   std::cerr<<"GIOChannelSocketSSL ctor " << (void*)this<<std::endl;
    cs.add_listener(this);
@@ -373,7 +374,7 @@ namespace
   }
 
 
-  int ssl_handshake(GIOChannel *handle, CertStore::Listener* listener, CertStore* cs, std::string host, SSL_SESSION* session)
+  int ssl_handshake(GIOChannel *handle, CertStore::Listener* listener, CertStore* cs, std::string host, SSL_SESSION* session, bool rehandshake)
   {
 
     GIOSSLChannel *chan = (GIOSSLChannel *)handle;
@@ -392,6 +393,20 @@ namespace
     SSL_set_ex_data(chan->ssl, SSL_get_fd(chan->ssl), &mydata);
 
     if (session) ret = SSL_set_session(chan->ssl, session);
+//    if (rehandshake)
+//    {
+////    SSL_set_verify(ssl,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
+//
+//      /* Stop the client from just resuming the un-authenticated session */
+//      SSL_set_session_id_context(chan->ssl, (void *)&s_server_auth_session_id_context, sizeof(s_server_auth_session_id_context));
+//
+//      if(SSL_renegotiate(ssl)<=0)
+//        return 1;
+//      if(SSL_do_handshake(ssl)<=0)
+//        ssl->state=SSL_ST_ACCEPT;
+//      if(SSL_do_handshake(ssl)<=0)
+//        return 1;
+//    }
 
     ret = SSL_connect(chan->ssl);
     if (ret <= 0) {
@@ -786,7 +801,7 @@ GIOChannelSocketSSL :: ssl_get_iochannel(GIOChannel *handle, gboolean verify)
   gchan->read_buf = g_string_sized_new(4096*128);
 
   int ret;
-  if ((ret = ssl_handshake(gchan, this, &_certstore, _host, _session)) == 0)
+  if ((ret = ssl_handshake(gchan, this, &_certstore, _host, _session, _rehandshake)) == 0)
   {
     g_io_channel_set_flags (handle, G_IO_FLAG_NONBLOCK, 0);
     return gchan;
diff --git a/pan/tasks/socket-impl-openssl.h b/pan/tasks/socket-impl-openssl.h
index 20eef27..ac71638 100644
--- a/pan/tasks/socket-impl-openssl.h
+++ b/pan/tasks/socket-impl-openssl.h
@@ -71,6 +71,10 @@ namespace pan
       SSL_CTX * _ctx;
       CertStore& _certstore;
       SSL_SESSION* _session;
+      bool _rehandshake;
+
+    public:
+      void set_rehandshake (bool setme) { _rehandshake = setme; }
 
     private:
       enum WatchMode { READ_NOW, WRITE_NOW, IGNORE_NOW };



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]