source: protocols/jabber/iq.c @ 8e6c732

Last change on this file since 8e6c732 was 8e6c732, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-09-26T13:12:11Z

Proper detection of resource changed strings from the server.

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[f06894d]1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  Jabber module - IQ packets                                               *
5*                                                                           *
6*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
7*                                                                           *
8*  This program is free software; you can redistribute it and/or modify     *
9*  it under the terms of the GNU General Public License as published by     *
10*  the Free Software Foundation; either version 2 of the License, or        *
11*  (at your option) any later version.                                      *
12*                                                                           *
13*  This program is distributed in the hope that it will be useful,          *
14*  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
15*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
16*  GNU General Public License for more details.                             *
17*                                                                           *
18*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24#include "jabber.h"
25
26xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )
27{
[21167d2]28        struct gaim_connection *gc = data;
29        struct jabber_data *jd = gc->proto_data;
[fe7a554]30        struct xt_node *query, *reply = NULL, *orig = NULL;
[70f6aab8]31        char *s, *type, *xmlns;
[21167d2]32        int st;
33       
34        query = xt_find_node( node->children, "query" );
[70f6aab8]35        type = xt_find_attr( node, "type" );
[f06894d]36       
[70f6aab8]37        if( !type )
[21167d2]38                return XT_HANDLED;      /* Ignore it for now, don't know what's best... */
39       
[70f6aab8]40        xmlns = xt_find_attr( query, "xmlns" );
41       
[fe7a554]42        if( ( s = xt_find_attr( node, "id" ) ) )
43                orig = jabber_packet_from_cache( gc, s );
44       
[70f6aab8]45        if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 )
[21167d2]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                       
[70f6aab8]81                        hide_login_progress( gc, "Can't find suitable authentication method" );
[21167d2]82                        signoff( gc );
83                        return XT_ABORT;
84                }
85               
86                reply = jabber_make_packet( "iq", "set", NULL, reply );
[fe7a554]87                jabber_cache_packet( gc, reply );
[21167d2]88                st = jabber_write_packet( gc, reply );
89               
90                return st ? XT_HANDLED : XT_ABORT;
91        }
[0b4a0db]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               
[5e202b0]109                account_online( gc );
[0b4a0db]110        }
[fe7a554]111        else if( strcmp( type, "result" ) == 0 && orig )
[70f6aab8]112        {
[8e6c732]113                struct xt_node *c;
[fe7a554]114               
115                if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
[8e6c732]116                    ( c = xt_find_node( orig->children, "query" ) ) &&
117                    ( c = xt_find_node( c->children, "username" ) ) &&
118                    c->text_len )
[70f6aab8]119                {
[fe7a554]120                        /* This happens when we just successfully authenticated
121                           the old (non-SASL) way. */
[70f6aab8]122                        jd->flags |= JFLAG_AUTHENTICATED;
123                        if( !jabber_get_roster( gc ) )
124                                return XT_ABORT;
125                }
[8e6c732]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" ) ) )
[fe7a554]132                {
[8e6c732]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                               
[fe7a554]140                                jd->flags &= ~JFLAG_WAIT_BIND;
[8e6c732]141                        }
142                        else if( strcmp( c->name, "session" ) == 0 )
[fe7a554]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                }
[70f6aab8]151        }
152        else if( strcmp( type, "error" ) == 0 )
153        {
154                if( !( jd->flags & JFLAG_AUTHENTICATED ) )
155                {
156                        hide_login_progress( gc, "Authentication failure" );
157                        signoff( gc );
158                        return XT_ABORT;
159                }
160        }
[f06894d]161       
162        return XT_HANDLED;
163}
164
[8d74291]165int jabber_start_iq_auth( struct gaim_connection *gc )
[21167d2]166{
167        struct jabber_data *jd = gc->proto_data;
168        struct xt_node *node;
169        int st;
170       
171        node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) );
172        xt_add_attr( node, "xmlns", "jabber:iq:auth" );
173        node = jabber_make_packet( "iq", "get", NULL, node );
174       
175        st = jabber_write_packet( gc, node );
176       
177        xt_free_node( node );
178        return st;
179}
[70f6aab8]180
181int jabber_get_roster( struct gaim_connection *gc )
182{
183        struct xt_node *node;
184        int st;
185       
186        set_login_progress( gc, 1, "Authenticated, requesting buddy list" );
187       
188        node = xt_new_node( "query", NULL, NULL );
189        xt_add_attr( node, "xmlns", "jabber:iq:roster" );
190        node = jabber_make_packet( "iq", "get", NULL, node );
191       
192        st = jabber_write_packet( gc, node );
193       
194        xt_free_node( node );
195        return st;
196}
[cfbb3a6]197
198int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name )
199{
200        struct xt_node *node;
201        int st;
202       
203        /* Build the item entry */
204        node = xt_new_node( "item", NULL, NULL );
205        xt_add_attr( node, "jid", handle );
206        if( name )
207                xt_add_attr( node, "name", name );
208       
209        /* And pack it into a roster-add packet */
210        node = xt_new_node( "query", NULL, node );
211        xt_add_attr( node, "xmlns", "jabber:iq:roster" );
212        node = jabber_make_packet( "iq", "set", NULL, node );
213       
214        st = jabber_write_packet( gc, node );
215       
216        xt_free_node( node );
217        return st;
218}
219
220int jabber_remove_from_roster( struct gaim_connection *gc, char *handle )
221{
222        struct xt_node *node;
223        int st;
224       
225        /* Build the item entry */
226        node = xt_new_node( "item", NULL, NULL );
227        xt_add_attr( node, "jid", handle );
228        xt_add_attr( node, "subscription", "remove" );
229       
230        /* And pack it into a roster-add packet */
231        node = xt_new_node( "query", NULL, node );
232        xt_add_attr( node, "xmlns", "jabber:iq:roster" );
233        node = jabber_make_packet( "iq", "set", NULL, node );
234       
235        st = jabber_write_packet( gc, node );
236       
237        xt_free_node( node );
238        return st;
239}
Note: See TracBrowser for help on using the repository browser.