# HG changeset patch # User Nathan Walp # Date 1062864281 0 # Node ID 6d0d4e9149b96af91689f75ba9d0f9cce9d08978 # Parent 362e60e7c2651cae31ce0111c8d122a4e6fe0da4 [gaim-migrate @ 7296] well, jabber.org is being a pain in the moment, as is my server. but this seems to work, so here it is. Jabber SSL support. Make sure you set the port to 5223 and check the "Use SSL" checkbox in the account editor. committer: Tailor Script diff -r 362e60e7c265 -r 6d0d4e9149b9 src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Sat Sep 06 15:15:24 2003 +0000 +++ b/src/protocols/jabber/jabber.c Sat Sep 06 16:04:41 2003 +0000 @@ -36,6 +36,7 @@ #include "request.h" #include "util.h" #include "html.h" +#include "sslconn.h" /* XXX */ #include "gaim.h" @@ -110,6 +111,8 @@ void *priv; + GaimSslConnection *gsc; + } *gjconn, gjconn_struct; typedef void (*gjconn_state_h)(gjconn gjc, int state); @@ -510,7 +513,10 @@ gjab_send_raw(gjc, ""); gjc->state = JCONN_STATE_OFF; gjc->was_connected = 0; - close(gjc->fd); + if(gjc->gsc) + gaim_ssl_close(gjc->gsc); + else + close(gjc->fd); gjc->fd = -1; XML_ParserFree(gjc->parser); gjc->parser = NULL; @@ -553,14 +559,22 @@ if (gjc && gjc->state != JCONN_STATE_OFF) { char *buf = xmlnode2str(x); if (buf) { + if(gjc->gsc) { + if(gaim_ssl_write(gjc->gsc, buf, strlen(buf)) < 0) { + gaim_connection_error(GJ_GC(gjc), _("Write error")); + } else { + gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send (ssl): %s\n", buf); + } + } else { #ifndef _WIN32 - if(write(gjc->fd, buf, strlen(buf)) < 0) { + if(write(gjc->fd, buf, strlen(buf)) < 0) { #else - if(send(gjc->fd, buf, strlen(buf), 0) < 0) { + if(send(gjc->fd, buf, strlen(buf), 0) < 0) { #endif - gaim_connection_error(GJ_GC(gjc), _("Write error")); - } else { - gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send: %s\n", buf); + gaim_connection_error(GJ_GC(gjc), _("Write error")); + } else { + gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send: %s\n", buf); + } } } } @@ -572,16 +586,24 @@ /* * JFIXME: No error detection?!?! */ + if(gjc->gsc) { + if(gaim_ssl_write(gjc->gsc, str, strlen(str)) < 0) { + gaim_connection_error(GJ_GC(gjc), _("Write error")); + } else { + gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send_raw (ssl): %s\n", str); + } + } else { #ifndef _WIN32 - if(write(gjc->fd, str, strlen(str)) < 0) { + if(write(gjc->fd, str, strlen(str)) < 0) { #else - if(send(gjc->fd, str, strlen(str), 0) < 0) { + if(send(gjc->fd, str, strlen(str), 0) < 0) { #endif - gaim_connection_error(GJ_GC(gjc), _("Write error")); + gaim_connection_error(GJ_GC(gjc), _("Write error")); + } + /* printing keepalives to the debug window is really annoying */ + if(strcmp(str, JABBER_KEEPALIVE_STRING)) + gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send_raw: %s\n", str); } - /* printing keepalives to the debug window is really annoying */ - if(strcmp(str, JABBER_KEEPALIVE_STRING)) - gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send_raw: %s\n", str); } } @@ -682,6 +704,28 @@ } } +static void gjab_ssl_recv(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + static char buf[4096]; + int len; + GaimConnection *gc = data; + struct jabber_data *jd = gc->proto_data; + gjconn gjc = jd->gjc; + + if (!gjc || gjc->state == JCONN_STATE_OFF) + return; + + if((len = gaim_ssl_read(gsc, buf, sizeof(buf) -1)) > 0) { + buf[len] = '\0'; + gaim_debug(GAIM_DEBUG_MISC, "jabber", + "input (ssl) (len %d): %s\n", len, buf); + XML_Parse(gjc->parser, buf, len, 0); + } else if(len < 0) { + STATE_EVT(JCONN_STATE_OFF) + } +} + static void startElement(void *userdata, const char *name, const char **attribs) { xmlnode x; @@ -752,10 +796,52 @@ xmlnode_insert_cdata(gjc->current, s, slen); } -static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) + +static void gjab_start_stream(gjconn gjc) { xmlnode x; char *t, *t2; + + gjc->state = JCONN_STATE_CONNECTED; + STATE_EVT(JCONN_STATE_CONNECTED) + + /* start stream */ + x = jutil_header(NS_CLIENT, gjc->user->server); + t = xmlnode2str(x); + /* this is ugly, we can create the string here instead of jutil_header */ + /* what do you think about it? -madcat */ + t2 = strstr(t, "/>"); + *t2++ = '>'; + *t2 = '\0'; + gjab_send_raw(gjc, ""); + gjab_send_raw(gjc, t); + xmlnode_free(x); +} + +static void gjab_ssl_connected(gpointer data, GaimSslConnection *gsc, + GaimInputCondition cond) +{ + GaimConnection *gc = data; + struct jabber_data *jd; + gjconn gjc; + + if (!g_list_find(gaim_connections_get_all(), gc)) { + gaim_ssl_close(gsc); + return; + } + + jd = gc->proto_data; + gjc = jd->gjc; + + gjab_start_stream(gjc); + + /* this seems wrong, but... */ + + gaim_ssl_input_add(gsc, gjab_ssl_recv, gc); +} + +static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) +{ GaimConnection *gc = data; struct jabber_data *jd; gjconn gjc; @@ -775,22 +861,8 @@ return; } - gjc->state = JCONN_STATE_CONNECTED; - STATE_EVT(JCONN_STATE_CONNECTED) - - /* start stream */ - x = jutil_header(NS_CLIENT, gjc->user->server); - t = xmlnode2str(x); - /* this is ugly, we can create the string here instead of jutil_header */ - /* what do you think about it? -madcat */ - t2 = strstr(t, "/>"); - *t2++ = '>'; - *t2 = '\0'; - gjab_send_raw(gjc, ""); - gjab_send_raw(gjc, t); - xmlnode_free(x); - - gc = GJ_GC(gjc); + gjab_start_stream(gjc); + gc->inpa = gaim_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc); } @@ -815,10 +887,19 @@ XML_SetElementHandler(gjc->parser, startElement, endElement); XML_SetCharacterDataHandler(gjc->parser, charData); - rc = gaim_proxy_connect(account, server, port, gjab_connected, GJ_GC(gjc)); - if (!account->gc || (rc != 0)) { - STATE_EVT(JCONN_STATE_OFF) - return; + if(gaim_account_get_bool(account, "ssl", FALSE) + && gaim_ssl_is_supported()) { + gjc->gsc = gaim_ssl_connect(account, server, port, + gjab_ssl_connected, GJ_GC(gjc)); + } + + if(!gjc->gsc) { + rc = gaim_proxy_connect(account, server, port, gjab_connected, + GJ_GC(gjc)); + if (!account->gc || (rc != 0)) { + STATE_EVT(JCONN_STATE_OFF) + return; + } } } @@ -4426,6 +4507,13 @@ prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); /* Account Options */ + + if(gaim_ssl_is_supported()) { + option = gaim_account_option_bool_new(_("Use SSL"), "ssl", FALSE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + } + option = gaim_account_option_int_new(_("Port"), "port", DEFAULT_PORT); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); diff -r 362e60e7c265 -r 6d0d4e9149b9 src/ssl-gnutls.c --- a/src/ssl-gnutls.c Sat Sep 06 15:15:24 2003 +0000 +++ b/src/ssl-gnutls.c Sat Sep 06 16:04:41 2003 +0000 @@ -60,16 +60,6 @@ } static void -input_func(gpointer data, gint source, GaimInputCondition cond) -{ - GaimSslConnection *gsc = (GaimSslConnection *)data; - - gaim_debug_misc("gnutls", "In input_func\n"); - - gsc->input_func(gsc->user_data, gsc, cond); -} - -static void ssl_gnutls_connect_cb(gpointer data, gint source, GaimInputCondition cond) { GaimSslConnection *gsc = (GaimSslConnection *)data; @@ -103,14 +93,12 @@ { gaim_debug_error("gnutls", "Handshake failed\n"); + /* XXX: notify the guy expecting the callback somehow? */ gaim_ssl_close(gsc); } else { - gaim_debug_info("gnutls", "Adding input handler.\n"); - gsc->inpa = gaim_input_add(gsc->fd, - GAIM_INPUT_READ | GAIM_INPUT_WRITE, - input_func, gsc); + gsc->connect_cb(gsc->connect_cb_data, gsc, cond); } } diff -r 362e60e7c265 -r 6d0d4e9149b9 src/ssl-nss.c --- a/src/ssl-nss.c Sat Sep 06 15:15:24 2003 +0000 +++ b/src/ssl-nss.c Sat Sep 06 16:04:41 2003 +0000 @@ -117,33 +117,6 @@ return status; } -static void -input_func(gpointer data, gint source, GaimInputCondition cond) -{ - GaimSslConnection *gsc = (GaimSslConnection *)data; -#if 0 - GaimSslNssData *nss_data = GAIM_SSL_NSS_DATA(gsc); - char *cp, *ip, *sp; - int op, kp0, kp1; - int result; - - result = SSL_SecurityStatus(nss_data->in, &op, &cp, &kp0, - &kp1, &ip, &sp); - - gaim_debug_misc("nss", - "bulk cipher %s, %d secret key bits, %d key bits, status: %d\n" - "subject DN: %s\n" - "issuer DN: %s\n", - cp, kp1, kp0, op, sp, ip); - - PR_Free(cp); - PR_Free(ip); - PR_Free(sp); -#endif - - gsc->input_func(gsc->user_data, gsc, cond); -} - static gboolean ssl_nss_init(void) { @@ -227,9 +200,14 @@ return; } - gsc->inpa = gaim_input_add(gsc->fd, - GAIM_INPUT_READ | GAIM_INPUT_WRITE, - input_func, gsc); + gsc->connect_cb(gsc->connect_cb_data, gsc, cond); +} + +static void +ssl_nss_recv_cb(gpointer data, gint source, GaimInputCondition cond) +{ + GaimSslConnection *gsc = data; + gsc->recv_cb(gsc->recv_cb_data, gsc, cond); } static void @@ -264,6 +242,7 @@ ssl_nss_init, ssl_nss_uninit, ssl_nss_connect_cb, + ssl_nss_recv_cb, ssl_nss_close, ssl_nss_read, ssl_nss_write diff -r 362e60e7c265 -r 6d0d4e9149b9 src/sslconn.c --- a/src/sslconn.c Sat Sep 06 15:15:24 2003 +0000 +++ b/src/sslconn.c Sat Sep 06 16:04:41 2003 +0000 @@ -93,8 +93,8 @@ gsc->host = g_strdup(host); gsc->port = port; - gsc->user_data = data; - gsc->input_func = func; + gsc->connect_cb_data = data; + gsc->connect_cb = func; i = gaim_proxy_connect(account, host, port, ops->connect_cb, gsc); @@ -109,6 +109,29 @@ return (GaimSslConnection *)gsc; } +static void +recv_cb(gpointer data, gint source, GaimInputCondition cond) +{ + GaimSslConnection *gsc = data; + + gsc->recv_cb(gsc->recv_cb_data, gsc, cond); +} + +void +gaim_ssl_input_add(GaimSslConnection *gsc, GaimSslInputFunction func, void *data) +{ + GaimSslOps *ops; + + g_return_if_fail(func != NULL); + g_return_if_fail(gaim_ssl_is_supported()); + + ops = gaim_ssl_get_ops(); + + gsc->recv_cb_data = data; + gsc->recv_cb = func; + gsc->inpa = gaim_input_add(gsc->fd, GAIM_INPUT_READ, recv_cb, gsc); +} + GaimSslConnection * gaim_ssl_connect_fd(GaimAccount *account, int fd, GaimSslInputFunction func, void *data) @@ -133,8 +156,8 @@ gsc = g_new0(GaimSslConnection, 1); - gsc->user_data = data; - gsc->input_func = func; + gsc->connect_cb_data = data; + gsc->connect_cb = func; ops->connect_cb(gsc, fd, GAIM_INPUT_READ); diff -r 362e60e7c265 -r 6d0d4e9149b9 src/sslconn.h --- a/src/sslconn.h Sat Sep 06 15:15:24 2003 +0000 +++ b/src/sslconn.h Sat Sep 06 16:04:41 2003 +0000 @@ -36,8 +36,10 @@ { char *host; int port; - void *user_data; - GaimSslInputFunction input_func; + void *connect_cb_data; + GaimSslInputFunction connect_cb; + void *recv_cb_data; + GaimSslInputFunction recv_cb; int fd; int inpa; @@ -93,6 +95,16 @@ void *data); /** + * Adds an input watcher for the specified SSL connection. + * + * @param gsc The SSL connection handle. + * @param func The callback function. + * @param data User-defined data. + */ +void gaim_ssl_input_add(GaimSslConnection *gsc, GaimSslInputFunction func, + void *data); + +/** * Makes a SSL connection using an already open file descriptor. * * @param account The account making the connection.