| 50 } |
54 } |
| 51 |
55 |
| 52 return FALSE; |
56 return FALSE; |
| 53 } |
57 } |
| 54 |
58 |
| |
59 static void finish_plaintext_authentication(JabberStream *js) |
| |
60 { |
| |
61 if(js->auth_type == JABBER_AUTH_PLAIN) { |
| |
62 xmlnode *auth; |
| |
63 GString *response; |
| |
64 char *enc_out; |
| |
65 |
| |
66 auth = xmlnode_new("auth"); |
| |
67 xmlnode_set_attrib(auth, "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); |
| |
68 |
| |
69 response = g_string_new(""); |
| |
70 response = g_string_append_len(response, "\0", 1); |
| |
71 response = g_string_append(response, js->user->node); |
| |
72 response = g_string_append_len(response, "\0", 1); |
| |
73 response = g_string_append(response, |
| |
74 gaim_account_get_password(js->gc->account)); |
| |
75 |
| |
76 enc_out = gaim_base64_encode(response->str, response->len); |
| |
77 |
| |
78 xmlnode_set_attrib(auth, "mechanism", "PLAIN"); |
| |
79 xmlnode_insert_data(auth, enc_out, -1); |
| |
80 g_free(enc_out); |
| |
81 g_string_free(response, TRUE); |
| |
82 |
| |
83 jabber_send(js, auth); |
| |
84 xmlnode_free(auth); |
| |
85 } else if(js->auth_type == JABBER_AUTH_IQ_AUTH) { |
| |
86 JabberIq *iq; |
| |
87 xmlnode *query, *x; |
| |
88 |
| |
89 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); |
| |
90 query = xmlnode_get_child(iq->node, "query"); |
| |
91 x = xmlnode_new_child(query, "username"); |
| |
92 xmlnode_insert_data(x, js->user->node, -1); |
| |
93 x = xmlnode_new_child(query, "resource"); |
| |
94 xmlnode_insert_data(x, js->user->resource, -1); |
| |
95 x = xmlnode_new_child(query, "password"); |
| |
96 xmlnode_insert_data(x, gaim_account_get_password(js->gc->account), -1); |
| |
97 jabber_iq_set_callback(iq, auth_old_result_cb, NULL); |
| |
98 jabber_iq_send(iq); |
| |
99 } |
| |
100 } |
| |
101 |
| |
102 static void allow_plaintext_auth(GaimAccount *account) |
| |
103 { |
| |
104 gaim_account_set_bool(account, "auth_plain_in_clear", TRUE); |
| |
105 |
| |
106 finish_plaintext_authentication(account->gc->proto_data); |
| |
107 } |
| |
108 |
| |
109 static void disallow_plaintext_auth(GaimAccount *account) |
| |
110 { |
| |
111 gaim_connection_error(account->gc, _("Server requires plaintext authentication over an unencrypted stream")); |
| |
112 } |
| |
113 |
| 55 void |
114 void |
| 56 jabber_auth_start(JabberStream *js, xmlnode *packet) |
115 jabber_auth_start(JabberStream *js, xmlnode *packet) |
| 57 { |
116 { |
| 58 xmlnode *mechs, *mechnode; |
117 xmlnode *mechs, *mechnode; |
| 59 xmlnode *auth; |
|
| 60 |
118 |
| 61 gboolean digest_md5 = FALSE, plain=FALSE; |
119 gboolean digest_md5 = FALSE, plain=FALSE; |
| 62 |
120 |
| 63 |
121 |
| 64 if(js->registration) { |
122 if(js->registration) { |
| 82 else if(mech_name && !strcmp(mech_name, "PLAIN")) |
140 else if(mech_name && !strcmp(mech_name, "PLAIN")) |
| 83 plain = TRUE; |
141 plain = TRUE; |
| 84 g_free(mech_name); |
142 g_free(mech_name); |
| 85 } |
143 } |
| 86 |
144 |
| 87 auth = xmlnode_new("auth"); |
|
| 88 xmlnode_set_attrib(auth, "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); |
|
| 89 |
145 |
| 90 if(digest_md5) { |
146 if(digest_md5) { |
| |
147 xmlnode *auth; |
| |
148 |
| |
149 js->auth_type = JABBER_AUTH_DIGEST_MD5; |
| |
150 auth = xmlnode_new("auth"); |
| |
151 xmlnode_set_attrib(auth, "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); |
| 91 xmlnode_set_attrib(auth, "mechanism", "DIGEST-MD5"); |
152 xmlnode_set_attrib(auth, "mechanism", "DIGEST-MD5"); |
| 92 js->auth_type = JABBER_AUTH_DIGEST_MD5; |
153 |
| |
154 jabber_send(js, auth); |
| |
155 xmlnode_free(auth); |
| 93 } else if(plain) { |
156 } else if(plain) { |
| 94 GString *response; |
157 js->auth_type = JABBER_AUTH_PLAIN; |
| 95 char *enc_out; |
|
| 96 |
158 |
| 97 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) { |
159 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) { |
| 98 /* XXX: later, make this yes/no so they can just click to enable it */ |
160 gaim_request_yes_no(js->gc, _("Plaintext Authentication"), |
| 99 gaim_connection_error(js->gc, |
161 _("Plaintext Authentication"), |
| 100 _("Server requires plaintext authentication over an unencrypted stream")); |
162 _("This server requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), |
| 101 xmlnode_free(auth); |
163 2, js->gc->account, allow_plaintext_auth, |
| |
164 disallow_plaintext_auth); |
| 102 return; |
165 return; |
| 103 } |
166 } |
| 104 |
167 finish_plaintext_authentication(js); |
| 105 response = g_string_new(""); |
|
| 106 response = g_string_append_len(response, "\0", 1); |
|
| 107 response = g_string_append(response, js->user->node); |
|
| 108 response = g_string_append_len(response, "\0", 1); |
|
| 109 response = g_string_append(response, |
|
| 110 gaim_account_get_password(js->gc->account)); |
|
| 111 |
|
| 112 enc_out = gaim_base64_encode(response->str, response->len); |
|
| 113 |
|
| 114 xmlnode_set_attrib(auth, "mechanism", "PLAIN"); |
|
| 115 xmlnode_insert_data(auth, enc_out, -1); |
|
| 116 g_free(enc_out); |
|
| 117 g_string_free(response, TRUE); |
|
| 118 |
|
| 119 js->auth_type = JABBER_AUTH_PLAIN; |
|
| 120 } else { |
168 } else { |
| 121 gaim_connection_error(js->gc, |
169 gaim_connection_error(js->gc, |
| 122 _("Server does not use any supported authentication method")); |
170 _("Server does not use any supported authentication method")); |
| 123 xmlnode_free(auth); |
171 } |
| 124 return; |
|
| 125 } |
|
| 126 |
|
| 127 jabber_send(js, auth); |
|
| 128 xmlnode_free(auth); |
|
| 129 } |
172 } |
| 130 |
173 |
| 131 static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data) |
174 static void auth_old_result_cb(JabberStream *js, xmlnode *packet, gpointer data) |
| 132 { |
175 { |
| 133 const char *type = xmlnode_get_attrib(packet, "type"); |
176 const char *type = xmlnode_get_attrib(packet, "type"); |
| 189 g_free(err_txt); |
231 g_free(err_txt); |
| 190 g_free(buf); |
232 g_free(buf); |
| 191 } else if(!strcmp(type, "result")) { |
233 } else if(!strcmp(type, "result")) { |
| 192 query = xmlnode_get_child(packet, "query"); |
234 query = xmlnode_get_child(packet, "query"); |
| 193 if(js->stream_id && xmlnode_get_child(query, "digest")) { |
235 if(js->stream_id && xmlnode_get_child(query, "digest")) { |
| 194 digest = TRUE; |
|
| 195 } else if(xmlnode_get_child(query, "password")) { |
|
| 196 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account, |
|
| 197 "auth_plain_in_clear", FALSE)) { |
|
| 198 /* XXX: later, make this yes/no so they can just click to enable it */ |
|
| 199 gaim_connection_error(js->gc, |
|
| 200 _("Server requires plaintext authentication over an unencrypted stream")); |
|
| 201 return; |
|
| 202 } |
|
| 203 } else { |
|
| 204 gaim_connection_error(js->gc, |
|
| 205 _("Server does not use any supported authentication method")); |
|
| 206 return; |
|
| 207 } |
|
| 208 |
|
| 209 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); |
|
| 210 query = xmlnode_get_child(iq->node, "query"); |
|
| 211 x = xmlnode_new_child(query, "username"); |
|
| 212 xmlnode_insert_data(x, js->user->node, -1); |
|
| 213 x = xmlnode_new_child(query, "resource"); |
|
| 214 xmlnode_insert_data(x, js->user->resource, -1); |
|
| 215 |
|
| 216 if(digest) { |
|
| 217 unsigned char hashval[20]; |
236 unsigned char hashval[20]; |
| 218 char *s, h[41], *p; |
237 char *s, h[41], *p; |
| 219 int i; |
238 int i; |
| |
239 |
| |
240 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); |
| |
241 query = xmlnode_get_child(iq->node, "query"); |
| |
242 x = xmlnode_new_child(query, "username"); |
| |
243 xmlnode_insert_data(x, js->user->node, -1); |
| |
244 x = xmlnode_new_child(query, "resource"); |
| |
245 xmlnode_insert_data(x, js->user->resource, -1); |
| 220 |
246 |
| 221 x = xmlnode_new_child(query, "digest"); |
247 x = xmlnode_new_child(query, "digest"); |
| 222 s = g_strdup_printf("%s%s", js->stream_id, pw); |
248 s = g_strdup_printf("%s%s", js->stream_id, pw); |
| 223 shaBlock((unsigned char *)s, strlen(s), hashval); |
249 shaBlock((unsigned char *)s, strlen(s), hashval); |
| 224 p = h; |
250 p = h; |
| 225 for(i=0; i<20; i++, p+=2) |
251 for(i=0; i<20; i++, p+=2) |
| 226 snprintf(p, 3, "%02x", hashval[i]); |
252 snprintf(p, 3, "%02x", hashval[i]); |
| 227 xmlnode_insert_data(x, h, -1); |
253 xmlnode_insert_data(x, h, -1); |
| 228 g_free(s); |
254 g_free(s); |
| |
255 jabber_iq_set_callback(iq, auth_old_result_cb, NULL); |
| |
256 jabber_iq_send(iq); |
| |
257 |
| |
258 } else if(xmlnode_get_child(query, "password")) { |
| |
259 if(js->gsc == NULL && !gaim_account_get_bool(js->gc->account, |
| |
260 "auth_plain_in_clear", FALSE)) { |
| |
261 gaim_request_yes_no(js->gc, _("Plaintext Authentication"), |
| |
262 _("Plaintext Authentication"), |
| |
263 _("This server requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), |
| |
264 2, js->gc->account, allow_plaintext_auth, |
| |
265 disallow_plaintext_auth); |
| |
266 return; |
| |
267 } |
| |
268 finish_plaintext_authentication(js); |
| 229 } else { |
269 } else { |
| 230 x = xmlnode_new_child(query, "password"); |
270 gaim_connection_error(js->gc, |
| 231 xmlnode_insert_data(x, pw, -1); |
271 _("Server does not use any supported authentication method")); |
| 232 } |
272 return; |
| 233 |
273 } |
| 234 jabber_iq_set_callback(iq, auth_old_result_cb, NULL); |
|
| 235 |
|
| 236 jabber_iq_send(iq); |
|
| 237 } |
274 } |
| 238 } |
275 } |
| 239 |
276 |
| 240 void jabber_auth_start_old(JabberStream *js) |
277 void jabber_auth_start_old(JabberStream *js) |
| 241 { |
278 { |