]> jfr.im git - irc/hexchat/hexchat.git/commitdiff
WIP: Use GSocketClient for IRC connections origin/wip/gsocketclient
authorPatrick Griffis <redacted>
Wed, 14 Jul 2021 03:09:26 +0000 (22:09 -0500)
committerPatrick Griffis <redacted>
Wed, 14 Jul 2021 03:09:26 +0000 (22:09 -0500)
TODO:
- Proxy support (some will be lost along the way)
- Remove all OpenSSL usage from fe-gtk?
- DCC support?

14 files changed:
meson.build
src/common/dcc.c
src/common/hexchat.c
src/common/hexchat.h
src/common/meson.build
src/common/outbound.c
src/common/server.c
src/common/server.h
src/common/ssl.c [deleted file]
src/common/ssl.h [deleted file]
src/common/text.c
src/common/textevents.in
src/common/util.c
src/common/util.h

index fe5f245d4b13c0517e21b5d7a31b2f36231e2b58..40a37ef9e77bd3a1a110ed67f186bbc2b80e735c 100644 (file)
@@ -13,7 +13,7 @@ gnome = import('gnome')
 cc = meson.get_compiler('c')
 
 
-libgio_dep = dependency('gio-2.0', version: '>= 2.34.0')
+libgio_dep = dependency('gio-2.0', version: '>= 2.44.0')
 libgmodule_dep = dependency('gmodule-2.0')
 
 libcanberra_dep = dependency('libcanberra', version: '>= 0.22',
@@ -46,8 +46,8 @@ config_h.set('G_DISABLE_SINGLE_INCLUDES', true)
 config_h.set('GTK_DISABLE_DEPRECATED', true)
 config_h.set('GTK_DISABLE_SINGLE_INCLUDES', true)
 config_h.set('GDK_PIXBUF_DISABLE_SINGLE_INCLUDES', true)
-config_h.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_34')
-config_h.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_34')
+config_h.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_44')
+config_h.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_44')
 
 # Detected features
 config_h.set('HAVE_MEMRCHR', cc.has_function('memrchr'))
index df129e68de7058586a8326339809b90bcfb2a991..c5f3c97c17f66d4e6b144229fc295f41a649542f 100644 (file)
@@ -487,6 +487,19 @@ dcc_notify_kill (struct server *serv)
        }
 }
 
+static int
+tcp_send_real (int sok, GIConv write_converter, char *buf, int len)
+{
+       int ret;
+
+       gsize buf_encoded_len;
+       gchar *buf_encoded = text_convert_invalid (buf, len, write_converter, arbitrary_encoding_fallback_string, &buf_encoded_len);
+       ret = send (sok, buf_encoded, buf_encoded_len, 0);
+       g_free (buf_encoded);
+
+       return ret;
+}
+
 struct DCC *
 dcc_write_chat (char *nick, char *text)
 {
@@ -499,7 +512,7 @@ dcc_write_chat (char *nick, char *text)
        if (dcc && dcc->dccstat == STAT_ACTIVE)
        {
                len = strlen (text);
-               tcp_send_real (NULL, dcc->sok, dcc->serv->write_converter, text, len);
+               tcp_send_real (dcc->sok, dcc->serv->write_converter, text, len);
                send (dcc->sok, "\n", 1, 0);
                dcc->size += len;
                fe_dcc_update (dcc);
@@ -1656,7 +1669,8 @@ dcc_listen_init (struct DCC *dcc, session *sess)
        memset (&SAddr, 0, sizeof (struct sockaddr_in));
 
        len = sizeof (SAddr);
-       getsockname (dcc->serv->sok, (struct sockaddr *) &SAddr, &len);
+       /* TODO: Get rid of raw socket usage */
+       getsockname (g_socket_get_fd (dcc->serv->socket), (struct sockaddr *) &SAddr, &len);
 
        SAddr.sin_family = AF_INET;
 
index 3ba7ed6d5567937e7a448a8391000785c1aa1eb1..ba5e93078be6c3b0858751baf43f8de403e6d9a8 100644 (file)
@@ -266,7 +266,7 @@ lag_check (void)
                                EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL,
                                                                 NULL, NULL, 0);
                                if (prefs.hex_net_auto_reconnect)
-                                       serv->auto_reconnect (serv, FALSE, -1);
+                                       serv->auto_reconnect (serv, FALSE, NULL);
                        }
                        else
                        {
index 5c9949a291ff2ba83c90e103d6d624fe09ea7234..c42d620d4b2c1f9c9e221af03c9d55154c0bc532 100644 (file)
 #include "history.h"
 #include "tree.h"
 
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>                 /* SSL_() */
-#endif
-
 #ifdef __EMX__                                           /* for o/s 2 */
 #define OFLAGS O_BINARY
 #define g_ascii_strcasecmp stricmp
@@ -434,10 +430,10 @@ typedef struct server
 {
        /*  server control operations (in server*.c) */
        void (*connect)(struct server *, char *hostname, int port, int no_login);
-       void (*disconnect)(struct session *, int sendquit, int err);
+       void (*disconnect)(struct session *, int sendquit, GError *err);
        int  (*cleanup)(struct server *);
        void (*flush_queue)(struct server *);
-       void (*auto_reconnect)(struct server *, int send_quit, int err);
+       void (*auto_reconnect)(struct server *, int send_quit, GError *err);
        /* irc protocol functions (in proto*.c) */
        void (*p_inline)(struct server *, char *buf, int len);
        void (*p_invite)(struct server *, char *channel, char *nick);
@@ -474,29 +470,18 @@ typedef struct server
        int (*p_cmp)(const char *s1, const char *s2);
 
        int port;
-       int sok;                                        /* is equal to sok4 or sok6 (the one we are using) */
-       int sok4;                                       /* tcp4 socket */
-       int sok6;                                       /* tcp6 socket */
-       int proxy_type;
-       int proxy_sok;                          /* Additional information for MS Proxy beast */
-       int proxy_sok4;
-       int proxy_sok6;
        int id;                                 /* unique ID number (for plugin API) */
 
        /* dcc_ip moved from hexchatprefs to make it per-server */
        guint32 dcc_ip;
 
-#ifdef USE_OPENSSL
-       SSL_CTX *ctx;
-       SSL *ssl;
-       int ssl_do_connect_tag;
-#else
-       void *ssl;
-#endif
-       int childread;
-       int childwrite;
-       int childpid;
-       int iotag;
+       GSocketClient *socket_client;
+       GSocketConnection *socket_conn;
+       GSocket *socket; /* Owned by socket_conn */
+       GCancellable *connection_cancellable;
+       GTlsCertificate *client_cert;
+       GSource *socket_read_source;
+
        int recondelay_tag;                             /* reconnect delay timeout */
        int joindelay_tag;                              /* waiting before we send JOIN */
        char hostname[128];                             /* real ip number */
index 6ca0f20c1f4da4fb703d9050779a621ed26dfb80..245ab335c95af066322c98e2b719e93c759e47d5 100644 (file)
@@ -74,7 +74,6 @@ textevents = custom_target('textevents',
 #   HAVE_GTK_MAC
 
 if libssl_dep.found()
-  common_sources += 'ssl.c'
   common_deps += libssl_dep
 endif
 
index 70fcd436a72bb61ccf2c507de2eb83266f36418f..a99809ebac430b6406351c65afc54f5216822b0c 100644 (file)
@@ -903,8 +903,8 @@ cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[])
        while (list)
        {
                v = (struct server *) list->data;
-               sprintf (tbuf, "%p %-5d %s\n",
-                                       v, v->sok, v->servername);
+               sprintf (tbuf, "%p %s\n",
+                                       v, v->servername);
                PrintText (sess, tbuf);
                list = list->next;
        }
@@ -1414,7 +1414,7 @@ cmd_devoice (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 static int
 cmd_discon (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-       sess->server->disconnect (sess, TRUE, -1);
+       sess->server->disconnect (sess, TRUE, NULL);
        return TRUE;
 }
 
@@ -1956,7 +1956,7 @@ cmd_quit (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
        if (*word_eol[2])
                sess->quitreason = word_eol[2];
-       sess->server->disconnect (sess, TRUE, -1);
+       sess->server->disconnect (sess, TRUE, NULL);
        sess->quitreason = NULL;
        return 2;
 }
@@ -3216,7 +3216,7 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[])
                {
                        serv = list->data;
                        if (serv->connected)
-                               serv->auto_reconnect (serv, TRUE, -1);
+                               serv->auto_reconnect (serv, TRUE, NULL);
                        list = list->next;
                }
        }
@@ -3249,11 +3249,11 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[])
                if (*word[3+offset])
                        serv->port = atoi (word[3+offset]);
                safe_strcpy (serv->hostname, word[2+offset], sizeof (serv->hostname));
-               serv->auto_reconnect (serv, TRUE, -1);
+               serv->auto_reconnect (serv, TRUE, NULL);
        }
        else
        {
-               serv->auto_reconnect (serv, TRUE, -1);
+               serv->auto_reconnect (serv, TRUE, NULL);
        }
        prefs.hex_net_reconnect_delay = tmp;
 
@@ -3294,6 +3294,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
        if (!word[2][0])
                return FALSE;
 
+#if 0
        addr = dcc_get_my_address (sess);
        if (addr == 0)
        {
@@ -3313,6 +3314,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[])
                g_snprintf (tbuf, 512, "DCC SEND %s", word_eol[2]);
 
        handle_command (sess, tbuf, FALSE);
+#endif
 
        return TRUE;
 }
index 4f809fa8f9c28ec544c202eb6416c2393f9b16db..442c39640dd1b51a2637b927694d83e31952040b 100644 (file)
 #include <errno.h>
 #include <fcntl.h>
 
-#define WANTSOCKET
-#define WANTARPA
-#include "inet.h"
-
-#ifdef WIN32
-#include <winbase.h>
-#include <io.h>
-#else
-#include <signal.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#endif
-
 #include "hexchat.h"
 #include "fe.h"
 #include "cfgfiles.h"
 #include "servlist.h"
 #include "server.h"
 
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>                 /* SSL_() */
-#include <openssl/err.h>                 /* ERR_() */
-#include "ssl.h"
-#endif
-
-#ifdef USE_OPENSSL
-/* local variables */
-static struct session *g_sess = NULL;
-#endif
 
 static GSList *away_list = NULL;
 GSList *serv_list = NULL;
 
-static void auto_reconnect (server *serv, int send_quit, int err);
-static void server_disconnect (session * sess, int sendquit, int err);
+static void auto_reconnect (server *serv, int send_quit, GError *err);
+static void server_disconnect (session * sess, int sendquit, GError *err);
 static int server_cleanup (server * serv);
 static void server_connect (server *serv, char *hostname, int port, int no_login);
 
-static void
-write_error (char *message, GError **error)
-{
-       if (error == NULL || *error == NULL) {
-               return;
-       }
-       g_printerr ("%s: %s\n", message, (*error)->message);
-       g_clear_error (error);
-}
-
-/* actually send to the socket. This might do a character translation or
-   send via SSL. server/dcc both use this function. */
-
-int
-tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len)
-{
-       int ret;
-
-       gsize buf_encoded_len;
-       gchar *buf_encoded = text_convert_invalid (buf, len, write_converter, arbitrary_encoding_fallback_string, &buf_encoded_len);
-#ifdef USE_OPENSSL
-       if (!ssl)
-               ret = send (sok, buf_encoded, buf_encoded_len, 0);
-       else
-               ret = _SSL_send (ssl, buf_encoded, buf_encoded_len);
-#else
-       ret = send (sok, buf_encoded, buf_encoded_len, 0);
-#endif
-       g_free (buf_encoded);
-
-       return ret;
-}
-
 static int
 server_send_real (server *serv, char *buf, int len)
 {
-       fe_add_rawlog (serv, buf, len, TRUE);
+       gsize buf_encoded_len;
+       gchar *buf_encoded;
+
+       buf_encoded = text_convert_invalid (buf, len, serv->write_converter, arbitrary_encoding_fallback_string, &buf_encoded_len);
 
-       url_check_line (buf);
+       fe_add_rawlog (serv, buf_encoded, buf_encoded_len, TRUE);
+       url_check_line (buf_encoded);
 
-       return tcp_send_real (serv->ssl, serv->sok, serv->write_converter, buf, len);
+       // TODO: Error and cancellable
+       return g_socket_send (serv->socket, buf_encoded, buf_encoded_len, NULL, NULL);
 }
 
 /* new throttling system, uses the same method as the Undernet
@@ -262,20 +211,6 @@ tcp_sendf (server *serv, const char *fmt, ...)
        tcp_send_len (serv, send_buf, len);
 }
 
-static int
-close_socket_cb (gpointer sok)
-{
-       closesocket (GPOINTER_TO_INT (sok));
-       return 0;
-}
-
-static void
-close_socket (int sok)
-{
-       /* close the socket in 5 seconds so the QUIT message is not lost */
-       fe_timeout_add_seconds (5, close_socket_cb, GINT_TO_POINTER (sok));
-}
-
 /* handle 1 line of text received from the server */
 
 static void
@@ -298,32 +233,23 @@ server_inline (server *serv, char *line, gssize len)
 /* read data from socket */
 
 static gboolean
-server_read (GIOChannel *source, GIOCondition condition, server *serv)
+on_socket_ready (GSocket *socket, GIOCondition condition, server *serv)
 {
-       int sok = serv->sok;
-       int error, i, len;
+       GError *error = NULL;
+       gssize len;
+       int i;
        char lbuf[2050];
 
        while (1)
        {
-#ifdef USE_OPENSSL
-               if (!serv->ssl)
-#endif
-                       len = recv (sok, lbuf, sizeof (lbuf) - 2, 0);
-#ifdef USE_OPENSSL
-               else
-                       len = _SSL_recv (serv->ssl, lbuf, sizeof (lbuf) - 2);
-#endif
-               if (len < 1)
+               len = g_socket_receive (socket, lbuf, sizeof (lbuf) - 2, NULL, &error);
+               if (error)
                {
-                       error = 0;
-                       if (len < 0)
+                       if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
                        {
-                               if (would_block ())
-                                       return TRUE;
-                               error = sock_error ();
+                               /* Fall through */
                        }
-                       if (!serv->end_of_motd)
+                       else if (!serv->end_of_motd)
                        {
                                server_disconnect (serv->server_session, FALSE, error);
                                if (!servlist_cycle (serv))
@@ -331,22 +257,26 @@ server_read (GIOChannel *source, GIOCondition condition, server *serv)
                                        if (prefs.hex_net_auto_reconnect)
                                                auto_reconnect (serv, FALSE, error);
                                }
-                       } else
+                       }
+                       else
                        {
                                if (prefs.hex_net_auto_reconnect)
                                        auto_reconnect (serv, FALSE, error);
                                else
                                        server_disconnect (serv->server_session, FALSE, error);
                        }
-                       return TRUE;
+
+                       g_error_free (error);
+                       return G_SOURCE_CONTINUE;
                }
 
-               i = 0;
 
+               i = 0;
                lbuf[len] = 0;
 
                while (i < len)
                {
+                       // FIXME: Unsafe?
                        switch (lbuf[i])
                        {
                        case '\r':
@@ -378,8 +308,12 @@ server_connected (server * serv)
        serv->ping_recv = time (0);
        serv->lag_sent = 0;
        serv->connected = TRUE;
-       set_nonblocking (serv->sok);
-       serv->iotag = fe_input_add (serv->sok, FIA_READ|FIA_EX, server_read, serv);
+
+       serv->socket_read_source = g_socket_create_source (serv->socket, G_IO_IN|G_IO_ERR, NULL);
+       g_source_set_callback (serv->socket_read_source, (GSourceFunc)on_socket_ready, serv, NULL);
+       g_source_attach (serv->socket_read_source, g_main_context_default ());
+       g_source_unref (serv->socket_read_source);
+
        if (!serv->no_login)
        {
                EMIT_SIGNAL (XP_TE_CONNECTED, serv->server_session, NULL, NULL, NULL,
@@ -425,11 +359,7 @@ server_close_pipe (int *pipefd)    /* see comments below */
 static void
 server_stopconnecting (server * serv)
 {
-       if (serv->iotag)
-       {
-               fe_input_remove (serv->iotag);
-               serv->iotag = 0;
-       }
+       g_assert (!serv->socket_read_source);
 
        if (serv->joindelay_tag)
        {
@@ -437,32 +367,8 @@ server_stopconnecting (server * serv)
                serv->joindelay_tag = 0;
        }
 
-#ifndef WIN32
-       /* kill the child process trying to connect */
-       kill (serv->childpid, SIGKILL);
-       waitpid (serv->childpid, NULL, 0);
-
-       close (serv->childwrite);
-       close (serv->childread);
-#else
-       PostThreadMessage (serv->childpid, WM_QUIT, 0, 0);
-
-       {
-               /* if we close the pipe now, giowin32 will crash. */
-               int *pipefd = g_new (int, 2);
-               pipefd[0] = serv->childwrite;
-               pipefd[1] = serv->childread;
-               g_idle_add ((GSourceFunc)server_close_pipe, pipefd);
-       }
-#endif
-
-#ifdef USE_OPENSSL
-       if (serv->ssl_do_connect_tag)
-       {
-               fe_timeout_remove (serv->ssl_do_connect_tag);
-               serv->ssl_do_connect_tag = 0;
-       }
-#endif
+       if (serv->connection_cancellable)
+               g_cancellable_cancel (serv->connection_cancellable);
 
        fe_progressbar_end (serv);
 
@@ -470,223 +376,6 @@ server_stopconnecting (server * serv)
        fe_server_event (serv, FE_SE_DISCONNECT, 0);
 }
 
-#ifdef USE_OPENSSL
-#define        SSLTMOUT        90                                /* seconds */
-static void
-ssl_cb_info (SSL * s, int where, int ret)
-{
-/*     char buf[128];*/
-
-
-       return;                                                   /* FIXME: make debug level adjustable in serverlist or settings */
-
-/*     g_snprintf (buf, sizeof (buf), "%s (%d)", SSL_state_string_long (s), where);
-       if (g_sess)
-               EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
-       else
-               fprintf (stderr, "%s\n", buf);*/
-}
-
-static int
-ssl_cb_verify (int ok, X509_STORE_CTX * ctx)
-{
-       char subject[256];
-       char issuer[256];
-       char buf[512];
-       X509 *current_cert = X509_STORE_CTX_get_current_cert (ctx);
-
-       if (!current_cert)
-               return TRUE;
-
-       X509_NAME_oneline (X509_get_subject_name (current_cert),
-                          subject, sizeof (subject));
-       X509_NAME_oneline (X509_get_issuer_name (current_cert),
-                          issuer, sizeof (issuer));
-
-       g_snprintf (buf, sizeof (buf), "* Subject: %s", subject);
-       EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
-       g_snprintf (buf, sizeof (buf), "* Issuer: %s", issuer);
-       EMIT_SIGNAL (XP_TE_SSLMESSAGE, g_sess, buf, NULL, NULL, NULL, 0);
-
-       return TRUE;
-}
-
-static int
-ssl_do_connect (server * serv)
-{
-       char buf[256]; // ERR_error_string() MUST have this size
-
-       g_sess = serv->server_session;
-
-       /* Set SNI hostname before connect */
-       SSL_set_tlsext_host_name(serv->ssl, serv->hostname);
-
-       if (SSL_connect (serv->ssl) <= 0)
-       {
-               char err_buf[128];
-               int err;
-
-               g_sess = NULL;
-               if ((err = ERR_get_error ()) > 0)
-               {
-                       ERR_error_string (err, err_buf);
-                       g_snprintf (buf, sizeof (buf), "(%d) %s", err, err_buf);
-                       EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
-                                                        NULL, NULL, 0);
-
-                       if (ERR_GET_REASON (err) == SSL_R_WRONG_VERSION_NUMBER)
-                               PrintText (serv->server_session, _("Are you sure this is a SSL capable server and port?\n"));
-
-                       server_cleanup (serv);
-
-                       if (prefs.hex_net_auto_reconnectonfail)
-                               auto_reconnect (serv, FALSE, -1);
-
-                       return (0);                               /* remove it (0) */
-               }
-       }
-       g_sess = NULL;
-
-       if (SSL_is_init_finished (serv->ssl))
-       {
-               struct cert_info cert_info;
-               struct chiper_info *chiper_info;
-               int verify_error;
-               int i;
-
-               if (!_SSL_get_cert_info (&cert_info, serv->ssl))
-               {
-                       g_snprintf (buf, sizeof (buf), "* Certification info:");
-                       EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                        NULL, 0);
-                       g_snprintf (buf, sizeof (buf), "  Subject:");
-                       EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                        NULL, 0);
-                       for (i = 0; cert_info.subject_word[i]; i++)
-                       {
-                               g_snprintf (buf, sizeof (buf), "    %s", cert_info.subject_word[i]);
-                               EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                                NULL, 0);
-                       }
-                       g_snprintf (buf, sizeof (buf), "  Issuer:");
-                       EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                        NULL, 0);
-                       for (i = 0; cert_info.issuer_word[i]; i++)
-                       {
-                               g_snprintf (buf, sizeof (buf), "    %s", cert_info.issuer_word[i]);
-                               EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                                NULL, 0);
-                       }
-                       g_snprintf (buf, sizeof (buf), "  Public key algorithm: %s (%d bits)",
-                                                cert_info.algorithm, cert_info.algorithm_bits);
-                       EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                        NULL, 0);
-                       /*if (cert_info.rsa_tmp_bits)
-                       {
-                               g_snprintf (buf, sizeof (buf),
-                                                        "  Public key algorithm uses ephemeral key with %d bits",
-                                                        cert_info.rsa_tmp_bits);
-                               EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                                NULL, 0);
-                       }*/
-                       g_snprintf (buf, sizeof (buf), "  Sign algorithm %s",
-                                                cert_info.sign_algorithm/*, cert_info.sign_algorithm_bits*/);
-                       EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                        NULL, 0);
-                       g_snprintf (buf, sizeof (buf), "  Valid since %s to %s",
-                                                cert_info.notbefore, cert_info.notafter);
-                       EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                        NULL, 0);
-               } else
-               {
-                       g_snprintf (buf, sizeof (buf), "No Certificate");
-                       goto conn_fail;
-               }
-
-               chiper_info = _SSL_get_cipher_info (serv->ssl); /* static buffer */
-               g_snprintf (buf, sizeof (buf), "* Cipher info:");
-               EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
-                                                0);
-               g_snprintf (buf, sizeof (buf), "  Version: %s, cipher %s (%u bits)",
-                                        chiper_info->version, chiper_info->chiper,
-                                        chiper_info->chiper_bits);
-               EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL,
-                                                0);
-
-               verify_error = SSL_get_verify_result (serv->ssl);
-               switch (verify_error)
-               {
-               case X509_V_OK:
-                       {
-                               X509 *cert = SSL_get_peer_certificate (serv->ssl);
-                               int hostname_err;
-                               if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0)
-                               {
-                                       g_snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s",
-                                                        hostname_err, serv->accept_invalid_cert ? " -- Ignored" : "");
-                                       if (serv->accept_invalid_cert)
-                                               EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0);
-                                       else
-                                               goto conn_fail;
-                               }
-                               break;
-                       }
-                       /* g_snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
-                       /* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
-               case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
-               case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
-               case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
-               case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
-               case X509_V_ERR_CERT_HAS_EXPIRED:
-                       if (serv->accept_invalid_cert)
-                       {
-                               g_snprintf (buf, sizeof (buf), "* Verify E: %s.? (%d) -- Ignored",
-                                                        X509_verify_cert_error_string (verify_error),
-                                                        verify_error);
-                               EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
-                                                                NULL, 0);
-                               break;
-                       }
-               default:
-                       g_snprintf (buf, sizeof (buf), "%s.? (%d)",
-                                                X509_verify_cert_error_string (verify_error),
-                                                verify_error);
-conn_fail:
-                       EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL,
-                                                        NULL, 0);
-
-                       server_cleanup (serv);
-
-                       return (0);
-               }
-
-               server_stopconnecting (serv);
-
-               /* activate gtk poll */
-               server_connected (serv);
-
-               return (0);                                       /* remove it (0) */
-       } else
-       {
-               SSL_SESSION *session = SSL_get_session (serv->ssl);
-               if (session && SSL_SESSION_get_time (session) + SSLTMOUT < time (NULL))
-               {
-                       g_snprintf (buf, sizeof (buf), "SSL handshake timed out");
-                       EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL,
-                                                        NULL, NULL, 0);
-                       server_cleanup (serv); /* ->connecting = FALSE */
-
-                       if (prefs.hex_net_auto_reconnectonfail)
-                               auto_reconnect (serv, FALSE, -1);
-
-                       return (0);                               /* remove it (0) */
-               }
-
-               return (1);                                       /* call it more (1) */
-       }
-}
-#endif
-
 static int
 timeout_auto_reconnect (server *serv)
 {
@@ -702,7 +391,7 @@ timeout_auto_reconnect (server *serv)
 }
 
 static void
-auto_reconnect (server *serv, int send_quit, int err)
+auto_reconnect (server *serv, int send_quit, GError *error)
 {
        session *s;
        int del;
@@ -727,17 +416,13 @@ auto_reconnect (server *serv, int send_quit, int err)
        }
 
        if (serv->connected)
-               server_disconnect (serv->server_session, send_quit, err);
+               server_disconnect (serv->server_session, send_quit, error);
 
        del = prefs.hex_net_reconnect_delay * 1000;
        if (del < 1000)
                del = 500;                                /* so it doesn't block the gui */
 
-#ifndef WIN32
-       if (err == -1 || err == 0 || err == ECONNRESET || err == ETIMEDOUT)
-#else
-       if (err == -1 || err == 0 || err == WSAECONNRESET || err == WSAETIMEDOUT)
-#endif
+       if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED) || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT))
                serv->reconnect_away = serv->is_away;
 
        /* is this server in a reconnect delay? remove it! */
@@ -764,32 +449,6 @@ server_flush_queue (server *serv)
 static void
 server_connect_success (server *serv)
 {
-#ifdef USE_OPENSSL
-#define        SSLDOCONNTMOUT  300
-       if (serv->use_ssl)
-       {
-               char *err;
-
-               /* it'll be a memory leak, if connection isn't terminated by
-                  server_cleanup() */
-               if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify, NULL)))
-               {
-                       EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
-                                                        NULL, NULL, 0);
-                       server_cleanup (serv);  /* ->connecting = FALSE */
-                       return;
-               }
-               serv->ssl = _SSL_socket (serv->ctx, serv->sok);
-               /* FIXME: it'll be needed by new servers */
-               /* send(serv->sok, "STLS\r\n", 6, 0); sleep(1); */
-               set_nonblocking (serv->sok);
-               serv->ssl_do_connect_tag = fe_timeout_add (SSLDOCONNTMOUT,
-                                                                                                                                ssl_do_connect, serv);
-               return;
-       }
-
-       serv->ssl = NULL;
-#endif
        server_stopconnecting (serv);   /* ->connecting = FALSE */
        /* activate glib poll */
        server_connected (serv);
@@ -797,6 +456,7 @@ server_connect_success (server *serv)
 
 /* receive info from the child-process about connection progress */
 
+#if 0
 static gboolean
 server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
 {
@@ -814,87 +474,7 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
                waitline2 (source, tbuf, sizeof tbuf);
                PrintText (serv->server_session, tbuf);
                break;
-       case '1':                                                 /* unknown host */
-               server_stopconnecting (serv);
-               closesocket (serv->sok4);
-               if (serv->proxy_sok4 != -1)
-                       closesocket (serv->proxy_sok4);
-               if (serv->sok6 != -1)
-                       closesocket (serv->sok6);
-               if (serv->proxy_sok6 != -1)
-                       closesocket (serv->proxy_sok6);
-               EMIT_SIGNAL (XP_TE_UKNHOST, sess, NULL, NULL, NULL, NULL, 0);
-               if (!servlist_cycle (serv))
-                       if (prefs.hex_net_auto_reconnectonfail)
-                               auto_reconnect (serv, FALSE, -1);
-               break;
-       case '2':                                                 /* connection failed */
-               waitline2 (source, tbuf, sizeof tbuf);
-               server_stopconnecting (serv);
-               closesocket (serv->sok4);
-               if (serv->proxy_sok4 != -1)
-                       closesocket (serv->proxy_sok4);
-               if (serv->sok6 != -1)
-                       closesocket (serv->sok6);
-               if (serv->proxy_sok6 != -1)
-                       closesocket (serv->proxy_sok6);
-               EMIT_SIGNAL (XP_TE_CONNFAIL, sess, errorstring (atoi (tbuf)), NULL,
-                                                NULL, NULL, 0);
-               if (!servlist_cycle (serv))
-                       if (prefs.hex_net_auto_reconnectonfail)
-                               auto_reconnect (serv, FALSE, -1);
-               break;
-       case '3':                                                 /* gethostbyname finished */
-               waitline2 (source, host, sizeof host);
-               waitline2 (source, ip, sizeof ip);
-               waitline2 (source, outbuf, sizeof outbuf);
-               EMIT_SIGNAL (XP_TE_CONNECT, sess, host, ip, outbuf, NULL, 0);
-               break;
-       case '4':                                                 /* success */
-               waitline2 (source, tbuf, sizeof (tbuf));
-               serv->sok = atoi (tbuf);
-               /* close the one we didn't end up using */
-               if (serv->sok == serv->sok4)
-                       closesocket (serv->sok6);
-               else
-                       closesocket (serv->sok4);
-               if (serv->proxy_sok != -1)
-               {
-                       if (serv->proxy_sok == serv->proxy_sok4)
-                               closesocket (serv->proxy_sok6);
-                       else
-                               closesocket (serv->proxy_sok4);
-               }
-
-               {
-                       struct sockaddr_storage addr;
-                       int addr_len = sizeof (addr);
-                       guint16 port;
-                       ircnet *net = serv->network;
 
-                       if (!getsockname (serv->sok, (struct sockaddr *)&addr, &addr_len))
-                       {
-                               if (addr.ss_family == AF_INET)
-                                       port = ntohs(((struct sockaddr_in *)&addr)->sin_port);
-                               else
-                                       port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port);
-
-                               g_snprintf (outbuf, sizeof (outbuf), "IDENTD %"G_GUINT16_FORMAT" ", port);
-                               if (net && net->user && !(net->flags & FLAG_USE_GLOBAL))
-                                       g_strlcat (outbuf, net->user, sizeof (outbuf));
-                               else
-                                       g_strlcat (outbuf, prefs.hex_irc_user_name, sizeof (outbuf));
-
-                               handle_command (serv->server_session, outbuf, FALSE);
-                       }
-               }
-
-               server_connect_success (serv);
-               break;
-       case '5':                                                 /* prefs ip discovered */
-               waitline2 (source, tbuf, sizeof tbuf);
-               prefs.local_ip = inet_addr (tbuf);
-               break;
        case '7':                                                 /* gethostbyname (prefs.hex_net_bind_host) failed */
                sprintf (outbuf,
                                        _("Cannot resolve hostname %s\nCheck your IP Settings!\n"),
@@ -905,15 +485,13 @@ server_read_child (GIOChannel *source, GIOCondition condition, server *serv)
                PrintText (sess, _("Proxy traversal failed.\n"));
                server_disconnect (sess, FALSE, -1);
                break;
-       case '9':
-               waitline2 (source, tbuf, sizeof tbuf);
-               EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, tbuf, NULL, NULL, NULL, 0);
-               break;
        }
 
        return TRUE;
 }
 
+#endif
+
 /* kill all sockets & iotags of a server. Stop a connection attempt, or
    disconnect if already connected. */
 
@@ -922,45 +500,26 @@ server_cleanup (server * serv)
 {
        fe_set_lag (serv, 0);
 
-       if (serv->iotag)
+       if (serv->socket_read_source)
        {
-               fe_input_remove (serv->iotag);
-               serv->iotag = 0;
+               g_clear_pointer (&serv->socket_read_source, g_source_destroy);
        }
-
        if (serv->joindelay_tag)
        {
                fe_timeout_remove (serv->joindelay_tag);
                serv->joindelay_tag = 0;
        }
 
-#ifdef USE_OPENSSL
-       if (serv->ssl)
-       {
-               SSL_shutdown (serv->ssl);
-               SSL_free (serv->ssl);
-               serv->ssl = NULL;
-       }
-#endif
+       g_clear_object (&serv->socket_client);
 
        if (serv->connecting)
        {
                server_stopconnecting (serv);
-               closesocket (serv->sok4);
-               if (serv->proxy_sok4 != -1)
-                       closesocket (serv->proxy_sok4);
-               if (serv->sok6 != -1)
-                       closesocket (serv->sok6);
-               if (serv->proxy_sok6 != -1)
-                       closesocket (serv->proxy_sok6);
                return 1;
        }
 
        if (serv->connected)
        {
-               close_socket (serv->sok);
-               if (serv->proxy_sok)
-                       close_socket (serv->proxy_sok);
                serv->connected = FALSE;
                serv->end_of_motd = FALSE;
                return 2;
@@ -978,11 +537,10 @@ server_cleanup (server * serv)
 }
 
 static void
-server_disconnect (session * sess, int sendquit, int err)
+server_disconnect (session * sess, int sendquit, GError *err)
 {
        server *serv = sess->server;
        GSList *list;
-       char tbuf[64];
        gboolean shutup = FALSE;
 
        /* send our QUIT reason */
@@ -1000,8 +558,7 @@ server_disconnect (session * sess, int sendquit, int err)
                notc_msg (sess);
                return;
        case 1:                                                   /* it was in the process of connecting */
-               sprintf (tbuf, "%d", sess->server->childpid);
-               EMIT_SIGNAL (XP_TE_STOPCONNECT, sess, tbuf, NULL, NULL, NULL, 0);
+               EMIT_SIGNAL (XP_TE_STOPCONNECT, sess, NULL, NULL, NULL, NULL, 0);
                return;
        case 3:
                shutup = TRUE;  /* won't print "disconnected" in channels */
@@ -1017,7 +574,7 @@ server_disconnect (session * sess, int sendquit, int err)
                {
                        if (!shutup || sess->type == SESS_SERVER)
                                /* print "Disconnected" to each window using this server */
-                               EMIT_SIGNAL (XP_TE_DISCON, sess, errorstring (err), NULL, NULL, NULL, 0);
+                               EMIT_SIGNAL (XP_TE_DISCON, sess, err ? err->message : NULL, NULL, NULL, NULL, 0);
 
                        if (!sess->channel[0] || sess->type == SESS_CHANNEL)
                                clear_channel (sess);
@@ -1036,320 +593,8 @@ server_disconnect (session * sess, int sendquit, int err)
 
 /* send a "print text" command to the parent process - MUST END IN \n! */
 
-static void
-proxy_error (int fd, char *msg)
-{
-       write (fd, "0\n", 2);
-       write (fd, msg, strlen (msg));
-}
-
-struct sock_connect
-{
-       char version;
-       char type;
-       guint16 port;
-       guint32 address;
-       char username[10];
-};
-
-/* traverse_socks() returns:
- *                             0 success                *
- *          1 socks traversal failed */
-
-static int
-traverse_socks (int print_fd, int sok, char *serverAddr, int port)
-{
-       struct sock_connect sc;
-       unsigned char buf[256];
-
-       sc.version = 4;
-       sc.type = 1;
-       sc.port = htons (port);
-       sc.address = inet_addr (serverAddr);
-       g_strlcpy (sc.username, prefs.hex_irc_user_name, sizeof (sc.username));
-
-       send (sok, (char *) &sc, 8 + strlen (sc.username) + 1, 0);
-       buf[1] = 0;
-       recv (sok, buf, 10, 0);
-       if (buf[1] == 90)
-               return 0;
-
-       g_snprintf (buf, sizeof (buf), "SOCKS\tServer reported error %d,%d.\n", buf[0], buf[1]);
-       proxy_error (print_fd, buf);
-       return 1;
-}
-
-struct sock5_connect1
-{
-       char version;
-       char nmethods;
-       char method;
-};
-
-static int
-traverse_socks5 (int print_fd, int sok, char *serverAddr, int port)
-{
-       struct sock5_connect1 sc1;
-       unsigned char *sc2;
-       unsigned int packetlen, addrlen;
-       unsigned char buf[260];
-       int auth = prefs.hex_net_proxy_auth && prefs.hex_net_proxy_user[0] && prefs.hex_net_proxy_pass[0];
-
-       sc1.version = 5;
-       sc1.nmethods = 1;
-       if (auth)
-               sc1.method = 2;  /* Username/Password Authentication (UPA) */
-       else
-               sc1.method = 0;  /* NO Authentication */
-       send (sok, (char *) &sc1, 3, 0);
-       if (recv (sok, buf, 2, 0) != 2)
-               goto read_error;
-
-       if (buf[0] != 5)
-       {
-               proxy_error (print_fd, "SOCKS\tServer is not socks version 5.\n");
-               return 1;
-       }
-
-       /* did the server say no auth required? */
-       if (buf[1] == 0)
-               auth = 0;
-
-       if (auth)
-       {
-               int len_u=0, len_p=0;
-               unsigned char *u_p_buf;
-
-               /* authentication sub-negotiation (RFC1929) */
-               if (buf[1] != 2)  /* UPA not supported by server */
-               {
-                       proxy_error (print_fd, "SOCKS\tServer doesn't support UPA authentication.\n");
-                       return 1;
-               }
-
-               /* form the UPA request */
-               len_u = strlen (prefs.hex_net_proxy_user);
-               len_p = strlen (prefs.hex_net_proxy_pass);
-
-        packetlen = 2 + len_u + 1 + len_p;
-               u_p_buf = g_malloc0 (packetlen);
-
-               u_p_buf[0] = 1;
-               u_p_buf[1] = len_u;
-               memcpy (u_p_buf + 2, prefs.hex_net_proxy_user, len_u);
-               u_p_buf[2 + len_u] = len_p;
-               memcpy (u_p_buf + 3 + len_u, prefs.hex_net_proxy_pass, len_p);
-
-               send (sok, u_p_buf, packetlen, 0);
-               g_free(u_p_buf);
-
-               if ( recv (sok, buf, 2, 0) != 2 )
-                       goto read_error;
-               if ( buf[1] != 0 )
-               {
-                       proxy_error (print_fd, "SOCKS\tAuthentication failed. "
-                                                        "Is username and password correct?\n");
-                       return 1; /* UPA failed! */
-               }
-       }
-       else
-       {
-               if (buf[1] != 0)
-               {
-                       proxy_error (print_fd, "SOCKS\tAuthentication required but disabled in settings.\n");
-                       return 1;
-               }
-       }
-
-       addrlen = strlen (serverAddr);
-       packetlen = 4 + 1 + addrlen + 2;
-       sc2 = g_malloc (packetlen);
-       sc2[0] = 5;                                               /* version */
-       sc2[1] = 1;                                               /* command */
-       sc2[2] = 0;                                               /* reserved */
-       sc2[3] = 3;                                               /* address type */
-       sc2[4] = (unsigned char) addrlen;       /* hostname length */
-       memcpy (sc2 + 5, serverAddr, addrlen);
-       *((unsigned short *) (sc2 + 5 + addrlen)) = htons (port);
-       send (sok, sc2, packetlen, 0);
-       g_free (sc2);
-
-       /* consume all of the reply */
-       if (recv (sok, buf, 4, 0) != 4)
-               goto read_error;
-       if (buf[0] != 5 || buf[1] != 0)
-       {
-               if (buf[1] == 2)
-                       g_snprintf (buf, sizeof (buf), "SOCKS\tProxy refused to connect to host (not allowed).\n");
-               else
-                       g_snprintf (buf, sizeof (buf), "SOCKS\tProxy failed to connect to host (error %d).\n", buf[1]);
-               proxy_error (print_fd, buf);
-               return 1;
-       }
-       if (buf[3] == 1)        /* IPV4 32bit address */
-       {
-               if (recv (sok, buf, 6, 0) != 6)
-                       goto read_error;
-       } else if (buf[3] == 4) /* IPV6 128bit address */
-       {
-               if (recv (sok, buf, 18, 0) != 18)
-                       goto read_error;
-       } else if (buf[3] == 3) /* string, 1st byte is size */
-       {
-               if (recv (sok, buf, 1, 0) != 1) /* read the string size */
-                       goto read_error;
-               packetlen = buf[0] + 2; /* can't exceed 260 */
-               if (recv (sok, buf, packetlen, 0) != packetlen)
-                       goto read_error;
-       }
-
-       return 0;       /* success */
-
-read_error:
-       proxy_error (print_fd, "SOCKS\tRead error from server.\n");
-       return 1;
-}
-
-static int
-traverse_wingate (int print_fd, int sok, char *serverAddr, int port)
-{
-       char buf[128];
-
-       g_snprintf (buf, sizeof (buf), "%s %d\r\n", serverAddr, port);
-       send (sok, buf, strlen (buf), 0);
-
-       return 0;
-}
-
-/* stuff for HTTP auth is here */
-
-static void
-three_to_four (char *from, char *to)
-{
-       static const char tab64[64]=
-       {
-               'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
-               'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
-               'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
-               'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
-       };
-
-       to[0] = tab64 [ (from[0] >> 2) & 63 ];
-       to[1] = tab64 [ ((from[0] << 4) | (from[1] >> 4)) & 63 ];
-       to[2] = tab64 [ ((from[1] << 2) | (from[2] >> 6)) & 63 ];
-       to[3] = tab64 [ from[2] & 63 ];
-};
-
-void
-base64_encode (char *to, char *from, unsigned int len)
-{
-       while (len >= 3)
-       {
-               three_to_four (from, to);
-               len -= 3;
-               from += 3;
-               to += 4;
-       }
-       if (len)
-       {
-               char three[3] = {0,0,0};
-               unsigned int i;
-               for (i = 0; i < len; i++)
-               {
-                       three[i] = *from++;
-               }
-               three_to_four (three, to);
-               if (len == 1)
-               {
-                       to[2] = to[3] = '=';
-               }
-               else if (len == 2)
-               {
-                       to[3] = '=';
-               }
-               to += 4;
-       };
-       to[0] = 0;
-}
-
-static int
-http_read_line (int print_fd, int sok, char *buf, int len)
-{
-       len = waitline (sok, buf, len, TRUE);
-       if (len >= 1)
-       {
-               /* print the message out (send it to the parent process) */
-               write (print_fd, "0\n", 2);
-
-               if (buf[len-1] == '\r')
-               {
-                       buf[len-1] = '\n';
-                       write (print_fd, buf, len);
-               } else
-               {
-                       write (print_fd, buf, len);
-                       write (print_fd, "\n", 1);
-               }
-       }
-
-       return len;
-}
-
-static int
-traverse_http (int print_fd, int sok, char *serverAddr, int port)
-{
-       char buf[512];
-       char auth_data[256];
-       char auth_data2[252];
-       int n, n2;
-
-       n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
-                                         serverAddr, port);
-       if (prefs.hex_net_proxy_auth)
-       {
-               n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
-                                                       prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass);
-               base64_encode (auth_data, auth_data2, n2);
-               n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
-       }
-       n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
-       send (sok, buf, n, 0);
-
-       n = http_read_line (print_fd, sok, buf, sizeof (buf));
-       /* "HTTP/1.0 200 OK" */
-       if (n < 12)
-               return 1;
-       if (memcmp (buf, "HTTP/", 5) || memcmp (buf + 9, "200", 3))
-               return 1;
-       while (1)
-       {
-               /* read until blank line */
-               n = http_read_line (print_fd, sok, buf, sizeof (buf));
-               if (n < 1 || (n == 1 && buf[0] == '\n'))
-                       break;
-       }
-       return 0;
-}
-
-static int
-traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
-{
-       switch (proxy_type)
-       {
-       case 1:
-               return traverse_wingate (print_fd, sok, ip, port);
-       case 2:
-               return traverse_socks (print_fd, sok, ip, port);
-       case 3:
-               return traverse_socks5 (print_fd, sok, ip, port);
-       case 4:
-               return traverse_http (print_fd, sok, ip, port);
-       }
-
-       return 1;
-}
-
 /* this is the child process making the connection attempt */
+#if 0
 
 static int
 server_child (server * serv)
@@ -1374,24 +619,6 @@ server_child (server * serv)
 
        ns_server = net_store_new ();
 
-       /* is a hostname set? - bind to it */
-       if (prefs.hex_net_bind_host[0])
-       {
-               ns_local = net_store_new ();
-               local_ip = net_resolve (ns_local, prefs.hex_net_bind_host, 0, &real_hostname);
-               if (local_ip != NULL)
-               {
-                       g_snprintf (buf, sizeof (buf), "5\n%s\n", local_ip);
-                       write (serv->childwrite, buf, strlen (buf));
-                       net_bind (ns_local, serv->sok4, serv->sok6);
-                       bound = 1;
-               } else
-               {
-                       write (serv->childwrite, "7\n", 2);
-               }
-               net_store_destroy (ns_local);
-       }
-
        if (!serv->dont_use_proxy) /* blocked in serverlist? */
        {
                if (prefs.hex_net_proxy_type == 5)
@@ -1443,6 +670,7 @@ server_child (server * serv)
                }
        }
 
+
        serv->proxy_type = proxy_type;
 
        /* first resolve where we want to connect to */
@@ -1538,77 +766,197 @@ xit:
        return 0;
        /* cppcheck-suppress memleak */
 }
+#endif
 
 static void
-server_connect (server *serv, char *hostname, int port, int no_login)
+on_client_network_event (GSocketClient *client,
+                         GSocketClientEvent event,
+                         GSocketConnectable *connectable,
+                         GIOStream *connection,
+                         gpointer user_data)
 {
-       int pid, read_des[2];
-       session *sess = serv->server_session;
+       session *sess = user_data;
+
+       // TODO:                prefs.local_ip = inet_addr (tbuf);
 
-#ifdef USE_OPENSSL
-       if (!serv->ctx && serv->use_ssl)
+       switch (event)
        {
-               if (!(serv->ctx = _SSL_context_init (ssl_cb_info)))
+       case G_SOCKET_CLIENT_RESOLVING:
+               EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, (char*)g_network_address_get_hostname (G_NETWORK_ADDRESS (connectable)),
+                            NULL, NULL, NULL, 0);
+               break;
+       case G_SOCKET_CLIENT_RESOLVED:
+               break;
+       case G_SOCKET_CLIENT_CONNECTING: {
+               GInetSocketAddress *remote_isaddr = G_INET_SOCKET_ADDRESS (g_socket_connection_get_remote_address (G_SOCKET_CONNECTION (connection), NULL));
+               
+               g_warn_if_fail (remote_isaddr != NULL);
+               if (remote_isaddr)
                {
-                       fprintf (stderr, "_SSL_context_init failed\n");
-                       exit (1);
+                       GInetAddress *remote_iaddr = G_INET_ADDRESS (g_inet_socket_address_get_address (remote_isaddr));
+                       char *remote_iaddr_string = g_inet_address_to_string (remote_iaddr);
+                       char *hostname = (char*)g_network_address_get_hostname (G_NETWORK_ADDRESS (connectable));
+                       char port_str[16];
+                       g_snprintf (port_str, sizeof (port_str), "%"G_GUINT16_FORMAT, g_inet_socket_address_get_port (remote_isaddr));
+
+                       EMIT_SIGNAL (XP_TE_CONNECT, sess, hostname, remote_iaddr_string, port_str, NULL, 0);
+                       g_free (remote_iaddr_string);
+                       g_object_unref (remote_isaddr);
                }
+               break;
        }
-#endif
+       case G_SOCKET_CLIENT_TLS_HANDSHAKED: {
+               // TODO: Print out certificate information
+               // EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL,
+               //                      NULL, 0);
+               break;
+       }
+       case G_SOCKET_CLIENT_CONNECTED: {
+               char buf[512];
+               ircnet *net = sess->server->network;
+               GInetSocketAddress *remote_isaddr = G_INET_SOCKET_ADDRESS (g_socket_connection_get_remote_address (G_SOCKET_CONNECTION (connection), NULL));
+
+               g_assert (remote_isaddr);
+               
+               g_snprintf (buf, sizeof (buf), "IDENTD %"G_GUINT16_FORMAT" ", g_inet_socket_address_get_port (remote_isaddr));
+               if (net && net->user && !(net->flags & FLAG_USE_GLOBAL))
+                       g_strlcat (buf, net->user, sizeof (buf));
+               else
+                       g_strlcat (buf, prefs.hex_irc_user_name, sizeof (buf));
+
+               handle_command (sess->server->server_session, buf, FALSE);
+
+               g_object_unref (remote_isaddr);
+               break;
+       }
+       }
+}
+
+static void
+on_client_connect_ready (GSocketClient *client, GAsyncResult *res, gpointer user_data)
+{
+       GSocketConnection *conn;
+       GError *error = NULL;
+       server *serv = user_data;
+
+       conn = g_socket_client_connect_finish (client, res, &error);
+       if (error)
+       {
+               g_debug ("Failed to connect: %s", error->message);
+       
+               if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+               {
+                       g_error_free (error);
+                       return;
+               }
+
+               server_stopconnecting (serv);
+               if (g_error_matches (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND))
+               {
+                       EMIT_SIGNAL (XP_TE_UKNHOST, serv->server_session, NULL, NULL, NULL, NULL, 0);
+               }
+               else if (error->domain == G_TLS_ERROR)
+               {
+                       EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, error->message, NULL, NULL, NULL, 0);
+               }
+               else
+               {
+                       EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, error->message, NULL, NULL, NULL, 0);
+               }
+
+
+               if (!servlist_cycle (serv))
+                       if (prefs.hex_net_auto_reconnectonfail)
+                               auto_reconnect (serv, FALSE, error);
+
+               g_error_free (error);
+               return;
+       }
+
+       serv->socket_conn = g_steal_pointer (&conn);
+       serv->socket = g_socket_connection_get_socket (serv->socket_conn);
+       g_socket_set_blocking (serv->socket, FALSE);
+
+       server_connect_success (serv);
+}
+
+static void
+server_connect (server *serv, char *hostname, int port, int no_login)
+{
+       session *sess = serv->server_session;
+       GSocketConnectable *connectable;
 
        if (!hostname[0])
+       {
+               g_debug ("server_connect: no hostname");
                return;
+       }
+
+       if (port <= 0 || port > G_MAXUINT16)
+               port = serv->use_ssl ? 6697 : 6667;
+
+       connectable = g_network_address_new (hostname, port);
+       
+       serv->socket_client = g_socket_client_new ();
+       g_socket_client_set_tls (serv->socket_client, serv->use_ssl);
+       g_socket_client_set_enable_proxy (serv->socket_client, !serv->dont_use_proxy);
+       g_socket_client_set_timeout (serv->socket_client, 60); // FIXME
+       g_signal_connect (serv->socket_client, "event", G_CALLBACK (on_client_network_event), sess);
 
-       if (port < 0)
+       if (prefs.hex_net_bind_host[0])
        {
-               /* use default port for this server type */
-               port = 6667;
-#ifdef USE_OPENSSL
-               if (serv->use_ssl)
-                       port = 6697;
-#endif
+               GSocketAddress *local_addr = g_inet_socket_address_new_from_string (prefs.hex_net_bind_host, 0);
+               g_socket_client_set_local_address (serv->socket_client, local_addr);
+               g_object_unref (local_addr);
+       }
+
+       
+       if (!serv->dont_use_proxy)
+       {
+               //GProxyResolver *proxy_resolver = g_proxy_resolver_get_default ();
+               // TODO:
        }
-       port &= 0xffff; /* wrap around */
 
-       if (serv->connected || serv->connecting || serv->recondelay_tag)
-               server_disconnect (sess, TRUE, -1);
+       // if (serv->connected || serv->connecting || serv->recondelay_tag)
+       //      server_disconnect (sess, TRUE, -1);
 
        fe_progressbar_start (sess);
 
-       EMIT_SIGNAL (XP_TE_SERVERLOOKUP, sess, hostname, NULL, NULL, NULL, 0);
-
        safe_strcpy (serv->servername, hostname, sizeof (serv->servername));
        /* overlap illegal in strncpy */
        if (hostname != serv->hostname)
                safe_strcpy (serv->hostname, hostname, sizeof (serv->hostname));
 
-#ifdef USE_OPENSSL
        if (serv->use_ssl)
        {
-               char *cert_file;
+               char *certificate_paths[2];
+               GError *error = NULL;
                serv->have_cert = FALSE;
+               guint i;
 
                /* first try network specific cert/key */
-               cert_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
-                                        get_xdir (), server_get_network (serv, TRUE));
-               if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
-               {
-                       if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
-                               serv->have_cert = TRUE;
-               }
-               else
+               certificate_paths[0] = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
+                                                get_xdir (), server_get_network (serv, TRUE));
+               /* if that doesn't exist, try <config>/certs/client.pem */
+        certificate_paths[1] = g_build_filename (get_xdir (), "certs", "client.pem", NULL);
+
+               for (i = 0; i < G_N_ELEMENTS (certificate_paths); i++)
                {
-                       /* if that doesn't exist, try <config>/certs/client.pem */
-                       cert_file = g_build_filename (get_xdir (), "certs", "client.pem", NULL);
-                       if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
+                       serv->client_cert = g_tls_certificate_new_from_file (certificate_paths[i], &error);
+                       if (error)
                        {
-                               if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
-                                       serv->have_cert = TRUE;
+                               g_debug ("Failed opening client cert (%s): %s", certificate_paths[i], error->message);
+                               g_clear_error (&error);
+                               continue;
                        }
+
+                       serv->have_cert = TRUE;
+                       break;
                }
-               g_free (cert_file);
+
+               g_free (certificate_paths[0]);
+               g_free (certificate_paths[1]);
        }
-#endif
 
        server_set_defaults (serv);
        serv->connecting = TRUE;
@@ -1619,55 +967,7 @@ server_connect (server *serv, char *hostname, int port, int no_login)
        fe_set_away (serv);
        server_flush_queue (serv);
 
-#ifdef WIN32
-       if (_pipe (read_des, 4096, _O_BINARY) < 0)
-#else
-       if (pipe (read_des) < 0)
-#endif
-               return;
-#ifdef __EMX__ /* os/2 */
-       setmode (read_des[0], O_BINARY);
-       setmode (read_des[1], O_BINARY);
-#endif
-       serv->childread = read_des[0];
-       serv->childwrite = read_des[1];
-
-       /* create both sockets now, drop one later */
-       net_sockets (&serv->sok4, &serv->sok6);
-       serv->proxy_sok4 = -1;
-       serv->proxy_sok6 = -1;
-
-#ifdef WIN32
-       CloseHandle (CreateThread (NULL, 0,
-                                                                               (LPTHREAD_START_ROUTINE)server_child,
-                                                                               serv, 0, (DWORD *)&pid));
-#else
-#ifdef LOOKUPD
-       /* CL: net_resolve calls rand() when LOOKUPD is set, so prepare a different
-        * seed for each child. This method gives a bigger variation in seed values
-        * than calling srand(time(0)) in the child itself.
-        */
-       rand();
-#endif
-       switch (pid = fork ())
-       {
-       case -1:
-               return;
-
-       case 0:
-               /* this is the child */
-               setuid (getuid ());
-               server_child (serv);
-               _exit (0);
-       }
-#endif
-       serv->childpid = pid;
-#ifdef WIN32
-       serv->iotag = fe_input_add (serv->childread, FIA_READ|FIA_FD, server_read_child,
-#else
-       serv->iotag = fe_input_add (serv->childread, FIA_READ, server_read_child,
-#endif
-                                                                                serv);
+       g_socket_client_connect_async (serv->socket_client, connectable, NULL, (GAsyncReadyCallback)on_client_connect_ready, serv);
 }
 
 void
@@ -1741,7 +1041,6 @@ server_new (void)
        server_fill_her_up (serv);
 
        serv->id = id++;
-       serv->sok = -1;
        strcpy (serv->nick, prefs.hex_irc_nick1);
        server_set_defaults (serv);
 
@@ -1932,10 +1231,6 @@ server_free (server *serv)
 
        if (serv->favlist)
                g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
-#ifdef USE_OPENSSL
-       if (serv->ctx)
-               _SSL_context_free (serv->ctx);
-#endif
 
        fe_server_callback (serv);
 
index ff8ef4047ee66ae2f9d535e7c3f5ed53a42889cd..cd991da6ef1d30fd257ed933d05ee27d6ea8f36c 100644 (file)
@@ -25,7 +25,6 @@ extern GSList *serv_list;
 /* eventually need to keep the tcp_* functions isolated to server.c */
 int tcp_send_len (server *serv, char *buf, int len);
 void tcp_sendf (server *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
-int tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len);
 
 server *server_new (void);
 int is_server (server *serv);
@@ -39,6 +38,4 @@ void server_free (server *serv);
 void server_away_save_message (server *serv, char *nick, char *msg);
 struct away_msg *server_away_find_message (server *serv, char *nick);
 
-void base64_encode (char *to, char *from, unsigned int len);
-
 #endif
diff --git a/src/common/ssl.c b/src/common/ssl.c
deleted file mode 100644 (file)
index 0eb78bd..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * ssl.c v0.0.3
- * Copyright (C) 2000  --  DaP <profeta@freemail.c3.hu>
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifdef __APPLE__
-#define __AVAILABILITYMACROS__
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
-
-#include "inet.h"                                /* make it first to avoid macro redefinitions */
-#include <openssl/ssl.h>                 /* SSL_() */
-#include <openssl/err.h>                 /* ERR_() */
-#include <openssl/x509v3.h>
-#ifdef WIN32
-#include <openssl/rand.h>                /* RAND_seed() */
-#endif
-#include "config.h"
-#include <time.h>                                /* asctime() */
-#include <string.h>                              /* strncpy() */
-#include "ssl.h"                                 /* struct cert_info */
-
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <gio/gio.h>
-#include "util.h"
-
-/* If openssl was built without ec */
-#ifndef SSL_OP_SINGLE_ECDH_USE
-#define SSL_OP_SINGLE_ECDH_USE 0
-#endif
-
-#ifndef SSL_OP_NO_COMPRESSION
-#define SSL_OP_NO_COMPRESSION 0
-#endif
-
-/* globals */
-static struct chiper_info chiper_info;         /* static buffer for _SSL_get_cipher_info() */
-static char err_buf[256];                      /* generic error buffer */
-
-
-/* +++++ Internal functions +++++ */
-
-static void
-__SSL_fill_err_buf (char *funcname)
-{
-       int err;
-       char buf[256];
-
-
-       err = ERR_get_error ();
-       ERR_error_string (err, buf);
-       g_snprintf (err_buf, sizeof (err_buf), "%s: %s (%d)\n", funcname, buf, err);
-}
-
-
-static void
-__SSL_critical_error (char *funcname)
-{
-       __SSL_fill_err_buf (funcname);
-       fprintf (stderr, "%s\n", err_buf);
-
-       exit (1);
-}
-
-/* +++++ SSL functions +++++ */
-
-SSL_CTX *
-_SSL_context_init (void (*info_cb_func))
-{
-       SSL_CTX *ctx;
-
-       SSLeay_add_ssl_algorithms ();
-       SSL_load_error_strings ();
-       ctx = SSL_CTX_new (SSLv23_client_method ());
-
-       SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
-       SSL_CTX_set_timeout (ctx, 300);
-       SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
-                                                         |SSL_OP_NO_COMPRESSION
-                                                         |SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
-                                                         |SSL_OP_NO_TICKET
-                                                         |SSL_OP_CIPHER_SERVER_PREFERENCE);
-
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined (OPENSSL_NO_COMP) /* workaround for OpenSSL 0.9.8 */
-       sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
-#endif
-
-       /* used in SSL_connect(), SSL_accept() */
-       SSL_CTX_set_info_callback (ctx, info_cb_func);
-
-       return(ctx);
-}
-
-static void
-ASN1_TIME_snprintf (char *buf, int buf_len, ASN1_TIME * tm)
-{
-       char *expires = NULL;
-       BIO *inMem = BIO_new (BIO_s_mem ());
-
-       ASN1_TIME_print (inMem, tm);
-       BIO_get_mem_data (inMem, &expires);
-       buf[0] = 0;
-       if (expires != NULL)
-       {
-               /* expires is not \0 terminated */
-               safe_strcpy (buf, expires, MIN(24, buf_len));
-       }
-       BIO_free (inMem);
-}
-
-
-static void
-broke_oneline (char *oneline, char *parray[])
-{
-       char *pt, *ppt;
-       int i;
-
-
-       i = 0;
-       ppt = pt = oneline + 1;
-       while ((pt = strchr (pt, '/')))
-       {
-               *pt = 0;
-               parray[i++] = ppt;
-               ppt = ++pt;
-       }
-       parray[i++] = ppt;
-       parray[i] = NULL;
-}
-
-
-/*
-    FIXME: Master-Key, Extensions, CA bits
-           (openssl x509 -text -in servcert.pem)
-*/
-int
-_SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)
-{
-       X509 *peer_cert;
-       X509_PUBKEY *key;
-       X509_ALGOR *algor = NULL;
-       EVP_PKEY *peer_pkey;
-       char notBefore[64];
-       char notAfter[64];
-       int alg;
-       int sign_alg;
-
-
-       if (!(peer_cert = SSL_get_peer_certificate (ssl)))
-               return (1);                               /* FATAL? */
-
-       X509_NAME_oneline (X509_get_subject_name (peer_cert), cert_info->subject,
-                                                        sizeof (cert_info->subject));
-       X509_NAME_oneline (X509_get_issuer_name (peer_cert), cert_info->issuer,
-                                                        sizeof (cert_info->issuer));
-       broke_oneline (cert_info->subject, cert_info->subject_word);
-       broke_oneline (cert_info->issuer, cert_info->issuer_word);
-
-       key = X509_get_X509_PUBKEY(peer_cert);
-       if (!X509_PUBKEY_get0_param(NULL, NULL, 0, &algor, key))
-               return 1;
-
-       alg = OBJ_obj2nid (algor->algorithm);
-#ifndef HAVE_X509_GET_SIGNATURE_NID
-       sign_alg = OBJ_obj2nid (peer_cert->sig_alg->algorithm);
-#else
-       sign_alg = X509_get_signature_nid (peer_cert);
-#endif
-       ASN1_TIME_snprintf (notBefore, sizeof (notBefore),
-                                                         X509_get_notBefore (peer_cert));
-       ASN1_TIME_snprintf (notAfter, sizeof (notAfter),
-                                                         X509_get_notAfter (peer_cert));
-
-       peer_pkey = X509_get_pubkey (peer_cert);
-
-       safe_strcpy (cert_info->algorithm,
-                               (alg == NID_undef) ? "Unknown" : OBJ_nid2ln (alg),
-                               sizeof (cert_info->algorithm));
-       cert_info->algorithm_bits = EVP_PKEY_bits (peer_pkey);
-       safe_strcpy (cert_info->sign_algorithm,
-                               (sign_alg == NID_undef) ? "Unknown" : OBJ_nid2ln (sign_alg),
-                               sizeof (cert_info->sign_algorithm));
-       /* EVP_PKEY_bits(ca_pkey)); */
-       cert_info->sign_algorithm_bits = 0;
-       safe_strcpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore));
-       safe_strcpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter));
-
-       EVP_PKEY_free (peer_pkey);
-
-       /* SSL_SESSION_print_fp(stdout, SSL_get_session(ssl)); */
-/*
-       if (ssl->session->sess_cert->peer_rsa_tmp) {
-               tmp_pkey = EVP_PKEY_new();
-               EVP_PKEY_assign_RSA(tmp_pkey, ssl->session->sess_cert->peer_rsa_tmp);
-               cert_info->rsa_tmp_bits = EVP_PKEY_bits (tmp_pkey);
-               EVP_PKEY_free(tmp_pkey);
-       } else
-               fprintf(stderr, "REMOTE SIDE DOESN'T PROVIDES ->peer_rsa_tmp\n");
-*/
-       cert_info->rsa_tmp_bits = 0;
-
-       X509_free (peer_cert);
-
-       return (0);
-}
-
-
-struct chiper_info *
-_SSL_get_cipher_info (SSL * ssl)
-{
-       const SSL_CIPHER *c;
-
-
-       c = SSL_get_current_cipher (ssl);
-       safe_strcpy (chiper_info.version, SSL_CIPHER_get_version (c),
-                               sizeof (chiper_info.version));
-       safe_strcpy (chiper_info.chiper, SSL_CIPHER_get_name (c),
-                               sizeof (chiper_info.chiper));
-       SSL_CIPHER_get_bits (c, &chiper_info.chiper_bits);
-
-       return (&chiper_info);
-}
-
-
-int
-_SSL_send (SSL * ssl, char *buf, int len)
-{
-       int num;
-
-
-       num = SSL_write (ssl, buf, len);
-
-       switch (SSL_get_error (ssl, num))
-       {
-       case SSL_ERROR_SSL:                       /* setup errno! */
-               /* ??? */
-               __SSL_fill_err_buf ("SSL_write");
-               fprintf (stderr, "%s\n", err_buf);
-               break;
-       case SSL_ERROR_SYSCALL:
-               /* ??? */
-               perror ("SSL_write/write");
-               break;
-       case SSL_ERROR_ZERO_RETURN:
-               /* fprintf(stderr, "SSL closed on write\n"); */
-               break;
-       }
-
-       return (num);
-}
-
-
-int
-_SSL_recv (SSL * ssl, char *buf, int len)
-{
-       int num;
-
-
-       num = SSL_read (ssl, buf, len);
-
-       switch (SSL_get_error (ssl, num))
-       {
-       case SSL_ERROR_SSL:
-               /* ??? */
-               __SSL_fill_err_buf ("SSL_read");
-               fprintf (stderr, "%s\n", err_buf);
-               break;
-       case SSL_ERROR_SYSCALL:
-               /* ??? */
-               if (!would_block ())
-                       perror ("SSL_read/read");
-               break;
-       case SSL_ERROR_ZERO_RETURN:
-               /* fprintf(stdeerr, "SSL closed on read\n"); */
-               break;
-       }
-
-       return (num);
-}
-
-
-SSL *
-_SSL_socket (SSL_CTX *ctx, int sd)
-{
-       SSL *ssl;
-       const SSL_METHOD *method;
-
-       if (!(ssl = SSL_new (ctx)))
-               /* FATAL */
-               __SSL_critical_error ("SSL_new");
-
-       SSL_set_fd (ssl, sd);
-
-#ifndef HAVE_SSL_CTX_GET_SSL_METHOD
-       method = ctx->method;
-#else
-       method = SSL_CTX_get_ssl_method (ctx);
-#endif
-       if (method == SSLv23_client_method())
-               SSL_set_connect_state (ssl);
-       else
-               SSL_set_accept_state(ssl);
-
-       return (ssl);
-}
-
-
-char *
-_SSL_set_verify (SSL_CTX *ctx, void *verify_callback, char *cacert)
-{
-       if (!SSL_CTX_set_default_verify_paths (ctx))
-       {
-               __SSL_fill_err_buf ("SSL_CTX_set_default_verify_paths");
-               return (err_buf);
-       }
-/*
-       if (cacert)
-       {
-               if (!SSL_CTX_load_verify_locations (ctx, cacert, NULL))
-               {
-                       __SSL_fill_err_buf ("SSL_CTX_load_verify_locations");
-                       return (err_buf);
-               }
-       }
-*/
-       SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, verify_callback);
-
-       return (NULL);
-}
-
-
-void
-_SSL_close (SSL * ssl)
-{
-       SSL_set_shutdown (ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
-       SSL_free (ssl);
-#ifdef HAVE_ERR_REMOVE_THREAD_STATE
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L
-       /* OpenSSL handles this itself in 1.1+ and this is a no-op */
-       ERR_remove_thread_state (NULL);
-#endif
-#else
-       ERR_remove_state (0);
-#endif
-}
-
-/* Hostname validation code based on OpenBSD's libtls. */
-
-static int
-_SSL_match_hostname (const char *cert_hostname, const char *hostname)
-{
-       const char *cert_domain, *domain, *next_dot;
-
-       if (g_ascii_strcasecmp (cert_hostname, hostname) == 0)
-               return 0;
-
-       /* Wildcard match? */
-       if (cert_hostname[0] == '*')
-       {
-               /*
-                * Valid wildcards:
-                * - "*.domain.tld"
-                * - "*.sub.domain.tld"
-                * - etc.
-                * Reject "*.tld".
-                * No attempt to prevent the use of eg. "*.co.uk".
-                */
-               cert_domain = &cert_hostname[1];
-               /* Disallow "*"  */
-               if (cert_domain[0] == '\0')
-                       return -1;
-               /* Disallow "*foo" */
-               if (cert_domain[0] != '.')
-                       return -1;
-               /* Disallow "*.." */
-               if (cert_domain[1] == '.')
-                       return -1;
-               next_dot = strchr (&cert_domain[1], '.');
-               /* Disallow "*.bar" */
-               if (next_dot == NULL)
-                       return -1;
-               /* Disallow "*.bar.." */
-               if (next_dot[1] == '.')
-                       return -1;
-
-               domain = strchr (hostname, '.');
-
-               /* No wildcard match against a hostname with no domain part. */
-               if (domain == NULL || strlen(domain) == 1)
-                       return -1;
-
-               if (g_ascii_strcasecmp (cert_domain, domain) == 0)
-                       return 0;
-       }
-
-       return -1;
-}
-
-static int
-_SSL_check_subject_altname (X509 *cert, const char *host)
-{
-       STACK_OF(GENERAL_NAME) *altname_stack = NULL;
-       GInetAddress *addr;
-       GSocketFamily family;
-       int type = GEN_DNS;
-       int count, i;
-       int rv = -1;
-
-       altname_stack = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL);
-       if (altname_stack == NULL)
-               return -1;
-
-       addr = g_inet_address_new_from_string (host);
-       if (addr != NULL)
-       {
-               family = g_inet_address_get_family (addr);
-               if (family == G_SOCKET_FAMILY_IPV4 || family == G_SOCKET_FAMILY_IPV6)
-                       type = GEN_IPADD;
-       }
-
-       count = sk_GENERAL_NAME_num(altname_stack);
-       for (i = 0; i < count; i++)
-       {
-               GENERAL_NAME *altname;
-
-               altname = sk_GENERAL_NAME_value (altname_stack, i);
-
-               if (altname->type != type)
-                       continue;
-
-               if (type == GEN_DNS)
-               {
-                       const unsigned char *data;
-                       int format;
-
-                       format = ASN1_STRING_type (altname->d.dNSName);
-                       if (format == V_ASN1_IA5STRING)
-                       {
-#ifdef HAVE_ASN1_STRING_GET0_DATA
-                               data = ASN1_STRING_get0_data (altname->d.dNSName);
-#else
-                               data = ASN1_STRING_data (altname->d.dNSName);
-#endif
-
-                               if (ASN1_STRING_length (altname->d.dNSName) != (int)strlen(data))
-                               {
-                                       g_warning("NUL byte in subjectAltName, probably a malicious certificate.\n");
-                                       rv = -2;
-                                       break;
-                               }
-
-                               if (_SSL_match_hostname (data, host) == 0)
-                               {
-                                       rv = 0;
-                                       break;
-                               }
-                       }
-                       else
-                               g_warning ("unhandled subjectAltName dNSName encoding (%d)\n", format);
-
-               }
-               else if (type == GEN_IPADD)
-               {
-                       const unsigned char *data;
-                       const guint8 *addr_bytes;
-                       int datalen, addr_len;
-
-                       datalen = ASN1_STRING_length (altname->d.iPAddress);
-#ifdef HAVE_ASN1_STRING_GET0_DATA
-                       data = ASN1_STRING_get0_data (altname->d.iPAddress);
-#else
-                       data = ASN1_STRING_data (altname->d.iPAddress);
-#endif
-
-                       addr_bytes = g_inet_address_to_bytes (addr);
-                       addr_len = (int)g_inet_address_get_native_size (addr);
-
-                       if (datalen == addr_len && memcmp (data, addr_bytes, addr_len) == 0)
-                       {
-                               rv = 0;
-                               break;
-                       }
-               }
-       }
-
-       if (addr != NULL)
-               g_object_unref (addr);
-       sk_GENERAL_NAME_pop_free (altname_stack, GENERAL_NAME_free);
-       return rv;
-}
-
-static int
-_SSL_check_common_name (X509 *cert, const char *host)
-{
-       X509_NAME *name;
-       char *common_name = NULL;
-       int common_name_len;
-       int rv = -1;
-       GInetAddress *addr;
-
-       name = X509_get_subject_name (cert);
-       if (name == NULL)
-               return -1;
-
-       common_name_len = X509_NAME_get_text_by_NID (name, NID_commonName, NULL, 0);
-       if (common_name_len < 0)
-               return -1;
-
-       common_name = g_malloc0 (common_name_len + 1);
-
-       X509_NAME_get_text_by_NID (name, NID_commonName, common_name, common_name_len + 1);
-
-       /* NUL bytes in CN? */
-       if (common_name_len != (int)strlen(common_name))
-       {
-               g_warning ("NUL byte in Common Name field, probably a malicious certificate.\n");
-               rv = -2;
-               goto out;
-       }
-
-       if ((addr = g_inet_address_new_from_string (host)) != NULL)
-       {
-               /*
-                * We don't want to attempt wildcard matching against IP
-                * addresses, so perform a simple comparison here.
-                */
-               if (g_strcmp0 (common_name, host) == 0)
-                       rv = 0;
-               else
-                       rv = -1;
-
-               g_object_unref (addr);
-       }
-       else if (_SSL_match_hostname (common_name, host) == 0)
-               rv = 0;
-
-out:
-       g_free(common_name);
-       return rv;
-}
-
-int
-_SSL_check_hostname (X509 *cert, const char *host)
-{
-       int rv;
-
-       rv = _SSL_check_subject_altname (cert, host);
-       if (rv == 0 || rv == -2)
-               return rv;
-
-       return _SSL_check_common_name (cert, host);
-}
diff --git a/src/common/ssl.h b/src/common/ssl.h
deleted file mode 100644 (file)
index e722f83..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* HexChat
- * Copyright (C) 1998-2010 Peter Zelezny.
- * Copyright (C) 2009-2013 Berke Viktor.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifndef HEXCHAT_SSL_H
-#define HEXCHAT_SSL_H
-
-struct cert_info {
-    char subject[256];
-    char *subject_word[12];
-    char issuer[256];
-    char *issuer_word[12];
-    char algorithm[32];
-    int algorithm_bits;
-    char sign_algorithm[32];
-    int sign_algorithm_bits;
-    char notbefore[32];
-    char notafter[32];
-
-    int rsa_tmp_bits;
-};
-
-struct chiper_info {
-    char version[16];
-    char chiper[48];
-    int chiper_bits;
-};
-
-SSL_CTX *_SSL_context_init (void (*info_cb_func));
-#define _SSL_context_free(a)   SSL_CTX_free(a);
-
-SSL *_SSL_socket (SSL_CTX *ctx, int sd);
-char *_SSL_set_verify (SSL_CTX *ctx, void *(verify_callback), char *cacert);
-/*
-    int SSL_connect(SSL *);
-    int SSL_accept(SSL *);
-    int SSL_get_fd(SSL *);
-*/
-void _SSL_close (SSL * ssl);
-int _SSL_check_hostname(X509 *cert, const char *host);
-int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl);
-struct chiper_info *_SSL_get_cipher_info (SSL * ssl);
-
-/*char *_SSL_add_keypair (SSL_CTX *ctx, char *privkey, char *cert);*/
-/*void _SSL_add_random_keypair(SSL_CTX *ctx, int bits);*/
-
-int _SSL_send (SSL * ssl, char *buf, int len);
-int _SSL_recv (SSL * ssl, char *buf, int len);
-
-/* misc */
-/*void broke_oneline (char *oneline, char *parray[]);*/
-
-/*char *_SSL_do_cipher_base64(char *buf, int buf_len, char *key, int operation);*/             /* must be freed */
-
-/*void *_SSL_get_sess_obj(SSL *ssl, int type);*/               /* NOT must be freed */
-#define        _SSL_get_sess_pkey(a)   _SSL_get_sess_obj(a, 0)
-#define        _SSL_get_sess_prkey(a)  _SSL_get_sess_obj(a, 1)
-#define        _SSL_get_sess_x509(a)   _SSL_get_sess_obj(a, 2)
-/*char *_SSL_get_obj_base64(void *s, int type);*/              /* must be freed */
-#define        _SSL_get_pkey_base64(a)         _SSL_get_obj_base64(a, 0)
-#define        _SSL_get_prkey_base64(a)        _SSL_get_obj_base64(a, 1)
-#define        _SSL_get_x509_base64(a)         _SSL_get_obj_base64(a, 2)
-/*char *_SSL_get_ctx_obj_base64(SSL_CTX *ctx, int type);*/     /* must be freed */
-#define        _SSL_get_ctx_pkey_base64(a)     _SSL_get_ctx_obj_base64(a, 0)
-#define        _SSL_get_ctx_prkey_base64(a)    _SSL_get_ctx_obj_base64(a, 1)
-#define        _SSL_get_ctx_x509_base64(a)     _SSL_get_ctx_obj_base64(a, 2)
-
-/*int _SSL_verify_x509(X509 *x509);*/
-
-#endif
index a77700fa359784e757e7fffe48db0b5ae894da5b..365d6cf488e471431c5bd4b042ba8a25cab7409f 100644 (file)
@@ -1323,7 +1323,6 @@ static char * const pevt_connect_help[] = {
 };
 
 static char * const pevt_sconnect_help[] = {
-       "PID"
 };
 
 static char * const pevt_generic_nick_help[] = {
index 19b0d497baf8c81242ae7ab5d42babbf008131b2..b58035e9ccec77e03b42f78f917163b2cd666348 100644 (file)
@@ -787,8 +787,8 @@ n2
 Stop Connection
 XP_TE_STOPCONNECT
 pevt_sconnect_help
-%C23*%O$tStopped previous connection attempt (%C24$1%O)
-1
+%C23*%O$tStopped previous connection attempt
+0
 
 Topic
 XP_TE_TOPIC
index fa0783d4de1ad2d80d26e4bba6d844c74b0e28fc..09ad24116fcf8320531fe050d267ccf4f6137a12 100644 (file)
@@ -56,6 +56,9 @@
 #ifdef USE_OPENSSL
 #include <openssl/bn.h>
 #include <openssl/rand.h>
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
 #ifndef WIN32
 #include <netinet/in.h>
 #endif
@@ -1550,3 +1553,52 @@ strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time)
        g_date_free (date);
        return result;
 }
+
+static void
+three_to_four (char *from, char *to)
+{
+       static const char tab64[64]=
+       {
+               'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+               'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+               'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+               'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+       };
+
+       to[0] = tab64 [ (from[0] >> 2) & 63 ];
+       to[1] = tab64 [ ((from[0] << 4) | (from[1] >> 4)) & 63 ];
+       to[2] = tab64 [ ((from[1] << 2) | (from[2] >> 6)) & 63 ];
+       to[3] = tab64 [ from[2] & 63 ];
+};
+
+void
+base64_encode (char *to, char *from, unsigned int len)
+{
+       while (len >= 3)
+       {
+               three_to_four (from, to);
+               len -= 3;
+               from += 3;
+               to += 4;
+       }
+       if (len)
+       {
+               char three[3] = {0,0,0};
+               unsigned int i;
+               for (i = 0; i < len; i++)
+               {
+                       three[i] = *from++;
+               }
+               three_to_four (three, to);
+               if (len == 1)
+               {
+                       to[2] = to[3] = '=';
+               }
+               else if (len == 2)
+               {
+                       to[3] = '=';
+               }
+               to += 4;
+       };
+       to[0] = 0;
+}
\ No newline at end of file
index fcb238345ee7ee3677b447122fd813f020bd3911..12a37b7dc69600b2e06ed4578730ce54932527c4 100644 (file)
@@ -80,4 +80,6 @@ char *encode_sasl_pass_plain (char *user, char *pass);
 char *challengeauth_response (const char *username, const char *password, const char *challenge);
 size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time);
 gsize strftime_utf8 (char *dest, gsize destsize, const char *format, time_t time);
+void base64_encode (char *to, char *from, unsigned int len);
+
 #endif