source: protocols/jabber/iq.c @ fe7a554

Last change on this file since fe7a554 was fe7a554, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-09-22T18:39:31Z

Better detection of successful IQ authentication (using packet caching),
properly working SASL authentication (although only PLAIN so far).

  • Property mode set to 100644
File size: 6.2 KB
Line 
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{
28        struct gaim_connection *gc = data;
29        struct jabber_data *jd = gc->proto_data;
30        struct xt_node *query, *reply = NULL, *orig = NULL;
31        char *s, *type, *xmlns;
32        int st;
33       
34        query = xt_find_node( node->children, "query" );
35        type = xt_find_attr( node, "type" );
36       
37        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_packet_from_cache( 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_packet( 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                presence_announce( gc );
110        }
111        else if( strcmp( type, "result" ) == 0 && orig )
112        {
113                struct xt_node *node;
114               
115                if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
116                    ( node = xt_find_node( orig->children, "query" ) ) &&
117                    ( node = xt_find_node( node->children, "username" ) ) &&
118                    node->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                else if( ( node = xt_find_node( orig->children, "bind" ) ) ||
127                         ( node = xt_find_node( orig->children, "session" ) ) )
128                {
129                        if( strcmp( node->name, "bind" ) == 0 )
130                                jd->flags &= ~JFLAG_WAIT_BIND;
131                        else if( strcmp( node->name, "session" ) == 0 )
132                                jd->flags &= ~JFLAG_WAIT_SESSION;
133                       
134                        if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
135                        {
136                                if( !jabber_get_roster( gc ) )
137                                        return XT_ABORT;
138                        }
139                }
140        }
141        else if( strcmp( type, "error" ) == 0 )
142        {
143                if( !( jd->flags & JFLAG_AUTHENTICATED ) )
144                {
145                        hide_login_progress( gc, "Authentication failure" );
146                        signoff( gc );
147                        return XT_ABORT;
148                }
149        }
150       
151        return XT_HANDLED;
152}
153
154int jabber_start_iq_auth( struct gaim_connection *gc )
155{
156        struct jabber_data *jd = gc->proto_data;
157        struct xt_node *node;
158        int st;
159       
160        node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) );
161        xt_add_attr( node, "xmlns", "jabber:iq:auth" );
162        node = jabber_make_packet( "iq", "get", NULL, node );
163       
164        st = jabber_write_packet( gc, node );
165       
166        xt_free_node( node );
167        return st;
168}
169
170int jabber_get_roster( struct gaim_connection *gc )
171{
172        struct xt_node *node;
173        int st;
174       
175        set_login_progress( gc, 1, "Authenticated, requesting buddy list" );
176       
177        node = xt_new_node( "query", NULL, NULL );
178        xt_add_attr( node, "xmlns", "jabber:iq:roster" );
179        node = jabber_make_packet( "iq", "get", NULL, node );
180       
181        st = jabber_write_packet( gc, node );
182       
183        xt_free_node( node );
184        return st;
185}
Note: See TracBrowser for help on using the repository browser.