aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/jabber/iq.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/jabber/iq.c')
-rw-r--r--protocols/jabber/iq.c274
1 files changed, 149 insertions, 125 deletions
diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c
index ae4ed099..1b968739 100644
--- a/protocols/jabber/iq.c
+++ b/protocols/jabber/iq.c
@@ -27,161 +27,161 @@ 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, *orig = NULL, *c;
- char *s, *type, *xmlns;
- int st;
+ char *type, *s;
- query = xt_find_node( node->children, "query" );
type = xt_find_attr( node, "type" );
if( !type )
- return XT_HANDLED; /* Ignore it for now, don't know what's best... */
+ {
+ hide_login_progress_error( gc, "Received IQ packet without type!" );
+ signoff( gc );
+ return XT_ABORT;
+ }
+
+ if( ( s = xt_find_attr( node, "id" ) ) &&
+ ( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) )
+ {
+ struct jabber_cache_entry *entry;
+
+ entry = g_hash_table_lookup( jd->node_cache, s );
+
+ if( entry == NULL )
+ serv_got_crap( gc, "WARNING: Received IQ %s packet with unknown/expired ID %s!", type, s );
+ else if( entry->func )
+ return entry->func( gc, node, entry->node );
+ }
+
+ return XT_HANDLED;
+}
+
+static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+
+int jabber_init_iq_auth( struct gaim_connection *gc )
+{
+ struct jabber_data *jd = gc->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", "jabber:iq:auth" );
+ node = jabber_make_packet( "iq", "get", NULL, node );
- xmlns = xt_find_attr( query, "xmlns" );
+ jabber_cache_add( gc, node, jabber_do_iq_auth );
+ st = jabber_write_packet( gc, node );
- if( ( s = xt_find_attr( node, "id" ) ) )
- orig = jabber_cache_get( gc, s );
+ return st;
+}
+
+static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+ struct jabber_data *jd = gc->proto_data;
+ struct xt_node *reply, *query;
+ xt_status st;
+ char *s;
- if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 )
+ query = xt_find_node( node->children, "query" );
+
+ /* Time to authenticate ourselves! */
+ reply = xt_new_node( "query", NULL, NULL );
+ xt_add_attr( reply, "xmlns", "jabber:iq:auth" );
+ xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
+ xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
+
+ if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) )
{
- /* Time to authenticate ourselves! */
- reply = xt_new_node( "query", NULL, NULL );
- xt_add_attr( reply, "xmlns", "jabber:iq:auth" );
- xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) );
- xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
+ /* We can do digest authentication, it seems, and of
+ course we prefer that. */
+ SHA_CTX sha;
+ char hash_hex[40];
+ unsigned char hash[20];
+ int i;
- 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. */
- SHA_CTX sha;
- char hash_hex[40];
- unsigned char hash[20];
- int i;
-
- shaInit( &sha );
- shaUpdate( &sha, (unsigned char*) s, strlen( s ) );
- shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) );
- shaFinal( &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", gc->acc->pass, NULL ) );
- }
- else
- {
- xt_free_node( reply );
-
- hide_login_progress( gc, "Can't find suitable authentication method" );
- signoff( gc );
- return XT_ABORT;
- }
+ shaInit( &sha );
+ shaUpdate( &sha, (unsigned char*) s, strlen( s ) );
+ shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) );
+ shaFinal( &sha, hash );
- reply = jabber_make_packet( "iq", "set", NULL, reply );
- jabber_cache_add( gc, reply );
- st = jabber_write_packet( gc, reply );
+ for( i = 0; i < 20; i ++ )
+ sprintf( hash_hex + i * 2, "%02x", hash[i] );
- return st ? XT_HANDLED : XT_ABORT;
+ xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) );
}
- if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:roster" ) == 0 )
+ else if( xt_find_node( query->children, "password" ) )
{
- struct xt_node *node;
-
- node = query->children;
- while( ( node = xt_find_node( node, "item" ) ) )
- {
- char *jid = xt_find_attr( node, "jid" );
- char *name = xt_find_attr( node, "name" );
- char *sub = xt_find_attr( node, "subscription" );
-
- if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
- add_buddy( gc, NULL, jid, name );
-
- node = node->next;
- }
-
- account_online( gc );
+ /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */
+ xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) );
}
- else if( strcmp( type, "result" ) == 0 && orig )
+ else
{
- struct xt_node *c;
+ xt_free_node( reply );
- if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
- ( c = xt_find_node( orig->children, "query" ) ) &&
- ( c = xt_find_node( c->children, "username" ) ) &&
- c->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;
- }
- /* Tricky: Look for <bind> in the reply, because the server
- should confirm the chosen resource string there. For
- <session>, however, look in the cache, because the server
- will probably not include it in its reply. */
- else if( ( c = xt_find_node( node->children, "bind" ) ) ||
- ( c = xt_find_node( orig->children, "session" ) ) )
- {
- if( strcmp( c->name, "bind" ) == 0 )
- {
- c = xt_find_node( c->children, "jid" );
- if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
- strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 )
- serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 );
-
- jd->flags &= ~JFLAG_WAIT_BIND;
- }
- else if( strcmp( c->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;
- }
- }
+ hide_login_progress( gc, "Can't find suitable authentication method" );
+ signoff( gc );
+ return XT_ABORT;
}
- else if( strcmp( type, "error" ) == 0 )
+
+ reply = jabber_make_packet( "iq", "set", NULL, reply );
+ jabber_cache_add( gc, reply, jabber_finish_iq_auth );
+ st = jabber_write_packet( gc, reply );
+
+ return st ? XT_HANDLED : XT_ABORT;
+}
+
+static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+ char *type = xt_find_attr( node, "type" );
+ struct jabber_data *jd = gc->proto_data;
+
+ if( strcmp( type, "error" ) == 0 )
+ {
+ hide_login_progress( gc, "Authentication failure" );
+ signoff( gc );
+ return XT_ABORT;
+ }
+ else if( strcmp( type, "result" ) == 0 )
{
- if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
- orig &&
- ( c = xt_find_node( orig->children, "query" ) ) &&
- ( c = xt_find_node( c->children, "username" ) ) &&
- c->text_len )
- {
- hide_login_progress( gc, "Authentication failure" );
- signoff( gc );
+ /* This happens when we just successfully authenticated the
+ old (non-SASL) way. */
+ jd->flags |= JFLAG_AUTHENTICATED;
+ if( !jabber_get_roster( gc ) )
return XT_ABORT;
- }
}
return XT_HANDLED;
}
-int jabber_start_iq_auth( struct gaim_connection *gc )
+xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
{
struct jabber_data *jd = gc->proto_data;
- struct xt_node *node;
- int st;
+ struct xt_node *c;
+ char *s;
- node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) );
- xt_add_attr( node, "xmlns", "jabber:iq:auth" );
- node = jabber_make_packet( "iq", "get", NULL, node );
+ if( ( c = xt_find_node( node->children, "bind" ) ) )
+ {
+ c = xt_find_node( c->children, "jid" );
+ if( c && c->text_len && ( s = strchr( c->text, '/' ) ) &&
+ strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 )
+ serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 );
+
+ jd->flags &= ~JFLAG_WAIT_BIND;
+ }
+ else
+ {
+ jd->flags &= ~JFLAG_WAIT_SESSION;
+ }
- st = jabber_write_packet( gc, node );
+ if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
+ {
+ if( !jabber_get_roster( gc ) )
+ return XT_ABORT;
+ }
- xt_free_node( node );
- return st;
+ return XT_HANDLED;
}
+static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig );
+
int jabber_get_roster( struct gaim_connection *gc )
{
struct xt_node *node;
@@ -193,12 +193,36 @@ int jabber_get_roster( struct gaim_connection *gc )
xt_add_attr( node, "xmlns", "jabber:iq:roster" );
node = jabber_make_packet( "iq", "get", NULL, node );
+ jabber_cache_add( gc, node, jabber_parse_roster );
st = jabber_write_packet( gc, node );
- xt_free_node( node );
return st;
}
+static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig )
+{
+ struct xt_node *query, *c;
+
+ query = xt_find_node( node->children, "query" );
+
+ c = query->children;
+ while( ( c = xt_find_node( c, "item" ) ) )
+ {
+ char *jid = xt_find_attr( c, "jid" );
+ char *name = xt_find_attr( c, "name" );
+ char *sub = xt_find_attr( c, "subscription" );
+
+ if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
+ add_buddy( gc, NULL, jid, name );
+
+ c = c->next;
+ }
+
+ account_online( gc );
+
+ return XT_HANDLED;
+}
+
int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name )
{
struct xt_node *node;