aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/jabber/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/jabber/io.c')
-rw-r--r--protocols/jabber/io.c107
1 files changed, 98 insertions, 9 deletions
diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c
index 333e3123..f1f62a48 100644
--- a/protocols/jabber/io.c
+++ b/protocols/jabber/io.c
@@ -22,6 +22,7 @@
\***************************************************************************/
#include "jabber.h"
+#include "ssl_client.h"
static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond );
@@ -75,7 +76,12 @@ static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition
if( jd->fd == -1 )
return FALSE;
- st = write( jd->fd, jd->txq, jd->tx_len );
+ if( jd->ssl )
+ st = ssl_write( jd->ssl, jd->txq, jd->tx_len );
+ else
+ st = write( jd->fd, jd->txq, jd->tx_len );
+
+// if( st > 0 ) write( 1, jd->txq, st );
if( st == jd->tx_len )
{
@@ -125,7 +131,12 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition
if( jd->fd == -1 )
return FALSE;
- st = read( fd, buf, sizeof( buf ) );
+ if( jd->ssl )
+ st = ssl_read( jd->ssl, buf, sizeof( buf ) );
+ else
+ st = read( jd->fd, buf, sizeof( buf ) );
+
+// if( st > 0 ) write( 1, buf, st );
if( st > 0 )
{
@@ -209,6 +220,22 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c
return jabber_start_stream( gc );
}
+gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond )
+{
+ struct gaim_connection *gc = data;
+
+ if( source == NULL )
+ {
+ hide_login_progress( gc, "Could not connect to server" );
+ signoff( gc );
+ return FALSE;
+ }
+
+ set_login_progress( gc, 1, "Connected to server, logging in" );
+
+ return jabber_start_stream( gc );
+}
+
static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data )
{
return XT_ABORT;
@@ -221,15 +248,43 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
struct xt_node *c, *reply;
c = xt_find_node( node->children, "starttls" );
- if( c )
+ if( c && !jd->ssl )
{
- /*
- jd->flags |= JFLAG_SUPPORTS_TLS;
- if( xt_find_node( c->children, "required" ) )
- jd->flags |= JFLAG_REQUIRES_TLS;
- */
+ /* If the server advertises the STARTTLS feature and if we're
+ not in a secure connection already: */
+
+ int try;
+
+ try = g_strcasecmp( set_getstr( &gc->acc->set, "tls" ), "try" ) == 0;
+ c = xt_find_node( c->children, "required" );
+
+ /* Only run this if the tls setting is set to true or try: */
+ if( ( try | set_getbool( &gc->acc->set, "tls" ) ) )
+ {
+ reply = xt_new_node( "starttls", NULL, NULL );
+ xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-tls" );
+ if( !jabber_write_packet( gc, reply ) )
+ {
+ xt_free_node( reply );
+ return XT_ABORT;
+ }
+ xt_free_node( reply );
+
+ return XT_HANDLED;
+ }
+ }
+ else
+ {
+ /* TODO: Abort if TLS is required by the user. */
}
+ /* This one used to be in jabber_handlers[], but it has to be done
+ from here to make sure the TLS session will be initialized
+ properly before we attempt SASL authentication. */
+ if( ( c = xt_find_node( node->children, "mechanisms" ) ) )
+ if( sasl_pkt_mechanisms( c, data ) == XT_ABORT )
+ return XT_ABORT;
+
if( ( c = xt_find_node( node->children, "bind" ) ) )
{
reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
@@ -268,6 +323,40 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
return XT_HANDLED;
}
+static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data )
+{
+ struct gaim_connection *gc = data;
+ struct jabber_data *jd = gc->proto_data;
+ char *xmlns;
+
+ xmlns = xt_find_attr( node, "xmlns" );
+
+ /* Just ignore it when it doesn't seem to be TLS-related (is that at
+ all possible??). */
+ if( !xmlns || strcmp( xmlns, "urn:ietf:params:xml:ns:xmpp-tls" ) != 0 )
+ return XT_HANDLED;
+
+ /* We don't want event handlers to touch our TLS session while it's
+ still initializing! */
+ b_event_remove( jd->r_inpa );
+ if( jd->tx_len > 0 )
+ {
+ /* Actually the write queue should be empty here, but just
+ to be sure... */
+ b_event_remove( jd->w_inpa );
+ g_free( jd->txq );
+ jd->txq = NULL;
+ jd->tx_len = 0;
+ }
+ jd->w_inpa = jd->r_inpa = 0;
+
+ set_login_progress( gc, 1, "Converting stream to TLS" );
+
+ jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, gc );
+
+ return XT_HANDLED;
+}
+
static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data )
{
printf( "Received unknown packet:\n" );
@@ -282,7 +371,7 @@ static const struct xt_handler_entry jabber_handlers[] = {
{ "presence", "stream:stream", jabber_pkt_presence },
{ "iq", "stream:stream", jabber_pkt_iq },
{ "stream:features", "stream:stream", jabber_pkt_features },
- { "mechanisms", "stream:features", sasl_pkt_mechanisms },
+ { "proceed", "stream:stream", jabber_pkt_proceed_tls },
{ "challenge", "stream:stream", sasl_pkt_challenge },
{ "success", "stream:stream", sasl_pkt_result },
{ "failure", "stream:stream", sasl_pkt_result },