Changeset 861c199 for protocols/jabber/iq.c
- Timestamp:
- 2006-10-08T18:41:11Z (16 years ago)
- Branches:
- master
- Children:
- 6a1128d
- Parents:
- 038d17f
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note: See TracChangeset
for help on using the changeset viewer.