Changeset 861c199 for protocols/jabber
- Timestamp:
- 2006-10-08T18:41:11Z (18 years ago)
- Branches:
- master
- Children:
- 6a1128d
- Parents:
- 038d17f
- Location:
- protocols/jabber
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/jabber/io.c
r038d17f r861c199 214 214 else 215 215 { 216 return jabber_ start_iq_auth( gc );216 return jabber_init_iq_auth( gc ); 217 217 } 218 218 } … … 351 351 else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( gc ) ) 352 352 { 353 if( !jabber_ start_iq_auth( gc ) )353 if( !jabber_init_iq_auth( gc ) ) 354 354 return XT_ABORT; 355 355 } … … 360 360 xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" ); 361 361 reply = jabber_make_packet( "iq", "set", NULL, reply ); 362 jabber_cache_add( gc, reply );362 jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); 363 363 364 364 if( !jabber_write_packet( gc, reply ) ) … … 373 373 xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" ); 374 374 reply = jabber_make_packet( "iq", "set", NULL, reply ); 375 jabber_cache_add( gc, reply );375 jabber_cache_add( gc, reply, jabber_pkt_bind_sess ); 376 376 377 377 if( !jabber_write_packet( gc, reply ) ) -
protocols/jabber/iq.c
r038d17f r861c199 28 28 struct gaim_connection *gc = data; 29 29 struct jabber_data *jd = gc->proto_data; 30 struct xt_node *query, *reply = NULL, *orig = NULL, *c; 31 char *s, *type, *xmlns; 32 int st; 33 34 query = xt_find_node( node->children, "query" ); 30 char *type, *s; 31 35 32 type = xt_find_attr( node, "type" ); 36 33 37 34 if( !type ) 38 return XT_HANDLED; /* Ignore it for now, don't know what's best... */ 39 40 xmlns = xt_find_attr( query, "xmlns" ); 41 42 if( ( s = xt_find_attr( node, "id" ) ) ) 43 orig = jabber_cache_get( gc, s ); 44 45 if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 ) 46 { 47 /* Time to authenticate ourselves! */ 48 reply = xt_new_node( "query", NULL, NULL ); 49 xt_add_attr( reply, "xmlns", "jabber:iq:auth" ); 50 xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); 51 xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); 52 53 if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) ) 54 { 55 /* We can do digest authentication, it seems, and of 56 course we prefer that. */ 57 SHA_CTX sha; 58 char hash_hex[40]; 59 unsigned char hash[20]; 60 int i; 61 62 shaInit( &sha ); 63 shaUpdate( &sha, (unsigned char*) s, strlen( s ) ); 64 shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) ); 65 shaFinal( &sha, hash ); 66 67 for( i = 0; i < 20; i ++ ) 68 sprintf( hash_hex + i * 2, "%02x", hash[i] ); 69 70 xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) ); 71 } 72 else if( xt_find_node( query->children, "password" ) ) 73 { 74 /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */ 75 xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) ); 76 } 77 else 78 { 79 xt_free_node( reply ); 80 81 hide_login_progress( gc, "Can't find suitable authentication method" ); 82 signoff( gc ); 83 return XT_ABORT; 84 } 85 86 reply = jabber_make_packet( "iq", "set", NULL, reply ); 87 jabber_cache_add( gc, reply ); 88 st = jabber_write_packet( gc, reply ); 89 90 return st ? XT_HANDLED : XT_ABORT; 91 } 92 if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:roster" ) == 0 ) 93 { 94 struct xt_node *node; 95 96 node = query->children; 97 while( ( node = xt_find_node( node, "item" ) ) ) 98 { 99 char *jid = xt_find_attr( node, "jid" ); 100 char *name = xt_find_attr( node, "name" ); 101 char *sub = xt_find_attr( node, "subscription" ); 102 103 if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) 104 add_buddy( gc, NULL, jid, name ); 105 106 node = node->next; 107 } 108 109 account_online( gc ); 110 } 111 else if( strcmp( type, "result" ) == 0 && orig ) 112 { 113 struct xt_node *c; 114 115 if( !( jd->flags & JFLAG_AUTHENTICATED ) && 116 ( c = xt_find_node( orig->children, "query" ) ) && 117 ( c = xt_find_node( c->children, "username" ) ) && 118 c->text_len ) 119 { 120 /* This happens when we just successfully authenticated 121 the old (non-SASL) way. */ 122 jd->flags |= JFLAG_AUTHENTICATED; 123 if( !jabber_get_roster( gc ) ) 124 return XT_ABORT; 125 } 126 /* Tricky: Look for <bind> in the reply, because the server 127 should confirm the chosen resource string there. For 128 <session>, however, look in the cache, because the server 129 will probably not include it in its reply. */ 130 else if( ( c = xt_find_node( node->children, "bind" ) ) || 131 ( c = xt_find_node( orig->children, "session" ) ) ) 132 { 133 if( strcmp( c->name, "bind" ) == 0 ) 134 { 135 c = xt_find_node( c->children, "jid" ); 136 if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && 137 strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 ) 138 serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 ); 139 140 jd->flags &= ~JFLAG_WAIT_BIND; 141 } 142 else if( strcmp( c->name, "session" ) == 0 ) 143 jd->flags &= ~JFLAG_WAIT_SESSION; 144 145 if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) 146 { 147 if( !jabber_get_roster( gc ) ) 148 return XT_ABORT; 149 } 150 } 151 } 152 else if( strcmp( type, "error" ) == 0 ) 153 { 154 if( !( jd->flags & JFLAG_AUTHENTICATED ) && 155 orig && 156 ( c = xt_find_node( orig->children, "query" ) ) && 157 ( c = xt_find_node( c->children, "username" ) ) && 158 c->text_len ) 159 { 160 hide_login_progress( gc, "Authentication failure" ); 161 signoff( gc ); 162 return XT_ABORT; 163 } 164 } 165 166 return XT_HANDLED; 167 } 168 169 int jabber_start_iq_auth( struct gaim_connection *gc ) 35 { 36 hide_login_progress_error( gc, "Received IQ packet without type!" ); 37 signoff( gc ); 38 return XT_ABORT; 39 } 40 41 if( ( s = xt_find_attr( node, "id" ) ) && 42 ( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) ) 43 { 44 struct jabber_cache_entry *entry; 45 46 entry = g_hash_table_lookup( jd->node_cache, s ); 47 48 if( entry == NULL ) 49 serv_got_crap( gc, "WARNING: Received IQ %s packet with unknown/expired ID %s!", type, s ); 50 else if( entry->func ) 51 return entry->func( gc, node, entry->node ); 52 } 53 54 return XT_HANDLED; 55 } 56 57 static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); 58 static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); 59 60 int jabber_init_iq_auth( struct gaim_connection *gc ) 170 61 { 171 62 struct jabber_data *jd = gc->proto_data; … … 177 68 node = jabber_make_packet( "iq", "get", NULL, node ); 178 69 179 st = jabber_write_packet( gc, node ); 180 181 xt_free_node( node ); 182 return st; 183 } 70 jabber_cache_add( gc, node, jabber_do_iq_auth ); 71 st = jabber_write_packet( gc, node ); 72 73 return st; 74 } 75 76 static xt_status jabber_do_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) 77 { 78 struct jabber_data *jd = gc->proto_data; 79 struct xt_node *reply, *query; 80 xt_status st; 81 char *s; 82 83 query = xt_find_node( node->children, "query" ); 84 85 /* Time to authenticate ourselves! */ 86 reply = xt_new_node( "query", NULL, NULL ); 87 xt_add_attr( reply, "xmlns", "jabber:iq:auth" ); 88 xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); 89 xt_add_child( reply, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) ); 90 91 if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) ) 92 { 93 /* We can do digest authentication, it seems, and of 94 course we prefer that. */ 95 SHA_CTX sha; 96 char hash_hex[40]; 97 unsigned char hash[20]; 98 int i; 99 100 shaInit( &sha ); 101 shaUpdate( &sha, (unsigned char*) s, strlen( s ) ); 102 shaUpdate( &sha, (unsigned char*) gc->acc->pass, strlen( gc->acc->pass ) ); 103 shaFinal( &sha, hash ); 104 105 for( i = 0; i < 20; i ++ ) 106 sprintf( hash_hex + i * 2, "%02x", hash[i] ); 107 108 xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) ); 109 } 110 else if( xt_find_node( query->children, "password" ) ) 111 { 112 /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */ 113 xt_add_child( reply, xt_new_node( "password", gc->acc->pass, NULL ) ); 114 } 115 else 116 { 117 xt_free_node( reply ); 118 119 hide_login_progress( gc, "Can't find suitable authentication method" ); 120 signoff( gc ); 121 return XT_ABORT; 122 } 123 124 reply = jabber_make_packet( "iq", "set", NULL, reply ); 125 jabber_cache_add( gc, reply, jabber_finish_iq_auth ); 126 st = jabber_write_packet( gc, reply ); 127 128 return st ? XT_HANDLED : XT_ABORT; 129 } 130 131 static xt_status jabber_finish_iq_auth( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) 132 { 133 char *type = xt_find_attr( node, "type" ); 134 struct jabber_data *jd = gc->proto_data; 135 136 if( strcmp( type, "error" ) == 0 ) 137 { 138 hide_login_progress( gc, "Authentication failure" ); 139 signoff( gc ); 140 return XT_ABORT; 141 } 142 else if( strcmp( type, "result" ) == 0 ) 143 { 144 /* This happens when we just successfully authenticated the 145 old (non-SASL) way. */ 146 jd->flags |= JFLAG_AUTHENTICATED; 147 if( !jabber_get_roster( gc ) ) 148 return XT_ABORT; 149 } 150 151 return XT_HANDLED; 152 } 153 154 xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) 155 { 156 struct jabber_data *jd = gc->proto_data; 157 struct xt_node *c; 158 char *s; 159 160 if( ( c = xt_find_node( node->children, "bind" ) ) ) 161 { 162 c = xt_find_node( c->children, "jid" ); 163 if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && 164 strcmp( s + 1, set_getstr( &gc->acc->set, "resource" ) ) != 0 ) 165 serv_got_crap( gc, "Server changed session resource string to `%s'", s + 1 ); 166 167 jd->flags &= ~JFLAG_WAIT_BIND; 168 } 169 else 170 { 171 jd->flags &= ~JFLAG_WAIT_SESSION; 172 } 173 174 if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 ) 175 { 176 if( !jabber_get_roster( gc ) ) 177 return XT_ABORT; 178 } 179 180 return XT_HANDLED; 181 } 182 183 static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); 184 184 185 185 int jabber_get_roster( struct gaim_connection *gc ) … … 194 194 node = jabber_make_packet( "iq", "get", NULL, node ); 195 195 196 st = jabber_write_packet( gc, node ); 197 198 xt_free_node( node ); 199 return st; 196 jabber_cache_add( gc, node, jabber_parse_roster ); 197 st = jabber_write_packet( gc, node ); 198 199 return st; 200 } 201 202 static xt_status jabber_parse_roster( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ) 203 { 204 struct xt_node *query, *c; 205 206 query = xt_find_node( node->children, "query" ); 207 208 c = query->children; 209 while( ( c = xt_find_node( c, "item" ) ) ) 210 { 211 char *jid = xt_find_attr( c, "jid" ); 212 char *name = xt_find_attr( c, "name" ); 213 char *sub = xt_find_attr( c, "subscription" ); 214 215 if( jid && sub && ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) 216 add_buddy( gc, NULL, jid, name ); 217 218 c = c->next; 219 } 220 221 account_online( gc ); 222 223 return XT_HANDLED; 200 224 } 201 225 -
protocols/jabber/jabber.c
r038d17f r861c199 174 174 xt_add_attr( node, "xmlns", "http://jabber.org/protocol/disco#info" ); 175 175 node = jabber_make_packet( "iq", "get", who, node ); 176 jabber_cache_add( gc, node);176 // jabber_cache_add( gc, node, ); 177 177 178 178 jabber_write_packet( gc, node ); -
protocols/jabber/jabber.h
r038d17f r861c199 69 69 }; 70 70 71 typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node * packet);71 typedef xt_status (*jabber_cache_event) ( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); 72 72 73 73 struct jabber_cache_entry … … 79 79 /* iq.c */ 80 80 xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); 81 int jabber_start_iq_auth( struct gaim_connection *gc ); 81 int jabber_init_iq_auth( struct gaim_connection *gc ); 82 xt_status jabber_pkt_bind_sess( struct gaim_connection *gc, struct xt_node *node, struct xt_node *orig ); 82 83 int jabber_get_roster( struct gaim_connection *gc ); 83 84 int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name ); … … 96 97 char *set_eval_tls( set_t *set, char *value ); 97 98 struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); 98 void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node );99 void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ); 99 100 struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id ); 100 101 void jabber_cache_entry_free( gpointer entry ); -
protocols/jabber/jabber_util.c
r038d17f r861c199 82 82 them when you receive the response. Use this BEFORE sending the packet so 83 83 it'll get an id= tag, and do NOT free() the packet after writing it! */ 84 void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node )84 void jabber_cache_add( struct gaim_connection *gc, struct xt_node *node, jabber_cache_event func ) 85 85 { 86 86 struct jabber_data *jd = gc->proto_data; … … 92 92 93 93 entry->node = node; 94 entry->func = func; 94 95 g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); 95 }96 97 struct xt_node *jabber_cache_get( struct gaim_connection *gc, char *id )98 {99 struct jabber_data *jd = gc->proto_data;100 struct jabber_cache_entry *entry = g_hash_table_lookup( jd->node_cache, id );101 102 return entry ? entry->node : NULL;103 96 } 104 97 … … 113 106 gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer ); 114 107 108 /* This one should be called from time to time (from keepalive, in this case) 109 to make sure things don't stay in the node cache forever. By marking nodes 110 during the first run and deleting marked nodes during a next run, every 111 node should be available in the cache for at least a minute (assuming the 112 function is indeed called every minute). */ 115 113 void jabber_cache_clean( struct gaim_connection *gc ) 116 114 {
Note: See TracChangeset
for help on using the changeset viewer.