1 | /***************************************************************************\ |
---|
2 | * * |
---|
3 | * BitlBee - An IRC to IM gateway * |
---|
4 | * Jabber module - SASL authentication * |
---|
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 | #include "base64.h" |
---|
26 | |
---|
27 | #define SASL_NS "urn:ietf:params:xml:ns:xmpp-sasl" |
---|
28 | |
---|
29 | xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) |
---|
30 | { |
---|
31 | struct gaim_connection *gc = data; |
---|
32 | struct jabber_data *jd = gc->proto_data; |
---|
33 | struct xt_node *c, *reply; |
---|
34 | char *s; |
---|
35 | int sup_plain = 0, sup_digest = 0; |
---|
36 | |
---|
37 | s = xt_find_attr( node, "xmlns" ); |
---|
38 | if( !s || strcmp( s, SASL_NS ) != 0 ) |
---|
39 | { |
---|
40 | signoff( gc ); |
---|
41 | return XT_ABORT; |
---|
42 | } |
---|
43 | |
---|
44 | c = node->children; |
---|
45 | while( ( c = xt_find_node( c, "mechanism" ) ) ) |
---|
46 | { |
---|
47 | if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 ) |
---|
48 | sup_plain = 1; |
---|
49 | if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 ) |
---|
50 | sup_digest = 1; |
---|
51 | |
---|
52 | c = c->next; |
---|
53 | } |
---|
54 | |
---|
55 | if( !sup_plain && !sup_digest ) |
---|
56 | { |
---|
57 | signoff( gc ); |
---|
58 | return XT_ABORT; |
---|
59 | } |
---|
60 | |
---|
61 | reply = xt_new_node( "auth", NULL, NULL ); |
---|
62 | xt_add_attr( reply, "xmlns", SASL_NS ); |
---|
63 | |
---|
64 | if( sup_plain ) |
---|
65 | { |
---|
66 | int len; |
---|
67 | |
---|
68 | xt_add_attr( reply, "mechanism", "PLAIN" ); |
---|
69 | |
---|
70 | /* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */ |
---|
71 | len = strlen( jd->username ) + strlen( gc->acc->pass ) + 2; |
---|
72 | s = g_malloc( len + 1 ); |
---|
73 | s[0] = 0; |
---|
74 | strcpy( s + 1, jd->username ); |
---|
75 | strcpy( s + 2 + strlen( jd->username ), gc->acc->pass ); |
---|
76 | reply->text = base64_encode( s, len ); |
---|
77 | reply->text_len = strlen( reply->text ); |
---|
78 | g_free( s ); |
---|
79 | } |
---|
80 | |
---|
81 | if( !jabber_write_packet( gc, reply ) ) |
---|
82 | { |
---|
83 | xt_free_node( reply ); |
---|
84 | return XT_ABORT; |
---|
85 | } |
---|
86 | xt_free_node( reply ); |
---|
87 | |
---|
88 | /* To prevent classic authentication from happening. */ |
---|
89 | jd->flags |= JFLAG_STREAM_STARTED; |
---|
90 | |
---|
91 | return XT_HANDLED; |
---|
92 | } |
---|
93 | |
---|
94 | xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) |
---|
95 | { |
---|
96 | } |
---|
97 | |
---|
98 | xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) |
---|
99 | { |
---|
100 | struct gaim_connection *gc = data; |
---|
101 | struct jabber_data *jd = gc->proto_data; |
---|
102 | char *s; |
---|
103 | |
---|
104 | s = xt_find_attr( node, "xmlns" ); |
---|
105 | if( !s || strcmp( s, SASL_NS ) != 0 ) |
---|
106 | { |
---|
107 | signoff( gc ); |
---|
108 | return XT_ABORT; |
---|
109 | } |
---|
110 | |
---|
111 | if( strcmp( node->name, "success" ) == 0 ) |
---|
112 | { |
---|
113 | set_login_progress( gc, 1, "Authentication finished" ); |
---|
114 | jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; |
---|
115 | } |
---|
116 | else if( strcmp( node->name, "failure" ) == 0 ) |
---|
117 | { |
---|
118 | hide_login_progress( gc, "Authentication failure" ); |
---|
119 | signoff( gc ); |
---|
120 | return XT_ABORT; |
---|
121 | } |
---|
122 | |
---|
123 | return XT_HANDLED; |
---|
124 | } |
---|