diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/jabber/Makefile | 2 | ||||
| -rw-r--r-- | protocols/jabber/io.c | 15 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 11 | ||||
| -rw-r--r-- | protocols/jabber/sasl.c | 124 | 
4 files changed, 146 insertions, 6 deletions
| diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile index d4dcc652..c084b1f4 100644 --- a/protocols/jabber/Makefile +++ b/protocols/jabber/Makefile @@ -9,7 +9,7 @@  -include ../../Makefile.settings  # [SH] Program variables -objects = io.o iq.o jabber.o jabber_util.o message.o presence.o xmltree.o +objects = io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o  CFLAGS += -Wall  LFLAGS += -r diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index b11ef17d..c7c1d8d9 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -135,6 +135,13 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition  			return FALSE;  		} +		if( jd->flags & JFLAG_STREAM_RESTART ) +		{ +			jd->flags &= ~JFLAG_STREAM_RESTART; +			xt_reset( jd->xt ); +			jabber_start_stream( gc ); +		} +		  		/* Garbage collection. */  		xt_cleanup( jd->xt, NULL ); @@ -203,6 +210,10 @@ static const struct xt_handler_entry jabber_handlers[] = {  	{ "iq",                 "stream:stream",        jabber_pkt_iq },  	{ "message",            "stream:stream",        jabber_pkt_message },  	{ "presence",           "stream:stream",        jabber_pkt_presence }, +	{ "mechanisms",         "stream:features",      sasl_pkt_mechanisms }, +	{ "challenge",          "stream:stream",        sasl_pkt_challenge }, +	{ "success",            "stream:stream",        sasl_pkt_result }, +	{ "failure",            "stream:stream",        sasl_pkt_result },  	{ NULL,                 "stream:stream",        jabber_pkt_misc },  	{ NULL,                 NULL,                   NULL }  }; @@ -223,9 +234,7 @@ gboolean jabber_start_stream( struct gaim_connection *gc )  	greet = g_strdup_printf( "<?xml version='1.0' ?>"  	                         "<stream:stream to=\"%s\" xmlns=\"jabber:client\" " -	                          "xmlns:stream=\"http://etherx.jabber.org/streams\">", jd->server ); -	/* Add this when TLS and SASL are supported? */ -	// version=\"1.0\">" +	                          "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server );  	st = jabber_write( gc, greet, strlen( greet ) ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 775cd787..03fe57a7 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -31,8 +31,10 @@  typedef enum  { -	JFLAG_STREAM_STARTED = 1, -	JFLAG_AUTHENTICATED = 2, +	JFLAG_STREAM_STARTED = 1,	/* Set when we detected the beginning of the stream and want to do auth. */ +	JFLAG_AUTHENTICATED = 2,	/* Set when we're successfully authenticatd. */ +	JFLAG_STREAM_RESTART = 4,	/* Set when we want to restart the stream (after SASL or TLS). */ +	JFLAG_SUPPORTS_TLS = 8,		/* Set when there's <starttls/> in <stream:features>. */  } jabber_flags_t;  /* iq.c */ @@ -59,6 +61,11 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c  gboolean jabber_start_stream( struct gaim_connection *gc );  void jabber_end_stream( struct gaim_connection *gc ); +/* sasl.c */ +xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ); +xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ); +xt_status sasl_pkt_result( struct xt_node *node, gpointer data ); +  struct jabber_data  {  	struct gaim_connection *gc; diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c new file mode 100644 index 00000000..da577877 --- /dev/null +++ b/protocols/jabber/sasl.c @@ -0,0 +1,124 @@ +/***************************************************************************\ +*                                                                           * +*  BitlBee - An IRC to IM gateway                                           * +*  Jabber module - SASL authentication                                      * +*                                                                           * +*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   * +*                                                                           * +*  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 Street, Fifth Floor, Boston, MA 02110-1301 USA.              * +*                                                                           * +\***************************************************************************/ + +#include "jabber.h" +#include "base64.h" + +#define SASL_NS "urn:ietf:params:xml:ns:xmpp-sasl" + +xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) +{ +	struct gaim_connection *gc = data; +	struct jabber_data *jd = gc->proto_data; +	struct xt_node *c, *reply; +	char *s; +	int sup_plain = 0, sup_digest = 0; +	 +	s = xt_find_attr( node, "xmlns" ); +	if( !s || strcmp( s, SASL_NS ) != 0 ) +	{ +		signoff( gc ); +		return XT_ABORT; +	} +	 +	c = node->children; +	while( ( c = xt_find_node( c, "mechanism" ) ) ) +	{ +		if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 ) +			sup_plain = 1; +		if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 ) +			sup_digest = 1; +		 +		c = c->next; +	} +	 +	if( !sup_plain && !sup_digest ) +	{ +		signoff( gc ); +		return XT_ABORT; +	} +	 +	reply = xt_new_node( "auth", NULL, NULL ); +	xt_add_attr( reply, "xmlns", SASL_NS ); +	 +	if( sup_plain ) +	{ +		int len; +		 +		xt_add_attr( reply, "mechanism", "PLAIN" ); +		 +		/* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */ +		len = strlen( jd->username ) + strlen( gc->acc->pass ) + 2; +		s = g_malloc( len + 1 ); +		s[0] = 0; +		strcpy( s + 1, jd->username ); +		strcpy( s + 2 + strlen( jd->username ), gc->acc->pass ); +		reply->text = base64_encode( s, len ); +		reply->text_len = strlen( reply->text ); +		g_free( s ); +	} +	 +	if( !jabber_write_packet( gc, reply ) ) +	{ +		xt_free_node( reply ); +		return XT_ABORT; +	} +	xt_free_node( reply ); +	 +	/* To prevent classic authentication from happening. */ +	jd->flags |= JFLAG_STREAM_STARTED; +	 +	return XT_HANDLED; +} + +xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) +{ +} + +xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) +{ +	struct gaim_connection *gc = data; +	struct jabber_data *jd = gc->proto_data; +	char *s; +	 +	s = xt_find_attr( node, "xmlns" ); +	if( !s || strcmp( s, SASL_NS ) != 0 ) +	{ +		signoff( gc ); +		return XT_ABORT; +	} +	 +	if( strcmp( node->name, "success" ) == 0 ) +	{ +		set_login_progress( gc, 1, "Authentication finished" ); +		jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; +	} +	else if( strcmp( node->name, "failure" ) == 0 ) +	{ +		hide_login_progress( gc, "Authentication failure" ); +		signoff( gc ); +		return XT_ABORT; +	} +	 +	return XT_HANDLED; +} | 
