Example #1
0
File: iq.c Project: shiplu/bitlbee
xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
{
	struct xt_node *node, *query;
	struct jabber_buddy *bud;
	
	if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
	{
		/* Who cares about the unknown... */
		imcb_log( ic, "Couldn't find buddy: %s", bare_jid);
		return XT_HANDLED;
	}
	
	if( bud->features ) /* been here already */
		return XT_HANDLED;
	
	node = xt_new_node( "query", NULL, NULL );
	xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
	
	if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
	{
		imcb_log( ic, "WARNING: Couldn't generate feature query" );
		xt_free_node( node );
		return XT_HANDLED;
	}

	jabber_cache_add( ic, query, jabber_iq_parse_features );

	return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
}
Example #2
0
File: iq.c Project: shiplu/bitlbee
static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
{
	struct jabber_data *jd = ic->proto_data;
	struct xt_node *reply, *query;
	xt_status st;
	char *s;
	
	if( !( query = xt_find_node( node->children, "query" ) ) )
	{
		imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" );
		imc_logout( ic, FALSE );
		return XT_HANDLED;
	}
	
	/* Time to authenticate ourselves! */
	reply = xt_new_node( "query", NULL, NULL );
	xt_add_attr( reply, "xmlns", XMLNS_AUTH );
	xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
	xt_add_child( reply, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
	
	if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) )
	{
		/* We can do digest authentication, it seems, and of
		   course we prefer that. */
		sha1_state_t sha;
		char hash_hex[41];
		unsigned char hash[20];
		int i;
		
		sha1_init( &sha );
		sha1_append( &sha, (unsigned char*) s, strlen( s ) );
		sha1_append( &sha, (unsigned char*) ic->acc->pass, strlen( ic->acc->pass ) );
		sha1_finish( &sha, hash );
		
		for( i = 0; i < 20; i ++ )
			sprintf( hash_hex + i * 2, "%02x", hash[i] );
		
		xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) );
	}
	else if( xt_find_node( query->children, "password" ) )
	{
		/* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */
		xt_add_child( reply, xt_new_node( "password", ic->acc->pass, NULL ) );
	}
	else
	{
		xt_free_node( reply );
		
		imcb_error( ic, "Can't find suitable authentication method" );
		imc_logout( ic, FALSE );
		return XT_ABORT;
	}
	
	reply = jabber_make_packet( "iq", "set", NULL, reply );
	jabber_cache_add( ic, reply, jabber_finish_iq_auth );
	st = jabber_write_packet( ic, reply );
	
	return st ? XT_HANDLED : XT_ABORT;
}
Example #3
0
File: iq.c Project: shiplu/bitlbee
void jabber_iq_version_send( struct im_connection *ic, struct jabber_buddy *bud, void *data )
{
	struct xt_node *node, *query;
	
	node = xt_new_node( "query", NULL, NULL );
	xt_add_attr( node, "xmlns", XMLNS_VERSION );
	query = jabber_make_packet( "iq", "get", bud->full_jid, node );
	jabber_cache_add( ic, query, jabber_iq_version_response );

	jabber_write_packet( ic, query );
}
Example #4
0
File: iq.c Project: shiplu/bitlbee
static int jabber_iq_disco_server( struct im_connection *ic )
{
	struct xt_node *node, *iq;
	struct jabber_data *jd = ic->proto_data;
	
	node = xt_new_node( "query", NULL, NULL );
	xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
	iq = jabber_make_packet( "iq", "get", jd->server, node );
	
	jabber_cache_add( ic, iq, jabber_iq_disco_server_response );
	return jabber_write_packet( ic, iq );
}
Example #5
0
File: iq.c Project: shiplu/bitlbee
int jabber_get_vcard( struct im_connection *ic, char *bare_jid )
{
	struct xt_node *node;
	
	if( strchr( bare_jid, '/' ) )
		return 1;	/* This was an error, but return 0 should only be done if the connection died... */
	
	node = xt_new_node( "vCard", NULL, NULL );
	xt_add_attr( node, "xmlns", XMLNS_VCARD );
	node = jabber_make_packet( "iq", "get", bare_jid, node );
	
	jabber_cache_add( ic, node, jabber_iq_display_vcard );
	return jabber_write_packet( ic, node );
}
Example #6
0
File: iq.c Project: shiplu/bitlbee
int jabber_init_iq_auth( struct im_connection *ic )
{
	struct jabber_data *jd = ic->proto_data;
	struct xt_node *node;
	int st;
	
	node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) );
	xt_add_attr( node, "xmlns", XMLNS_AUTH );
	node = jabber_make_packet( "iq", "get", NULL, node );
	
	jabber_cache_add( ic, node, jabber_do_iq_auth );
	st = jabber_write_packet( ic, node );
	
	return st;
}
Example #7
0
File: iq.c Project: shiplu/bitlbee
int jabber_get_roster( struct im_connection *ic )
{
	struct xt_node *node;
	int st;
	
	imcb_log( ic, "Authenticated, requesting buddy list" );
	
	node = xt_new_node( "query", NULL, NULL );
	xt_add_attr( node, "xmlns", XMLNS_ROSTER );
	node = jabber_make_packet( "iq", "get", NULL, node );
	
	jabber_cache_add( ic, node, jabber_parse_roster );
	st = jabber_write_packet( ic, node );
	
	return st;
}
Example #8
0
File: iq.c Project: shiplu/bitlbee
xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
{
	struct xt_node *node, *query;
	struct jabber_data *jd = ic->proto_data;
	
	node = xt_new_node( "query", NULL, NULL );
	xt_add_attr( node, "xmlns", xmlns );
	
	if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
	{
		imcb_log( ic, "WARNING: Couldn't generate server query" );
		xt_free_node( node );
	}

	jd->have_streamhosts--;
	jabber_cache_add( ic, query, jabber_iq_parse_server_features );

	return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
}
Example #9
0
struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password)
{
	struct jabber_chat *jc;
	struct xt_node *node;
	struct groupchat *c;
	char *roomjid;

	roomjid = g_strdup_printf("%s/%s", room, nick);
	node = xt_new_node("x", NULL, NULL);
	xt_add_attr(node, "xmlns", XMLNS_MUC);
	if (password) {
		xt_add_child(node, xt_new_node("password", password, NULL));
	}
	node = jabber_make_packet("presence", NULL, roomjid, node);
	jabber_cache_add(ic, node, jabber_chat_join_failed);

	if (!jabber_write_packet(ic, node)) {
		g_free(roomjid);
		return NULL;
	}

	jc = g_new0(struct jabber_chat, 1);
	jc->name = jabber_normalize(room);

	if ((jc->me = jabber_buddy_add(ic, roomjid)) == NULL) {
		g_free(roomjid);
		g_free(jc->name);
		g_free(jc);
		return NULL;
	}

	/* roomjid isn't normalized yet, and we need an original version
	   of the nick to send a proper presence update. */
	jc->my_full_jid = roomjid;

	c = imcb_chat_new(ic, room);
	c->data = jc;

	return c;
}
Example #10
0
File: iq.c Project: shiplu/bitlbee
int jabber_add_to_roster( struct im_connection *ic, const char *handle, const char *name, const char *group )
{
	struct xt_node *node;
	int st;
	
	/* Build the item entry */
	node = xt_new_node( "item", NULL, NULL );
	xt_add_attr( node, "jid", handle );
	if( name )
		xt_add_attr( node, "name", name );
	if( group )
		xt_add_child( node, xt_new_node( "group", group, NULL ) );
	
	/* And pack it into a roster-add packet */
	node = xt_new_node( "query", NULL, node );
	xt_add_attr( node, "xmlns", XMLNS_ROSTER );
	node = jabber_make_packet( "iq", "set", NULL, node );
	jabber_cache_add( ic, node, jabber_add_to_roster_callback );
	
	st = jabber_write_packet( ic, node );
	
	return st;
}
Example #11
0
static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
{
	struct im_connection *ic = data;
	struct jabber_data *jd = ic->proto_data;
	struct xt_node *c, *reply;
	int trytls;
	
	trytls = g_strcasecmp( set_getstr( &ic->acc->set, "tls" ), "try" ) == 0;
	c = xt_find_node( node->children, "starttls" );
	if( c && !jd->ssl )
	{
		/* If the server advertises the STARTTLS feature and if we're
		   not in a secure connection already: */
		
		c = xt_find_node( c->children, "required" );
		
		if( c && ( !trytls && !set_getbool( &ic->acc->set, "tls" ) ) )
		{
			imcb_error( ic, "Server requires TLS connections, but TLS is turned off for this account" );
			imc_logout( ic, FALSE );
			
			return XT_ABORT;
		}
		
		/* Only run this if the tls setting is set to true or try: */
		if( ( trytls || set_getbool( &ic->acc->set, "tls" ) ) )
		{
			reply = xt_new_node( "starttls", NULL, NULL );
			xt_add_attr( reply, "xmlns", XMLNS_TLS );
			if( !jabber_write_packet( ic, reply ) )
			{
				xt_free_node( reply );
				return XT_ABORT;
			}
			xt_free_node( reply );
			
			return XT_HANDLED;
		}
	}
	else if( !c && !jd->ssl )
	{
		/* If the server does not advertise the STARTTLS feature and
		   we're not in a secure connection already: (Servers have a
		   habit of not advertising <starttls/> anymore when already
		   using SSL/TLS. */
		
		if( !trytls && set_getbool( &ic->acc->set, "tls" ) )
		{
			imcb_error( ic, "TLS is turned on for this account, but is not supported by this server" );
			imc_logout( ic, FALSE );
			
			return XT_ABORT;
		}
	}
	
	/* 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 the server *SEEMS* to support SASL authentication but doesn't
	   support it after all, we should try to do authentication the
	   other way. jabber.com doesn't seem to do SASL while it pretends
	   to be XMPP 1.0 compliant! */
	else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( ic ) )
	{
		if( !jabber_init_iq_auth( ic ) )
			return XT_ABORT;
	}
	
	if( ( c = xt_find_node( node->children, "bind" ) ) )
	{
		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
		xt_add_attr( reply, "xmlns", XMLNS_BIND );
		reply = jabber_make_packet( "iq", "set", NULL, reply );
		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
		
		if( !jabber_write_packet( ic, 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", XMLNS_SESSION );
		reply = jabber_make_packet( "iq", "set", NULL, reply );
		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
		
		if( !jabber_write_packet( ic, 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 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( ic ) )
			return XT_ABORT;
	}
	
	return XT_HANDLED;
}
Example #12
0
File: iq.c Project: shiplu/bitlbee
xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
{
	struct jabber_data *jd = ic->proto_data;
	struct xt_node *c, *reply = NULL;
	char *s;
	
	if( node && ( c = xt_find_node( node->children, "bind" ) ) )
	{
		c = xt_find_node( c->children, "jid" );
		if( !c || !c->text )
		{
			/* Server is crap, but this is no disaster. */
		}
		else if( strncmp( jd->me, c->text, strlen( jd->me ) ) != 0 )
		{
			s = strchr( c->text, '/' );
			if( s )
				*s = '\0';
			jabber_set_me( ic, c->text );
			imcb_log( ic, "Server claims your JID is `%s' instead of `%s'. "
			          "This mismatch may cause problems with groupchats "
			          "and possibly other things.",
			          c->text, ic->acc->user );
			if( s )
				*s = '/';
		}
		else if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
		         strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 )
			imcb_log( ic, "Server changed session resource string to `%s'", s + 1 );
	}
	
	if( jd->flags & JFLAG_WANT_BIND )
	{
		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
		xt_add_attr( reply, "xmlns", XMLNS_BIND );
		jd->flags &= ~JFLAG_WANT_BIND;
	}
	else if( jd->flags & JFLAG_WANT_SESSION )
	{
		reply = xt_new_node( "session", NULL, NULL );
		xt_add_attr( reply, "xmlns", XMLNS_SESSION );
		jd->flags &= ~JFLAG_WANT_SESSION;
	}
	
	if( reply != NULL )
	{
		reply = jabber_make_packet( "iq", "set", NULL, reply );
		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
		
		if( !jabber_write_packet( ic, reply ) )
			return XT_ABORT;
	}
	else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 )
	{
		if( !jabber_get_roster( ic ) )
			return XT_ABORT;
		if( !jabber_iq_disco_server( ic ) )
			return XT_ABORT;
	}
	
	return XT_HANDLED;
}