[pan2: 168/268] ssl fully working now todo: * win32 implementation if i have the time * configure script for openssl



commit 2c551658248d8d63a469159ed5544318e2639f0a
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Sat Oct 22 23:12:38 2011 +0200

    ssl fully working now
    todo:
    * win32 implementation if i have the time
    * configure script for openssl/crypto to be modular

 pan.cbp                          |    2 +
 pan/data-impl/add-server.cc      |   17 ++--
 pan/data-impl/data-impl.h        |    7 +-
 pan/data-impl/server.cc          |   24 +++++-
 pan/data/server-info.h           |    5 +
 pan/general/file-util.cc         |   10 --
 pan/general/file-util.h          |    2 -
 pan/gui/pan.cc                   |    3 +-
 pan/gui/server-ui.cc             |   52 ++++++++++-
 pan/tasks/Makefile.am            |    2 +
 pan/tasks/nntp-pool.cc           |    7 +-
 pan/tasks/nntp-pool.h            |    5 +-
 pan/tasks/queue.cc               |    2 +-
 pan/tasks/queue.h                |    5 +-
 pan/tasks/socket-impl-gio.cc     |  116 +---------------------
 pan/tasks/socket-impl-gio.h      |   11 --
 pan/tasks/socket-impl-main.cc    |  156 +++++++++++++++++++++++++++++
 pan/tasks/socket-impl-main.h     |   70 +++++++++++++
 pan/tasks/socket-impl-openssl.cc |  204 ++++++++++++--------------------------
 pan/tasks/socket-impl-openssl.h  |   16 +---
 pan/tasks/socket.h               |    2 +-
 21 files changed, 410 insertions(+), 308 deletions(-)
---
diff --git a/pan.cbp b/pan.cbp
index bb6cb1c..3d72e28 100644
--- a/pan.cbp
+++ b/pan.cbp
@@ -220,6 +220,8 @@
 		<Unit filename="pan/tasks/queue.h" />
 		<Unit filename="pan/tasks/socket-impl-gio.cc" />
 		<Unit filename="pan/tasks/socket-impl-gio.h" />
+		<Unit filename="pan/tasks/socket-impl-main.cc" />
+		<Unit filename="pan/tasks/socket-impl-main.h" />
 		<Unit filename="pan/tasks/socket-impl-openssl.cc" />
 		<Unit filename="pan/tasks/socket-impl-openssl.h" />
 		<Unit filename="pan/tasks/socket-impl-scripted.cc" />
diff --git a/pan/data-impl/add-server.cc b/pan/data-impl/add-server.cc
index b8e3514..3ae41b0 100644
--- a/pan/data-impl/add-server.cc
+++ b/pan/data-impl/add-server.cc
@@ -5,6 +5,7 @@
 #include <pan/tasks/queue.h>
 #include <pan/tasks/socket-impl-gio.h>
 #include <pan/tasks/task-groups.h>
+#include <pan/tasks/socket-impl-main.h>
 #include "data-impl.h"
 
 using namespace pan;
@@ -57,13 +58,15 @@ int main (int argc, char *argv[])
   // initialize the queue
   TaskArchive null_task_archive;
   WorkerPool pool;
-  GIOChannelSocket::Creator _socket_creator;
-  Queue queue (data, null_task_archive, &_socket_creator, pool, true, 10);
-  queue.add_task (new TaskGroups (data, servername));
 
-  // start the event loop...
-  main_loop = g_main_loop_new (NULL, false);
-  g_timeout_add (2*1000, check_for_tasks_done, &queue);
-  g_main_loop_run (main_loop);
+    // FIXME : DBG!
+//  SocketCreator _socket_creator;
+//  Queue queue (data, null_task_archive, &_socket_creator, pool, true, 10);
+//  queue.add_task (new TaskGroups (data, servername));
+//
+//  // start the event loop...
+//  main_loop = g_main_loop_new (NULL, false);
+//  g_timeout_add (2*1000, check_for_tasks_done, &queue);
+//  g_main_loop_run (main_loop);
   return 0;
 }
diff --git a/pan/data-impl/data-impl.h b/pan/data-impl/data-impl.h
index 5225b09..fb27ba0 100644
--- a/pan/data-impl/data-impl.h
+++ b/pan/data-impl/data-impl.h
@@ -107,10 +107,11 @@ namespace pan
          int article_expiration_age;
          int max_connections;
          int rank;
+         int ssl_support;
          typedef sorted_vector<Quark,true,AlphabeticalQuarkOrdering> groups_t;
          groups_t groups;
 
-         Server(): port(119), article_expiration_age(31), max_connections(2), rank(1) {}
+         Server(): port(119), article_expiration_age(31), max_connections(2), rank(1), ssl_support(0) {}
       };
 
       typedef Loki::AssocVector<Quark,Server> servers_t;
@@ -140,6 +141,8 @@ namespace pan
 
       virtual void set_server_rank (const Quark& server, int rank);
 
+      virtual void set_server_ssl_support (const Quark& server, int ssl);
+
       virtual void set_server_article_expiration_age  (const Quark  & server,
                                                        int            days);
 
@@ -164,6 +167,8 @@ namespace pan
 
       virtual std::string get_server_address (const Quark& servername) const;
 
+      virtual bool get_server_ssl_support (const Quark & server) const;
+
       virtual int get_server_rank (const Quark& server) const;
 
       virtual int get_server_limits (const Quark & server) const;
diff --git a/pan/data-impl/server.cc b/pan/data-impl/server.cc
index 2dd509c..f28baa7 100644
--- a/pan/data-impl/server.cc
+++ b/pan/data-impl/server.cc
@@ -158,6 +158,16 @@ DataImpl :: set_server_rank (const Quark   & server,
 }
 
 void
+DataImpl :: set_server_ssl_support (const Quark   & server,
+                                    int             ssl)
+{
+  Server * s (find_server (server));
+  assert (s != 0);
+  s->ssl_support = ssl;
+
+}
+
+void
 DataImpl :: save_server_info (const Quark& server)
 {
   Server * s (find_server (server));
@@ -206,6 +216,16 @@ DataImpl :: get_server_address (const Quark& server) const
   return str;
 }
 
+bool
+DataImpl :: get_server_ssl_support (const Quark & server) const
+{
+  bool retval (false);
+  const Server * s (find_server (server));
+  if (s != 0)
+    retval = (s->ssl_support != 0);
+  return retval;
+}
+
 int
 DataImpl :: get_server_limits (const Quark & server) const
 {
@@ -330,6 +350,7 @@ DataImpl :: load_server_properties (const DataIO& source)
     s.max_connections = to_int (kv["connection-limit"], 2);
     s.article_expiration_age = to_int(kv["expire-articles-n-days-old"], 31);
     s.rank = to_int(kv["rank"], 1);
+    s.ssl_support = to_int(kv["use-ssl"], 0);
     s.newsrc_filename = kv["newsrc"];
     if (s.newsrc_filename.empty()) { // set a default filename
       std::ostringstream o;
@@ -382,7 +403,8 @@ DataImpl :: save_server_properties (DataIO& data_io) const
          << indent(depth) << "<expire-articles-n-days-old>" << s->article_expiration_age << "</expire-articles-n-days-old>\n"
          << indent(depth) << "<connection-limit>" << s->max_connections << "</connection-limit>\n"
          << indent(depth) << "<newsrc>" << s->newsrc_filename << "</newsrc>\n"
-         << indent(depth) << "<rank>" << s->rank << "</rank>\n";
+         << indent(depth) << "<rank>" << s->rank << "</rank>\n"
+         << indent(depth) << "<use-ssl>" << s->ssl_support << "</use-ssl>\n";
 
     *out << indent(--depth) << "</server>\n";
   }
diff --git a/pan/data/server-info.h b/pan/data/server-info.h
index 0bae055..9d20785 100644
--- a/pan/data/server-info.h
+++ b/pan/data/server-info.h
@@ -61,6 +61,9 @@ namespace pan
       virtual void set_server_rank (const Quark& server,
                                     int          rank) = 0;
 
+      virtual void set_server_ssl_support (const Quark& server,
+                                    int          ssl) = 0;
+
       virtual void save_server_info (const Quark& server) = 0;
 
     public: // accessors
@@ -76,6 +79,8 @@ namespace pan
 	  // only used for debug and loging output
       virtual std::string get_server_address (const Quark& servername) const = 0;
 
+      virtual bool get_server_ssl_support (const Quark & server) const = 0;
+
       /** If set_server_limits() has never been called, 2 is returned. */
       virtual int get_server_limits (const Quark & server) const = 0;
 
diff --git a/pan/general/file-util.cc b/pan/general/file-util.cc
index 7e8a770..2e08bc2 100644
--- a/pan/general/file-util.cc
+++ b/pan/general/file-util.cc
@@ -70,16 +70,6 @@ file :: get_pan_home ()
   return pan_home;
 }
 
-std::string
-file :: get_temp_attach_path()
-{
-  char * pch (g_build_filename (file::get_pan_home().c_str(), "downloaded-attachments", NULL));
-  file :: ensure_dir_exists (pch);
-  std::string path (pch);
-  g_free (pch);
-  return path;
-}
-
 const char*
 file :: pan_strerror (int error_number)
 {
diff --git a/pan/general/file-util.h b/pan/general/file-util.h
index fb9c77a..a81f751 100644
--- a/pan/general/file-util.h
+++ b/pan/general/file-util.h
@@ -58,8 +58,6 @@ namespace pan
      */
     std::string get_pan_home ();
 
-    std::string get_temp_attach_path ();
-
     /**
      * If the specified directory doesn't exist, Pan tries to create it.
      * @param path
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index 619633a..42899f6 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -35,6 +35,7 @@ extern "C" {
 #include <pan/general/worker-pool.h>
 #include <pan/tasks/socket-impl-gio.h>
 #include <pan/tasks/socket-impl-openssl.h>
+#include <pan/tasks/socket-impl-main.h>
 #include <pan/tasks/task-groups.h>
 #include <pan/tasks/task-xover.h>
 #include <pan/tasks/nzb.h>
@@ -333,7 +334,7 @@ main (int argc, char *argv[])
     WorkerPool worker_pool (4, true);
 
 //    GIOChannelSocket::Creator socket_creator;
-    GIOChannelSocketSSL::Creator socket_creator;
+    SocketCreator socket_creator;
 
     Queue queue (data, data, &socket_creator, worker_pool,
                  prefs.get_flag ("work-online", true),
diff --git a/pan/gui/server-ui.cc b/pan/gui/server-ui.cc
index a118661..d1664c2 100644
--- a/pan/gui/server-ui.cc
+++ b/pan/gui/server-ui.cc
@@ -55,6 +55,7 @@ namespace
     GtkWidget * connection_limit_spin;
     GtkWidget * expiration_age_combo;
     GtkWidget * rank_combo;
+    GtkWidget * ssl_combo;
     ServerEditDialog (Data& d, Queue& q): data(d), queue(q) {}
   };
 
@@ -91,7 +92,7 @@ namespace
 
     d->server = server;
 
-    int port(119), max_conn(4), age(31*3), rank(1);
+    int port(119), max_conn(4), age(31*3), rank(1), ssl(0);
     std::string addr, user, pass;
     if (!server.empty()) {
       d->data.get_server_addr (server, addr, port);
@@ -99,6 +100,7 @@ namespace
       age = d->data.get_server_article_expiration_age (server);
       rank = d->data.get_server_rank (server);
       max_conn = d->data.get_server_limits (server);
+      ssl = d->data.get_server_ssl_support(server);
     }
 
     pan_entry_set_text (d->address_entry, addr);
@@ -131,6 +133,19 @@ namespace
         break;
       }
     } while (gtk_tree_model_iter_next(model, &iter));
+
+    // set ssl combo
+    combo = GTK_COMBO_BOX (d->ssl_combo);
+    model = gtk_combo_box_get_model (combo);
+    if (gtk_tree_model_get_iter_first(model, &iter)) do {
+      int that;
+      gtk_tree_model_get (model, &iter, 1, &that, -1);
+      if (that == ssl) {
+        gtk_combo_box_set_active_iter (combo, &iter);
+        break;
+      }
+    } while (gtk_tree_model_iter_next(model, &iter));
+
   }
 
   void
@@ -159,6 +174,10 @@ namespace
       combo = GTK_COMBO_BOX (d->rank_combo);
       if (gtk_combo_box_get_active_iter (combo, &iter))
         gtk_tree_model_get (gtk_combo_box_get_model(combo), &iter, 1, &rank, -1);
+      int ssl(0);
+      combo = GTK_COMBO_BOX (d->ssl_combo);
+      if (gtk_combo_box_get_active_iter (combo, &iter))
+        gtk_tree_model_get (gtk_combo_box_get_model(combo), &iter, 1, &ssl, -1);
 
       const char * err_msg (0);
       if (addr.empty())
@@ -181,6 +200,7 @@ namespace
         d->data.set_server_limits (d->server, max_conn);
         d->data.set_server_article_expiration_age (d->server, age);
         d->data.set_server_rank (d->server, rank);
+        d->data.set_server_ssl_support(d->server, ssl);
         d->data.save_server_info(d->server);
         d->queue.upkeep ();
       }
@@ -304,6 +324,36 @@ pan :: server_edit_dialog_new (Data& data, Queue& queue, GtkWindow * window, con
     gtk_widget_set_tooltip_text( e, _("Fallback servers are used for articles that can't be found on the primaries.  One common approach is to use free servers as primaries and subscription servers as fallbacks."));
     HIG::workarea_add_row (t, &row, e, w);
 
+    // ssl 3.0 option
+    HIG::workarea_add_section_divider (t, &row);
+    HIG::workarea_add_section_title (t, &row, _("Security"));
+    HIG::workarea_add_section_spacer (t, row, 2);
+    struct { int o; const char * str; } ssl_items[] = {
+      { 0, N_("Use Plaintext (Unsecured) Connections") },
+      { 1, N_("Use Secure TLS (SSL) Connections") }
+    };
+    store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+    for (unsigned int i(0); i<G_N_ELEMENTS(ssl_items); ++i) {
+      GtkTreeIter iter;
+      gtk_list_store_append (store,  &iter);
+      gtk_list_store_set (store, &iter, 0, _(ssl_items[i].str), 1, ssl_items[i].o, -1);
+    }
+
+    d->ssl_combo = w = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
+    g_object_unref (G_OBJECT(store));
+    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), renderer, true);
+    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer, "text", 0, NULL);
+    gtk_combo_box_set_active (GTK_COMBO_BOX(w), 0);
+    l = gtk_label_new (_("TLS (SSL) Options:"));
+    e = gtk_event_box_new ();
+    gtk_container_add (GTK_CONTAINER(e), l);
+    gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
+    gtk_widget_set_tooltip_text( e, _("You can set the option for using/disabling secure SSL/TLS connections here. If you enable SSL/TLS, your data is encrypted and secure. "
+                                      "It is encouraged to use this option for privacy reasons."));
+    HIG::workarea_add_row (t, &row, e, w);
+
+
+
   d->server = server;
   edit_dialog_populate (data, server, d);
   gtk_widget_show_all (d->dialog);
diff --git a/pan/tasks/Makefile.am b/pan/tasks/Makefile.am
index 32201a4..1a696bc 100644
--- a/pan/tasks/Makefile.am
+++ b/pan/tasks/Makefile.am
@@ -17,6 +17,7 @@ libtasks_a_SOURCES = \
   queue.cc \
   upload-queue.cc \
   socket.cc \
+  socket-impl-main.cc \
   socket-impl-openssl.cc \
   socket-impl-gio.cc \
   socket-impl-scripted.cc \
@@ -41,6 +42,7 @@ noinst_HEADERS = \
   queue.h  \
   upload-queue.h \
   socket.h \
+  socket-impl-main.h \
   socket-impl-gio.h \
   socket-impl-openssl.h \
   socket-impl-scripted.h \
diff --git a/pan/tasks/nntp-pool.cc b/pan/tasks/nntp-pool.cc
index 2c9f061..12e4fc0 100644
--- a/pan/tasks/nntp-pool.cc
+++ b/pan/tasks/nntp-pool.cc
@@ -39,7 +39,7 @@ namespace
 
 NNTP_Pool :: NNTP_Pool (const Quark        & server,
                         ServerInfo         & server_info,
-                        Socket::Creator    * creator):
+                        SocketCreator      * creator):
   _server_info (server_info),
   _server (server),
   _socket_creator (creator),
@@ -266,14 +266,13 @@ NNTP_Pool :: request_nntp (WorkerPool& threadpool)
 
   if (!idle && ((pending+active)<max) && new_connections_are_allowed())
   {
-    debug ("trying to create a socket");
-
     std::string address;
     int port;
     if (_server_info.get_server_addr (_server, address, port))
     {
       ++_pending_connections;
-      _socket_creator->create_socket (address, port, threadpool, this);
+      const bool ssl(_server_info.get_server_ssl_support(_server));
+      _socket_creator->create_socket (address, port, threadpool, this, ssl);
     }
   }
 }
diff --git a/pan/tasks/nntp-pool.h b/pan/tasks/nntp-pool.h
index 9f5009f..4815e1b 100644
--- a/pan/tasks/nntp-pool.h
+++ b/pan/tasks/nntp-pool.h
@@ -26,6 +26,7 @@
 #include <pan/data/server-info.h>
 #include <pan/tasks/socket.h>
 #include <pan/tasks/nntp.h>
+#include <pan/tasks/socket-impl-main.h>
 
 namespace pan
 {
@@ -45,7 +46,7 @@ namespace pan
 
       NNTP_Pool (const Quark       & server,
                  ServerInfo        & server_info,
-                 Socket::Creator   *);
+                 SocketCreator     *);
 
       virtual ~NNTP_Pool ();
 
@@ -92,7 +93,7 @@ namespace pan
 
       ServerInfo& _server_info;
       const Quark _server;
-      Socket::Creator * _socket_creator;
+      SocketCreator * _socket_creator;
       int _pending_connections;
 
       struct PoolItem {
diff --git a/pan/tasks/queue.cc b/pan/tasks/queue.cc
index 8d5aeae..3fbc306 100644
--- a/pan/tasks/queue.cc
+++ b/pan/tasks/queue.cc
@@ -33,7 +33,7 @@ using namespace pan;
 
 Queue :: Queue (ServerInfo         & server_info,
                 TaskArchive        & archive,
-                Socket::Creator    * socket_creator,
+                SocketCreator      * socket_creator,
                 WorkerPool         & pool,
                 bool                 online,
                 int                  save_delay_secs):
diff --git a/pan/tasks/queue.h b/pan/tasks/queue.h
index b97d2c9..1257641 100644
--- a/pan/tasks/queue.h
+++ b/pan/tasks/queue.h
@@ -34,6 +34,7 @@
 #include <pan/tasks/task.h>
 #include <pan/tasks/encoder.h>
 #include <pan/tasks/task-weak-ordering.h>
+#include <pan/tasks/socket-impl-main.h>
 
 namespace pan
 {
@@ -69,7 +70,7 @@ namespace pan
     private AdaptableSet<Task*, TaskWeakOrdering>::Listener
   {
     public:
-      Queue (ServerInfo&, TaskArchive&, Socket::Creator*, WorkerPool&,
+      Queue (ServerInfo&, TaskArchive&, SocketCreator*, WorkerPool&,
              bool online, int save_delay_secs);
       virtual ~Queue ();
 
@@ -201,7 +202,7 @@ namespace pan
       std::set<TaskUpload*> _uploads;
       std::set<Task*> _removing;
       std::set<Task*> _stopped;
-      Socket::Creator * _socket_creator;
+      SocketCreator * _socket_creator;
       WorkerPool & _worker_pool;
       Decoder _decoder;
       Encoder _encoder;
diff --git a/pan/tasks/socket-impl-gio.cc b/pan/tasks/socket-impl-gio.cc
index a0e14eb..95f4993 100644
--- a/pan/tasks/socket-impl-gio.cc
+++ b/pan/tasks/socket-impl-gio.cc
@@ -89,71 +89,12 @@ extern "C" {
 #include <pan/general/string-view.h>
 #include <pan/usenet-utils/gnksa.h>
 #include "socket-impl-gio.h"
+#include "socket-impl-main.h"
 
 using namespace pan;
 
 namespace
 {
-  typedef int (*t_getaddrinfo)(const char *,const char *, const struct addrinfo*, struct addrinfo **);
-  t_getaddrinfo p_getaddrinfo (0);
-
-  typedef void (*t_freeaddrinfo)(struct addrinfo*);
-  t_freeaddrinfo p_freeaddrinfo (0);
-
-  void ensure_module_inited (void)
-  {
-    static bool inited (false);
-
-    if (!inited)
-    {
-      p_freeaddrinfo=NULL;
-      p_getaddrinfo=NULL;
-
-#ifdef G_OS_WIN32
-      WSADATA wsaData;
-      WSAStartup(MAKEWORD(2,2), &wsaData);
-
-      char sysdir[MAX_PATH], path[MAX_PATH+8];
-
-      if(GetSystemDirectory(sysdir,MAX_PATH)!=0)
-      {
-        HMODULE lib=NULL;
-        FARPROC pfunc=NULL;
-        const char *libs[]={"ws2_32","wship6",NULL};
-
-        for(const char **p=libs;*p!=NULL;++p)
-        {
-          g_snprintf(path,MAX_PATH+8,"%s\\%s",sysdir,*p);
-          lib=LoadLibrary(path);
-          if(!lib)
-            continue;
-          pfunc=GetProcAddress(lib,"getaddrinfo");
-          if(!pfunc)
-          {
-            FreeLibrary(lib);
-            lib=NULL;
-            continue;
-          }
-          p_getaddrinfo=reinterpret_cast<t_getaddrinfo>(pfunc);
-          pfunc=GetProcAddress(lib,"freeaddrinfo");
-          if(!pfunc)
-          {
-            FreeLibrary(lib);
-            lib=NULL;
-            p_getaddrinfo=NULL;
-            continue;
-          }
-          p_freeaddrinfo=reinterpret_cast<t_freeaddrinfo>(pfunc);
-          break;
-        }
-      }
-#else
-      p_freeaddrinfo=::freeaddrinfo;
-      p_getaddrinfo=::getaddrinfo;
-#endif
-      inited = true;
-    }
-  }
 
   GIOChannel *
   create_channel (const StringView& host_in, int port, std::string& setme_err)
@@ -170,7 +111,7 @@ namespace
     char portbuf[32], hpbuf[255];
     g_snprintf (portbuf, sizeof(portbuf), "%d", port);
     g_snprintf (hpbuf,sizeof(hpbuf),"%s:%s",host_in.str,portbuf);
-    
+
 #ifdef G_OS_WIN32 // windows might not have getaddrinfo...
     if (!p_getaddrinfo)
     {
@@ -220,7 +161,7 @@ namespace
       hints.ai_family = 0;
       hints.ai_socktype = SOCK_STREAM;
       struct addrinfo * ans;
-      err = p_getaddrinfo (host.c_str(), portbuf, &hints, &ans);
+      err = ::getaddrinfo (host.c_str(), portbuf, &hints, &ans);
       if (err != 0) {
         char buf[512];
         snprintf (buf, sizeof(buf), _("Error connecting to \"%s\""), hpbuf);
@@ -255,7 +196,7 @@ namespace
       }
 
       // cleanup
-      p_freeaddrinfo (ans);
+      ::freeaddrinfo (ans);
     }
 
     // create the giochannel...
@@ -339,6 +280,7 @@ bool
 GIOChannelSocket :: open (const StringView& address, int port, std::string& setme_err)
 {
   _host.assign (address.str, address.len);
+  std::cerr<<"open normal "<<address<<":"<<port<<std::endl;
   _channel = create_channel (address, port, setme_err);
   return _channel != 0;
 }
@@ -553,51 +495,3 @@ GIOChannelSocket :: set_watch_mode (WatchMode mode)
 
   debug ("set_watch_mode " << mode << ": _tag_watch is now " << _tag_watch);
 }
-
-/***
-****  GIOChannel::SocketCreator -- create a socket in a worker thread
-***/
-
-namespace
-{
-  struct ThreadWorker : public WorkerPool::Worker,
-                        public WorkerPool::Worker::Listener
-  {
-    std::string host;
-    int port;
-    Socket::Creator::Listener * listener;
-
-    bool ok;
-    Socket * socket;
-    std::string err;
-
-    ThreadWorker (const StringView& h, int p, Socket::Creator::Listener *l):
-      host(h), port(p), listener(l), ok(false), socket(0) {}
-
-    void do_work ()
-    {
-      socket = new GIOChannelSocket ();
-      ok = socket->open (host, port, err);
-    }
-
-    /** called in main thread after do_work() is done */
-    void on_worker_done (bool cancelled UNUSED)
-    {
-      // pass results to main thread...
-      if (!err.empty())   Log :: add_err (err.c_str());
-      listener->on_socket_created (host, port, ok, socket);
-    }
-  };
-}
-
-void
-GIOChannelSocket :: Creator :: create_socket (const StringView & host,
-                                              int                port,
-                                              WorkerPool       & threadpool,
-                                              Listener         * listener)
-{
-  ensure_module_inited ();
-
-  ThreadWorker * w = new ThreadWorker (host, port, listener);
-  threadpool.push_work (w, w, true);
-}
diff --git a/pan/tasks/socket-impl-gio.h b/pan/tasks/socket-impl-gio.h
index da74acc..e38679e 100644
--- a/pan/tasks/socket-impl-gio.h
+++ b/pan/tasks/socket-impl-gio.h
@@ -61,17 +61,6 @@ namespace pan
       enum DoResult { IO_ERR, IO_READ, IO_WRITE, IO_DONE };
       DoResult do_read ();
       DoResult do_write ();
-
-    public:
-
-      /**
-       * Socket::Creator that instantiates GIOSocket objects.
-       */
-      class Creator: public Socket::Creator {
-        public:
-          virtual ~Creator () { }
-          virtual void create_socket (const StringView& host, int port, WorkerPool&, Listener *l);
-      };
   };
 }
 
diff --git a/pan/tasks/socket-impl-main.cc b/pan/tasks/socket-impl-main.cc
new file mode 100644
index 0000000..43b68b2
--- /dev/null
+++ b/pan/tasks/socket-impl-main.cc
@@ -0,0 +1,156 @@
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2006  Charles Kerr <charles rebelbase com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+/***
+****  GIOChannel::SocketCreator -- create a socket in a worker thread
+***/
+
+#include <string>
+#include <glib/giochannel.h>
+#include <glib/gstring.h>
+#include <pan/tasks/socket.h>
+
+#include <config.h>
+#include <iostream>
+#include <string>
+#include <cerrno>
+#include <cstring>
+
+#include <pan/general/log.h>
+#include <pan/general/macros.h>
+#include <pan/general/worker-pool.h>
+#include <pan/general/string-view.h>
+
+#include "socket-impl-main.h"
+
+using namespace pan;
+
+/*  FIXME for win32!!!!!!!
+namespace
+{
+  void ensure_module_inited (void)
+  {
+    static bool inited (false);
+
+    if (!inited)
+    {
+      p_freeaddrinfo=NULL;
+      p_getaddrinfo=NULL;
+
+#ifdef G_OS_WIN32
+      WSADATA wsaData;
+      WSAStartup(MAKEWORD(2,2), &wsaData);
+
+      char sysdir[MAX_PATH], path[MAX_PATH+8];
+
+      if(GetSystemDirectory(sysdir,MAX_PATH)!=0)
+      {
+        HMODULE lib=NULL;
+        FARPROC pfunc=NULL;
+        const char *libs[]={"ws2_32","wship6",NULL};
+
+        for(const char **p=libs;*p!=NULL;++p)
+        {
+          g_snprintf(path,MAX_PATH+8,"%s\\%s",sysdir,*p);
+          lib=LoadLibrary(path);
+          if(!lib)
+            continue;
+          pfunc=GetProcAddress(lib,"getaddrinfo");
+          if(!pfunc)
+          {
+            FreeLibrary(lib);
+            lib=NULL;
+            continue;
+          }
+          p_getaddrinfo=reinterpret_cast<t_getaddrinfo>(pfunc);
+          pfunc=GetProcAddress(lib,"freeaddrinfo");
+          if(!pfunc)
+          {
+            FreeLibrary(lib);
+            lib=NULL;
+            p_getaddrinfo=NULL;
+            continue;
+          }
+          p_freeaddrinfo=reinterpret_cast<t_freeaddrinfo>(pfunc);
+          break;
+        }
+      }
+#else
+      p_freeaddrinfo=::freeaddrinfo;
+      p_getaddrinfo=::getaddrinfo;
+#endif
+      inited = true;
+    }
+  }
+}
+*/
+
+namespace pan
+{
+  struct ThreadWorker : public WorkerPool::Worker,
+                        public WorkerPool::Worker::Listener
+  {
+    std::string host;
+    int port;
+    Socket::Creator::Listener * listener;
+
+    bool ok;
+    Socket * socket;
+    std::string err;
+    bool use_ssl;
+
+    ThreadWorker (const StringView& h, int p, Socket::Creator::Listener *l, bool ssl):
+      host(h), port(p), listener(l), ok(false), socket(0), use_ssl(ssl) {}
+
+    void do_work ()
+    {
+      if (use_ssl)
+        socket = new GIOChannelSocketSSL ();
+      else
+        socket = new GIOChannelSocket ();
+      ok = socket->open (host, port, err);
+    }
+
+    /** called in main thread after do_work() is done */
+    void on_worker_done (bool cancelled UNUSED)
+    {
+      // pass results to main thread...
+      if (!err.empty())   Log :: add_err (err.c_str());
+      listener->on_socket_created (host, port, ok, socket);
+    }
+  };
+}
+
+SocketCreator :: SocketCreator() {}
+SocketCreator :: ~SocketCreator() {}
+
+void
+SocketCreator :: create_socket (const StringView & host,
+                                int                port,
+                                WorkerPool       & threadpool,
+                                Socket::Creator::Listener * listener,
+                                bool               use_ssl)
+{
+//  ensure_module_inited ();
+
+  ThreadWorker * w = new ThreadWorker (host, port, listener, use_ssl);
+  threadpool.push_work (w, w, true);
+}
diff --git a/pan/tasks/socket-impl-main.h b/pan/tasks/socket-impl-main.h
new file mode 100644
index 0000000..c1b8787
--- /dev/null
+++ b/pan/tasks/socket-impl-main.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Pan - A Newsreader for Gtk+
+ * Copyright (C) 2002-2006  Charles Kerr <charles rebelbase com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef __SocketMAIN_h__
+#define __SocketMAIN_h__
+
+#ifdef G_OS_WIN32
+  #include <ws2tcpip.h>
+#else
+  #include <signal.h>
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <netinet/in.h>
+  #include <netdb.h>
+  #include <arpa/inet.h>
+#endif
+
+#include <pan/general/string-view.h>
+#include <pan/general/worker-pool.h>
+#include "socket.h"
+#include "socket-impl-openssl.h"
+#include "socket-impl-gio.h"
+
+namespace pan
+{
+
+  typedef int (*t_getaddrinfo)(const char *,const char *, const struct addrinfo*, struct addrinfo **);
+  static t_getaddrinfo p_getaddrinfo (0);
+
+  typedef void (*t_freeaddrinfo)(struct addrinfo*);
+  static t_freeaddrinfo p_freeaddrinfo (0);
+
+}
+
+namespace pan
+{
+
+  class SocketCreator
+  {
+    public:
+      SocketCreator ();
+      virtual ~SocketCreator ();
+
+      virtual void create_socket (const StringView & host,
+                                  int                port,
+                                  WorkerPool       & threadpool,
+                                  Socket::Creator::Listener * listener,
+                                  bool               use_ssl);
+  };
+
+}
+
+#endif
diff --git a/pan/tasks/socket-impl-openssl.cc b/pan/tasks/socket-impl-openssl.cc
index 66c0857..0c18bec 100644
--- a/pan/tasks/socket-impl-openssl.cc
+++ b/pan/tasks/socket-impl-openssl.cc
@@ -44,16 +44,16 @@ extern "C" {
   #define _WIN32_WINNT 0x0501
   #include <ws2tcpip.h>
   #undef gai_strerror
-  /*
+
   #define gai_strerror(i) gai_strerror_does_not_link (i)
-  const char*
-  gai_strerror_does_not_link (int errval)
-  {
-    char buf[32];
-    g_snprintf (buf, sizeof(buf), "Winsock error %d", errval);
-    return buf;
-  }
-  */
+//  const char*
+//  gai_strerror_does_not_link (int errval)
+//  {
+//    char buf[32];
+//    g_snprintf (buf, sizeof(buf), "Winsock error %d", errval);
+//    return buf;
+//  }
+
   const char*
   get_last_error (int err)
   {
@@ -88,76 +88,11 @@ extern "C" {
 #include <pan/general/log.h>
 #include <pan/general/string-view.h>
 #include <pan/usenet-utils/gnksa.h>
-#include "socket-impl-gio.h"
 #include "socket-impl-openssl.h"
+#include "socket-impl-main.h"
 
 using namespace pan;
 
-namespace
-{
-  typedef int (*t_getaddrinfo)(const char *,const char *, const struct addrinfo*, struct addrinfo **);
-  t_getaddrinfo p_getaddrinfo (0);
-
-  typedef void (*t_freeaddrinfo)(struct addrinfo*);
-  t_freeaddrinfo p_freeaddrinfo (0);
-
-  void ensure_module_inited (void)
-  {
-    bool inited (false);
-
-    if (!inited)
-    {
-      p_freeaddrinfo=0;
-      p_getaddrinfo=0;
-
-#ifdef G_OS_WIN32
-      WSADATA wsaData;
-      WSAStartup(MAKEWORD(2,2), &wsaData);
-
-      char sysdir[MAX_PATH], path[MAX_PATH+8];
-
-      if(GetSystemDirectory(sysdir,MAX_PATH)!=0)
-      {
-        HMODULE lib=0;
-        FARPROC pfunc=0;
-        const char *libs[]={"ws2_32","wship6",0};
-
-        for(const char **p=libs;*p!=0;++p)
-        {
-          g_snprintf(path,MAX_PATH+8,"%s\\%s",sysdir,*p);
-          lib=LoadLibrary(path);
-          if(!lib)
-            continue;
-          pfunc=GetProcAddress(lib,"getaddrinfo");
-          if(!pfunc)
-          {
-            FreeLibrary(lib);
-            lib=0;
-            continue;
-          }
-          p_getaddrinfo=reinterpret_cast<t_getaddrinfo>(pfunc);
-          pfunc=GetProcAddress(lib,"freeaddrinfo");
-          if(!pfunc)
-          {
-            FreeLibrary(lib);
-            lib=0;
-            p_getaddrinfo=0;
-            continue;
-          }
-          p_freeaddrinfo=reinterpret_cast<t_freeaddrinfo>(pfunc);
-          break;
-        }
-      }
-#else
-      p_freeaddrinfo=::freeaddrinfo;
-      p_getaddrinfo=::getaddrinfo;
-#endif
-      inited = true;
-    }
-  }
-
-}
-
 /****
 *****
 *****
@@ -176,6 +111,7 @@ GIOChannelSocketSSL :: GIOChannelSocketSSL ():
    debug ("GIOChannelSocketSSL ctor " << (void*)this);
 }
 
+
 GIOChannel *
 GIOChannelSocketSSL :: create_channel (const StringView& host_in, int port, std::string& setme_err)
 {
@@ -186,6 +122,8 @@ GIOChannelSocketSSL :: create_channel (const StringView& host_in, int port, std:
   signal (SIGPIPE, SIG_IGN);
 #endif
 
+  std::cerr<<"cc "<<host_in<<":"<<port<<"\n";
+
   // get an addrinfo for the host
   const std::string host (host_in.str, host_in.len);
   char portbuf[32], hpbuf[255];
@@ -241,7 +179,7 @@ GIOChannelSocketSSL :: create_channel (const StringView& host_in, int port, std:
     hints.ai_family = 0;
     hints.ai_socktype = SOCK_STREAM;
     struct addrinfo * ans;
-    err = p_getaddrinfo (host.c_str(), portbuf, &hints, &ans);
+    err = ::getaddrinfo (host.c_str(), portbuf, &hints, &ans);
     if (err != 0) {
       char buf[512];
       snprintf (buf, sizeof(buf), _("Error connecting to \"%s\""), hpbuf);
@@ -276,7 +214,7 @@ GIOChannelSocketSSL :: create_channel (const StringView& host_in, int port, std:
     }
 
     // cleanup
-    p_freeaddrinfo (ans);
+    ::freeaddrinfo (ans);
   }
 
   // create the giochannel...
@@ -361,6 +299,46 @@ namespace
     }
   }
 
+  /* todo: real verify + UI ! */
+  gboolean ssl_verify(SSL *ssl, SSL_CTX *ctx, X509 *cert)
+  {
+//    if (SSL_get_verify_result(ssl) != X509_V_OK) {
+      unsigned char md[EVP_MAX_MD_SIZE];
+      unsigned int n;
+      char *str;
+
+      if ((str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) == NULL)
+        g_warning("  Could not get subject-name from peer certificate");
+      else {
+        g_warning("  Subject : %s", str);
+        free(str);
+      }
+      if ((str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)) == NULL)
+        g_warning("  Could not get issuer-name from peer certificate");
+      else {
+        g_warning("  Issuer  : %s", str);
+        free(str);
+      }
+      if (! X509_digest(cert, EVP_md5(), md, &n))
+        g_warning("  Could not get fingerprint from peer certificate");
+      else {
+        char hex[] = "0123456789ABCDEF";
+        char fp[EVP_MAX_MD_SIZE*3];
+        if (n < sizeof(fp)) {
+          unsigned int i;
+          for (i = 0; i < n; i++) {
+            fp[i*3+0] = hex[(md[i] >> 4) & 0xF];
+            fp[i*3+1] = hex[(md[i] >> 0) & 0xF];
+            fp[i*3+2] = i == n - 1 ? '\0' : ':';
+          }
+          g_warning("  MD5 Fingerprint : %s", fp);
+        }
+      }
+//      return FALSE;
+//    }
+    return TRUE;
+  }
+
 
   void ssl_free(GIOChannel *handle)
   {
@@ -398,6 +376,7 @@ bool
 GIOChannelSocketSSL :: open (const StringView& address, int port, std::string& setme_err)
 {
   _host.assign (address.str, address.len);
+  std::cerr<<"open ssl "<<address<<":"<<port<<std::endl;
   _channel = create_channel (address, port, setme_err);
   return _channel != 0;
 }
@@ -452,34 +431,29 @@ namespace
     return G_IO_STATUS_ERROR;
   }
 
-  int ssl_handshake(GIOChannel *handle)
+  bool ssl_handshake(GIOChannel *handle)
   {
     GIOSSLChannel *chan = (GIOSSLChannel *)handle;
-    int ret, err;
+    bool ret;
+    int err;
     X509 *cert;
     const char *errstr;
 
-    if (!handle || !chan->ssl) return -1;
+    if (!handle || !chan->ssl || !chan->ctx) return -1;
 
     ret = SSL_connect(chan->ssl);
     if (ret <= 0) {
       err = SSL_get_error(chan->ssl, ret);
-      if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
-        errstr = ERR_reason_error_string(ERR_get_error());
-        g_warning("SSL handshake failed: %s", errstr != 0 ? errstr : "server closed connection");
+      if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
         return -1;
-      }
       return err == SSL_ERROR_WANT_READ ? 1 : 3;
     }
 
-
     cert = SSL_get_peer_certificate(chan->ssl);
-    if (cert == 0) {
-      g_warning("SSL server supplied no certificate");
+    if (!cert && chan->ssl)
       return -1;
-    }
 
-//    ret = chan->verify ? ssl_verify(chan->ssl, chan->ctx, handle->hostname.c_str(), cert) : true;
+    ret = chan->verify ? ssl_verify(chan->ssl, chan->ctx, cert) : true;
     X509_free(cert);
     return ret ? 0 : -1;
   }
@@ -847,59 +821,9 @@ GIOChannelSocketSSL :: ssl_get_iochannel(GIOChannel *handle, gboolean verify)
   gchan->read_buf = g_string_sized_new(4096*128);
 
   /// FIXME : callback
-  debug("before handshake");
-  while (ssl_handshake(gchan) != 0) ;
-  debug("after handshake");
+  if (ssl_handshake(gchan))
 
 //  std::cerr<<"handshake success!\n";
 
 	return gchan;
 }
-
-/***
-****  GIOChannel::SocketCreator -- create a socket in a worker thread
-***/
-
-namespace
-{
-  struct ThreadWorker : public WorkerPool::Worker,
-                        public WorkerPool::Worker::Listener
-  {
-    std::string host;
-    int port;
-    Socket::Creator::Listener * listener;
-
-    bool ok;
-    Socket * socket;
-    std::string err;
-
-    ThreadWorker (const StringView& h, int p, Socket::Creator::Listener *l):
-      host(h), port(p), listener(l), ok(false), socket(0) {}
-
-    void do_work ()
-    {
-      socket = new GIOChannelSocketSSL ();
-      ok = socket->open (host, port, err);
-    }
-
-    /** called in main thread after do_work() is done */
-    void on_worker_done (bool cancelled UNUSED)
-    {
-      // pass results to main thread...
-      if (!err.empty())   Log :: add_err (err.c_str());
-      listener->on_socket_created (host, port, ok, socket);
-    }
-  };
-}
-
-void
-GIOChannelSocketSSL :: Creator :: create_socket (const StringView & host,
-                                              int                port,
-                                              WorkerPool       & threadpool,
-                                              Listener         * listener)
-{
-  ensure_module_inited ();
-
-  ThreadWorker * w = new ThreadWorker (host, port, listener);
-  threadpool.push_work (w, w, true);
-}
diff --git a/pan/tasks/socket-impl-openssl.h b/pan/tasks/socket-impl-openssl.h
index 323e76f..48d3017 100644
--- a/pan/tasks/socket-impl-openssl.h
+++ b/pan/tasks/socket-impl-openssl.h
@@ -32,6 +32,8 @@
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 
+#include "socket-impl-gio.h"
+
 namespace pan
 {
   /**
@@ -39,7 +41,7 @@ namespace pan
    *
    * @ingroup tasks
    */
-  class GIOChannelSocketSSL: public Socket
+  class GIOChannelSocketSSL: public GIOChannelSocket
   {
     public:
       GIOChannelSocketSSL ();
@@ -71,20 +73,8 @@ namespace pan
 
       GIOChannel * create_channel (const StringView& host_in, int port, std::string& setme_err);
 
-    //SSL functions
     private:
       GIOChannel* ssl_get_iochannel(GIOChannel *handle, gboolean verify=true);
-
-    public:
-
-      /**
-       * Socket::Creator that instantiates GIOSocket objects.
-       */
-      class Creator: public Socket::Creator {
-        public:
-          virtual ~Creator () { }
-          virtual void create_socket (const StringView& host, int port, WorkerPool&, Listener *l);
-      };
   };
 }
 
diff --git a/pan/tasks/socket.h b/pan/tasks/socket.h
index db40ac2..a4cfa7e 100644
--- a/pan/tasks/socket.h
+++ b/pan/tasks/socket.h
@@ -86,7 +86,7 @@ namespace pan
         };
 
         virtual ~Creator () { }
-        virtual void create_socket (const StringView& host, int port, WorkerPool&, Listener*) = 0;
+        virtual void create_socket (const StringView& host, int port, WorkerPool&, Listener*, bool) = 0;
       };
   };
 }



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