Split SSL server support from SSL client support.
authorThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Wed, 10 Jun 2009 17:13:04 +0000 (14:13 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Wed, 10 Jun 2009 17:13:04 +0000 (14:13 -0300)
Makefile.am
ssl.c
ssl.h
ssl_server.c [new file with mode: 0644]

index f8041f6..83c80ab 100644 (file)
@@ -1,3 +1,3 @@
 bin_PROGRAMS = popproxy
-popproxy_SOURCES = popproxy.c log.c log.h nethook.c nethook.h proto_detect.c proto_detect.h jabber.c jabber.h jabber_server.c iksemel_extra.c iksemel_extra.h null.c null.h ssl.c ssl.h
+popproxy_SOURCES = popproxy.c log.c log.h nethook.c nethook.h proto_detect.c proto_detect.h jabber.c jabber.h jabber_server.c iksemel_extra.c iksemel_extra.h null.c null.h ssl.c ssl.h ssl_server.c
 sysconf_DATA = popproxy.conf
diff --git a/ssl.c b/ssl.c
index 2a45657..fff8e63 100644 (file)
--- a/ssl.c
+++ b/ssl.c
 #include <errno.h>
 #include "ssl.h"
 
-#define container_of(ptr, type, member) ({                      \
-        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-        (type *)( (char *)__mptr - offsetof(type,member) );})
-
-struct ssl_data
-{
-  char *server;
-  gnutls_session_t session;
-  GString *buffer;
-  gboolean handshaking;
-};
-
-static struct ssl_data *
-ssl_data_new (char *server)
-{
-  struct ssl_data *ssl;
-  int kx_prio[] = {GNUTLS_KX_RSA, 0};
-  gnutls_certificate_credentials cred;
-  gnutls_certificate_allocate_credentials (&cred);
-  ssl = g_slice_new (struct ssl_data);
-  ssl->server = g_strdup (server);
-  gnutls_init (&ssl->session, GNUTLS_CLIENT);
-  gnutls_set_default_priority (ssl->session);
-  gnutls_set_default_priority (ssl->session);
-  gnutls_kx_set_priority (ssl->session, kx_prio);
-  gnutls_credentials_set (ssl->session, GNUTLS_CRD_CERTIFICATE, cred);
-  ssl->buffer = g_string_sized_new (4096);
-  ssl->handshaking = FALSE;
-  return ssl;
-}
-
-static void
-ssl_data_destroy (struct ssl_data *ssl)
-{
-  gnutls_deinit (ssl->session);
-  g_free (ssl->server);
-  g_string_free (ssl->buffer, TRUE);
-  g_slice_free (struct ssl_data, ssl);
-}
-
-static ssize_t
-ssl_push (gnutls_transport_ptr_t ptr, const void *buffer, size_t len)
-{
-  net_hook_t *hook = ptr;
-  struct ssl_data *ssl = hook->data;
-  int r;
-  if (ssl->handshaking == TRUE)
-    {
-      g_io_channel_write_chars (hook->conn->iochannel, buffer, len,
-                                &r, NULL);
-      return r;
-    }
-  gnet_conn_write (hook->conn, (void *) buffer, len);
-  return len;
-}
-
-static ssize_t
-ssl_pull (gnutls_transport_ptr_t ptr, void *buffer, size_t len)
-{
-  net_hook_t *hook = ptr;
-  struct ssl_data *ssl = hook->data;
-  int r;
-  if (ssl->handshaking == TRUE)
-    {
-      g_io_channel_read_chars (hook->conn->iochannel, buffer, len,
-                               &r, NULL);
-      return r;
-    }
-  if (len > ssl->buffer->len)
-    {
-      r = ssl->buffer->len;
-      memcpy (buffer, ssl->buffer->str, r);
-      g_string_truncate (ssl->buffer, 0);
-    }
-  else
-    {
-      r = len;
-      memcpy (buffer, ssl->buffer->str, r);
-      g_string_erase (ssl->buffer, 0, r);
-    }
-  if (r == 0)
-    {
-      gnutls_transport_set_errno (ssl->session, EAGAIN);
-      return -1;
-    }
-  return r;
-}
-
-static void
-ssl_server_connect (net_hook_t *hook)
-{
-  struct ssl_data *ssl = hook->data;
-  int error;
-  gnutls_transport_set_ptr (ssl->session, (gnutls_transport_ptr_t) hook);
-  gnutls_transport_set_push_function (ssl->session, ssl_push);
-  gnutls_transport_set_pull_function (ssl->session, ssl_pull);
-  ssl->handshaking = TRUE;
-  if ((error = gnutls_handshake (ssl->session)) < 0)
-    {
-      g_message ("%satal error while doing TLS handshaking.\n",
-                 gnutls_error_is_fatal (error) ? "F" : "Nonf");
-      g_message ("%s\n", gnutls_strerror (error));
-    }
-  ssl->handshaking = FALSE;
-}
-
-static void
-ssl_server_close (net_hook_t *hook)
-{
-  struct ssl_data *ssl = hook->data;
-  if (hook->peer)
-    {
-      hook->peer->peer = NULL;
-      gnet_conn_disconnect (hook->peer->conn);
-    }
-  gnet_conn_delete (hook->conn);
-  if (ssl != NULL)
-    {
-      gnutls_bye (ssl->session, GNUTLS_SHUT_RDWR);
-      ssl_data_destroy (ssl);
-    }
-  g_slice_free (net_hook_t, hook);
-}
-
-static void
-ssl_server_write (net_hook_t *hook)
-{
-}
-
-static void
-ssl_server_read (net_hook_t *hook, gchar *buffer, size_t len)
-{
-  struct ssl_data *ssl = hook->data;
-  int r;
-  g_string_append_len (ssl->buffer, buffer, len);
-  do
-    {
-      r = gnutls_record_recv (ssl->session, buffer, len);
-      if (r > 0)
-        gnet_conn_write (hook->peer->conn, buffer, r);
-    } while (r > 0);
-}
-
-static void
-ssl_server_error (net_hook_t *hook)
-{
-  g_message ("Error in POP3 client connection.");
-}
-
-static net_hook_t *
-ssl_server_hook_new (net_hook_t *client_hook, char *server)
-{
-  net_hook_t *hook;
-  hook = g_slice_new (net_hook_t);
-  hook->conn = gnet_conn_new (server, 995, nethook_event, hook);
-  hook->peer = client_hook;
-  hook->server = TRUE;
-  hook->connect = ssl_server_connect;
-  hook->close = ssl_server_close;
-  hook->write = ssl_server_write;
-  hook->read = ssl_server_read;
-  hook->data = ssl_data_new (server);
-  gnet_conn_connect (hook->conn);
-  gnet_conn_read (hook->conn);
-  return hook;
-}
-
 static void
 ssl_connect (net_hook_t *hook)
 {
diff --git a/ssl.h b/ssl.h
index c292008..61cc68f 100644 (file)
--- a/ssl.h
+++ b/ssl.h
 #include <gnet.h>
 #include "nethook.h"
 
+struct ssl_data
+{
+  char *server;
+  gnutls_session_t session;
+  GString *buffer;
+  gboolean handshaking;
+};
+
 net_hook_t* ssl_hook_new (GConn*, char*);
 void ssl_destroy (net_hook_t*);
 
+net_hook_t * ssl_server_hook_new (net_hook_t *, char *);
+
 #endif
diff --git a/ssl_server.c b/ssl_server.c
new file mode 100644 (file)
index 0000000..4d39e34
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+** Copyright (C) 2006 Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
+** Copyright (C) 2009 Thadeu Lima de Souza Cascardo <cascardo@holoscopio.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; either version 2 of the License, or
+** (at your option) any later version.
+**  
+** 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.
+**  
+*/
+
+#include <gnutls/gnutls.h>
+#include <gnet.h>
+#include <glib.h>
+#include <string.h>
+#include <errno.h>
+#include "ssl.h"
+
+static struct ssl_data *
+ssl_data_new (char *server)
+{
+  struct ssl_data *ssl;
+  int kx_prio[] = {GNUTLS_KX_RSA, 0};
+  gnutls_certificate_credentials cred;
+  gnutls_certificate_allocate_credentials (&cred);
+  ssl = g_slice_new (struct ssl_data);
+  ssl->server = g_strdup (server);
+  gnutls_init (&ssl->session, GNUTLS_CLIENT);
+  gnutls_set_default_priority (ssl->session);
+  gnutls_set_default_priority (ssl->session);
+  gnutls_kx_set_priority (ssl->session, kx_prio);
+  gnutls_credentials_set (ssl->session, GNUTLS_CRD_CERTIFICATE, cred);
+  ssl->buffer = g_string_sized_new (4096);
+  ssl->handshaking = FALSE;
+  return ssl;
+}
+
+static void
+ssl_data_destroy (struct ssl_data *ssl)
+{
+  gnutls_deinit (ssl->session);
+  g_free (ssl->server);
+  g_string_free (ssl->buffer, TRUE);
+  g_slice_free (struct ssl_data, ssl);
+}
+
+static ssize_t
+ssl_push (gnutls_transport_ptr_t ptr, const void *buffer, size_t len)
+{
+  net_hook_t *hook = ptr;
+  struct ssl_data *ssl = hook->data;
+  int r;
+  if (ssl->handshaking == TRUE)
+    {
+      g_io_channel_write_chars (hook->conn->iochannel, buffer, len,
+                                &r, NULL);
+      return r;
+    }
+  gnet_conn_write (hook->conn, (void *) buffer, len);
+  return len;
+}
+
+static ssize_t
+ssl_pull (gnutls_transport_ptr_t ptr, void *buffer, size_t len)
+{
+  net_hook_t *hook = ptr;
+  struct ssl_data *ssl = hook->data;
+  int r;
+  if (ssl->handshaking == TRUE)
+    {
+      g_io_channel_read_chars (hook->conn->iochannel, buffer, len,
+                               &r, NULL);
+      return r;
+    }
+  if (len > ssl->buffer->len)
+    {
+      r = ssl->buffer->len;
+      memcpy (buffer, ssl->buffer->str, r);
+      g_string_truncate (ssl->buffer, 0);
+    }
+  else
+    {
+      r = len;
+      memcpy (buffer, ssl->buffer->str, r);
+      g_string_erase (ssl->buffer, 0, r);
+    }
+  if (r == 0)
+    {
+      gnutls_transport_set_errno (ssl->session, EAGAIN);
+      return -1;
+    }
+  return r;
+}
+
+static void
+ssl_server_connect (net_hook_t *hook)
+{
+  struct ssl_data *ssl = hook->data;
+  int error;
+  gnutls_transport_set_ptr (ssl->session, (gnutls_transport_ptr_t) hook);
+  gnutls_transport_set_push_function (ssl->session, ssl_push);
+  gnutls_transport_set_pull_function (ssl->session, ssl_pull);
+  ssl->handshaking = TRUE;
+  if ((error = gnutls_handshake (ssl->session)) < 0)
+    {
+      g_message ("%satal error while doing TLS handshaking.\n",
+                 gnutls_error_is_fatal (error) ? "F" : "Nonf");
+      g_message ("%s\n", gnutls_strerror (error));
+    }
+  ssl->handshaking = FALSE;
+}
+
+static void
+ssl_server_close (net_hook_t *hook)
+{
+  struct ssl_data *ssl = hook->data;
+  if (hook->peer)
+    {
+      hook->peer->peer = NULL;
+      gnet_conn_disconnect (hook->peer->conn);
+    }
+  gnet_conn_delete (hook->conn);
+  if (ssl != NULL)
+    {
+      gnutls_bye (ssl->session, GNUTLS_SHUT_RDWR);
+      ssl_data_destroy (ssl);
+    }
+  g_slice_free (net_hook_t, hook);
+}
+
+static void
+ssl_server_write (net_hook_t *hook)
+{
+}
+
+static void
+ssl_server_read (net_hook_t *hook, gchar *buffer, size_t len)
+{
+  struct ssl_data *ssl = hook->data;
+  int r;
+  g_string_append_len (ssl->buffer, buffer, len);
+  do
+    {
+      r = gnutls_record_recv (ssl->session, buffer, len);
+      if (r > 0)
+        gnet_conn_write (hook->peer->conn, buffer, r);
+    } while (r > 0);
+}
+
+static void
+ssl_server_error (net_hook_t *hook)
+{
+  g_message ("Error in POP3 client connection.");
+}
+
+net_hook_t *
+ssl_server_hook_new (net_hook_t *client_hook, char *server)
+{
+  net_hook_t *hook;
+  hook = g_slice_new (net_hook_t);
+  hook->conn = gnet_conn_new (server, 995, nethook_event, hook);
+  hook->peer = client_hook;
+  hook->server = TRUE;
+  hook->connect = ssl_server_connect;
+  hook->close = ssl_server_close;
+  hook->write = ssl_server_write;
+  hook->read = ssl_server_read;
+  hook->data = ssl_data_new (server);
+  gnet_conn_connect (hook->conn);
+  gnet_conn_read (hook->conn);
+  return hook;
+}