diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2006-09-22 20:39:31 +0200 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2006-09-22 20:39:31 +0200 | 
| commit | fe7a55434385fd858453dffdbb425a21f41e3859 (patch) | |
| tree | 31f7d29dd436d59d80d06674c12b98b934ddb467 /protocols | |
| parent | 8d7429102adf8dce6844f2f3da2723d1f87c6442 (diff) | |
Better detection of successful IQ authentication (using packet caching),
properly working SASL authentication (although only PLAIN so far).
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/jabber/io.c | 33 | ||||
| -rw-r--r-- | protocols/jabber/iq.c | 34 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 6 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 6 | ||||
| -rw-r--r-- | protocols/jabber/jabber_util.c | 29 | ||||
| -rw-r--r-- | protocols/jabber/sasl.c | 10 | 
6 files changed, 105 insertions, 13 deletions
| diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 8f2ce0f1..333e3123 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -218,7 +218,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )  {  	struct gaim_connection *gc = data;  	struct jabber_data *jd = gc->proto_data; -	struct xt_node *c; +	struct xt_node *c, *reply;  	c = xt_find_node( node->children, "starttls" );  	if( c ) @@ -230,9 +230,36 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )  		*/  	} +	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 ) ); +		xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" ); +		reply = jabber_make_packet( "iq", "set", NULL, reply ); +		jabber_cache_packet( gc, reply ); +		 +		if( !jabber_write_packet( gc, reply ) ) +			return XT_ABORT; +		 +		jd->flags |= JFLAG_WAIT_BIND; +	} +	 +	if( ( c = xt_find_node( node->children, "session" ) ) ) +	{ +		reply = xt_new_node( "session", NULL, NULL ); +		xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" ); +		reply = jabber_make_packet( "iq", "set", NULL, reply ); +		jabber_cache_packet( gc, reply ); +		 +		if( !jabber_write_packet( gc, reply ) ) +			return XT_ABORT; +		 +		jd->flags |= JFLAG_WAIT_SESSION; +	} +	  	/* This flag is already set if we authenticated via SASL, so now -	   we can resume the session in the new stream. */ -	if( jd->flags & JFLAG_AUTHENTICATED ) +	   we can resume the session in the new stream, if we don't have +	   to bind/initialize the session. */ +	if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )  	{  		if( !jabber_get_roster( gc ) )  			return XT_ABORT; diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index bcce5289..fbb4a38b 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -27,7 +27,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  {  	struct gaim_connection *gc = data;  	struct jabber_data *jd = gc->proto_data; -	struct xt_node *query, *reply = NULL; +	struct xt_node *query, *reply = NULL, *orig = NULL;  	char *s, *type, *xmlns;  	int st; @@ -39,6 +39,9 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  	xmlns = xt_find_attr( query, "xmlns" ); +	if( ( s = xt_find_attr( node, "id" ) ) ) +		orig = jabber_packet_from_cache( gc, s ); +	  	if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 )  	{  		/* Time to authenticate ourselves! */ @@ -81,8 +84,8 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  		}  		reply = jabber_make_packet( "iq", "set", NULL, reply ); +		jabber_cache_packet( gc, reply );  		st = jabber_write_packet( gc, reply ); -		xt_free_node( reply );  		return st ? XT_HANDLED : XT_ABORT;  	} @@ -105,16 +108,35 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  		presence_announce( gc );  	} -	else if( strcmp( type, "result" ) == 0 ) +	else if( strcmp( type, "result" ) == 0 && orig )  	{ -		/* If we weren't authenticated yet, let's assume we are now. -		   There are cleaner ways to do this, probably, but well.. */ -		if( !( jd->flags & JFLAG_AUTHENTICATED ) ) +		struct xt_node *node; +		 +		if( !( jd->flags & JFLAG_AUTHENTICATED ) && +		    ( node = xt_find_node( orig->children, "query" ) ) && +		    ( node = xt_find_node( node->children, "username" ) ) && +		    node->text_len )  		{ +			/* This happens when we just successfully authenticated +			   the old (non-SASL) way. */  			jd->flags |= JFLAG_AUTHENTICATED;  			if( !jabber_get_roster( gc ) )  				return XT_ABORT;  		} +		else if( ( node = xt_find_node( orig->children, "bind" ) ) || +		         ( node = xt_find_node( orig->children, "session" ) ) ) +		{ +			if( strcmp( node->name, "bind" ) == 0 ) +				jd->flags &= ~JFLAG_WAIT_BIND; +			else if( strcmp( node->name, "session" ) == 0 ) +				jd->flags &= ~JFLAG_WAIT_SESSION; +			 +			if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) +			{ +				if( !jabber_get_roster( gc ) ) +					return XT_ABORT; +			} +		}  	}  	else if( strcmp( type, "error" ) == 0 )  	{ diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 13eac23e..c8525db5 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -75,6 +75,8 @@ static void jabber_login( account_t *acc )  	*jd->server = 0;  	jd->server ++; +	jd->node_cache = xt_new_node( "cache", NULL, NULL ); +	  	if( set_getbool( &acc->set, "ssl" ) )  	{  		signoff( gc ); @@ -102,6 +104,10 @@ static void jabber_close( struct gaim_connection *gc )  	if( jd->fd >= 0 )  		closesocket( jd->fd ); +	if( jd->tx_len ) +		g_free( jd->txq ); +	 +	xt_free_node( jd->node_cache );  	xt_free( jd->xt );  	g_free( jd->username ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index f8b604b0..c2d3867e 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -34,6 +34,8 @@ typedef enum  	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_WAIT_SESSION = 8,		/* Set if we sent a <session> tag and need a reply before we continue. */ +	JFLAG_WAIT_BIND = 16,		/* ... for <bind> tag. */  } jabber_flags_t;  /* iq.c */ @@ -52,6 +54,8 @@ int presence_send( struct gaim_connection *gc, char *to, char *show, char *statu  char *set_eval_resprio( set_t *set, char *value );  char *set_eval_tls( set_t *set, char *value );  struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); +void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ); +struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id );  /* io.c */  int jabber_write_packet( struct gaim_connection *gc, struct xt_node *node ); @@ -81,6 +85,8 @@ struct jabber_data  	char *username;		/* USERNAME@server */  	char *server;		/* username@SERVER -=> server/domain, not hostname */ +	 +	struct xt_node *node_cache;  };  #endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 46811d05..88b9e55d 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -51,18 +51,43 @@ char *set_eval_tls( set_t *set, char *value )  struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children )  { -	char *id = g_strdup_printf( "BeeX%04x", next_id++ );  	struct xt_node *node;  	node = xt_new_node( name, NULL, children ); -	xt_add_attr( node, "id", id );  	if( type )  		xt_add_attr( node, "type", type );  	if( to )  		xt_add_attr( node, "to", to ); +	return node; +} + +/* Cache a node/packet for later use. Mainly useful for IQ packets if you need +   them when you receive the response. Use this BEFORE sending the packet so +   it'll get an id= tag, and do NOT free() the packet after writing it! */ +void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node ) +{ +	struct jabber_data *jd = gc->proto_data; +	char *id = g_strdup_printf( "BeeX%04x", next_id++ ); +	 +	/* FIXME: Maybe start using g_error() here if nodes still have a parent, for example? */ +	 +	xt_add_attr( node, "id", id ); +	xt_add_child( jd->node_cache, node );  	g_free( id ); +} + +/* Emptying this cache is a BIG TODO! */ +struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id ) +{ +	struct jabber_data *jd = gc->proto_data; +	struct xt_node *node; +	char *s; +	 +	for( node = jd->node_cache->children; node; node = node->next ) +		if( ( s = xt_find_attr( node, "id" ) ) && strcmp( id, s ) == 0 ) +			break;  	return node;  } diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 2f75e733..13ff9d26 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -70,7 +70,13 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )  	reply = xt_new_node( "auth", NULL, NULL );  	xt_add_attr( reply, "xmlns", SASL_NS ); -	if( sup_plain ) +	if( sup_digest && 0 ) +	{ +		xt_add_attr( reply, "mechanism", "DIGEST-MD5" ); +		 +		/* The rest will be done later, when we receive a <challenge/>. */ +	} +	else if( sup_plain )  	{  		int len; @@ -140,5 +146,5 @@ gboolean sasl_supported( struct gaim_connection *gc )  {  	struct jabber_data *jd = gc->proto_data; -	return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != NULL; +	return ( (void*) ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) ) != NULL;  } | 
