comparison src/protocols/jabber/auth.c @ 7291:632cee95cc5c

[gaim-migrate @ 7872] disable jabber SASL for the moment, until the RFCs are actually approved, since the authentication stuff is still in a state of flux committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Fri, 17 Oct 2003 20:03:44 +0000
parents 109817b028a6
children b250288fa948
comparison
equal deleted inserted replaced
7290:2267f71cb47b 7291:632cee95cc5c
36 void 36 void
37 jabber_auth_start(JabberStream *js, xmlnode *packet) 37 jabber_auth_start(JabberStream *js, xmlnode *packet)
38 { 38 {
39 xmlnode *mechs, *mechnode; 39 xmlnode *mechs, *mechnode;
40 xmlnode *starttls; 40 xmlnode *starttls;
41 41 xmlnode *auth;
42 gboolean digest_md5 = FALSE; 42
43 gboolean digest_md5 = FALSE, plain=FALSE;
43 44
44 if((starttls = xmlnode_get_child(packet, "starttls"))) { 45 if((starttls = xmlnode_get_child(packet, "starttls"))) {
45 if(gaim_ssl_is_supported()) { 46 if(gaim_ssl_is_supported()) {
46 jabber_send_raw(js, 47 jabber_send_raw(js,
47 "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); 48 "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
63 { 64 {
64 if(mechnode->type == NODE_TYPE_TAG) { 65 if(mechnode->type == NODE_TYPE_TAG) {
65 char *mech_name = xmlnode_get_data(mechnode); 66 char *mech_name = xmlnode_get_data(mechnode);
66 if(mech_name && !strcmp(mech_name, "DIGEST-MD5")) 67 if(mech_name && !strcmp(mech_name, "DIGEST-MD5"))
67 digest_md5 = TRUE; 68 digest_md5 = TRUE;
69 else if(mech_name && !strcmp(mech_name, "PLAIN"))
70 plain = TRUE;
68 g_free(mech_name); 71 g_free(mech_name);
69 } 72 }
70 } 73 }
71 74
75 auth = xmlnode_new("auth");
76 xmlnode_set_attrib(auth, "xmlns", "urn:ietf:params:xml:ns:xmpp-sasl");
72 if(digest_md5) { 77 if(digest_md5) {
73 jabber_send_raw(js, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl'" 78 xmlnode_set_attrib(auth, "mechanism", "DIGEST-MD5");
74 " mechanism='DIGEST-MD5' />"); 79 js->auth_type = JABBER_AUTH_DIGEST_MD5;
80 /*
81 } else if(plain) {
82 js->auth_type = JABBER_AUTH_PLAIN;
83 */
75 } else { 84 } else {
76 gaim_connection_error(js->gc, 85 gaim_connection_error(js->gc,
77 _("Server does not use any supported authentication method")); 86 _("Server does not use any supported authentication method"));
78 } 87 xmlnode_free(auth);
88 return;
89 }
90 jabber_send(js, auth);
91 xmlnode_free(auth);
79 } 92 }
80 93
81 static void auth_old_result_cb(JabberStream *js, xmlnode *packet) 94 static void auth_old_result_cb(JabberStream *js, xmlnode *packet)
82 { 95 {
83 const char *type = xmlnode_get_attrib(packet, "type"); 96 const char *type = xmlnode_get_attrib(packet, "type");
246 } 259 }
247 260
248 void 261 void
249 jabber_auth_handle_challenge(JabberStream *js, xmlnode *packet) 262 jabber_auth_handle_challenge(JabberStream *js, xmlnode *packet)
250 { 263 {
251 char *enc_in = xmlnode_get_data(packet); 264
252 char *dec_in; 265 if(js->auth_type == JABBER_AUTH_PLAIN) {
253 char *enc_out; 266 /* XXX: implement me! */
254 GHashTable *parts; 267 } else if(js->auth_type == JABBER_AUTH_DIGEST_MD5) {
255 268 char *enc_in = xmlnode_get_data(packet);
256 gaim_base64_decode(enc_in, &dec_in, NULL); 269 char *dec_in;
257 270 char *enc_out;
258 parts = parse_challenge(dec_in); 271 GHashTable *parts;
259 272
260 /* we're actually supposed to prompt the user for a realm if 273 gaim_base64_decode(enc_in, &dec_in, NULL);
261 * the server doesn't send one, but that really complicates things, 274
262 * so i'm not gonna worry about it until is poses a problem to someone, 275 parts = parse_challenge(dec_in);
263 * or I get really bored */ 276
264 277
265 if(g_hash_table_lookup(parts, "realm")) { 278 if (g_hash_table_lookup(parts, "rspauth")) {
266 /* assemble a response, and send it */ 279 char *rspauth = g_hash_table_lookup(parts, "rspauth");
267 /* see RFC 2831 */ 280
268 GString *response = g_string_new(""); 281
269 char *a2; 282 if(rspauth && js->expected_rspauth &&
270 char *auth_resp; 283 !strcmp(rspauth, js->expected_rspauth)) {
271 char *buf; 284 jabber_send_raw(js,
272 char *cnonce; 285 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />");
273 char *realm; 286 } else {
274 char *nonce; 287 gaim_connection_error(js->gc, _("Invalid challenge from server"));
275 288 }
276 cnonce = g_strdup_printf("%x%u%x", g_random_int(), (int)time(NULL), 289 g_free(js->expected_rspauth);
277 g_random_int());
278 nonce = g_hash_table_lookup(parts, "nonce");
279 realm = g_hash_table_lookup(parts, "realm");
280
281 a2 = g_strdup_printf("AUTHENTICATE:xmpp/%s", realm);
282 auth_resp = generate_response_value(js->user,
283 gaim_account_get_password(js->gc->account), nonce, cnonce, a2, realm);
284 g_free(a2);
285
286 a2 = g_strdup_printf(":xmpp/%s", realm);
287 js->expected_rspauth = generate_response_value(js->user,
288 gaim_account_get_password(js->gc->account), nonce, cnonce, a2, realm);
289 g_free(a2);
290
291
292 g_string_append_printf(response, "username=\"%s\"", js->user->node);
293 g_string_append_printf(response, ",realm=\"%s\"", realm);
294 g_string_append_printf(response, ",nonce=\"%s\"", nonce);
295 g_string_append_printf(response, ",cnonce=\"%s\"", cnonce);
296 g_string_append_printf(response, ",nc=00000001");
297 g_string_append_printf(response, ",qop=auth");
298 g_string_append_printf(response, ",digest-uri=\"xmpp/%s\"", realm);
299 g_string_append_printf(response, ",response=%s", auth_resp);
300 g_string_append_printf(response, ",charset=utf-8");
301 g_string_append_printf(response, ",authzid=\"%s@%s/%s\"",
302 js->user->node, js->user->domain, js->user->resource);
303
304 g_free(auth_resp);
305 g_free(cnonce);
306
307 enc_out = gaim_base64_encode(response->str, response->len);
308
309 gaim_debug(GAIM_DEBUG_MISC, "jabber", "decoded response (%d): %s\n", response->len, response->str);
310
311 buf = g_strdup_printf("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</response>", enc_out);
312
313 jabber_send_raw(js, buf);
314
315 g_free(buf);
316
317 g_free(enc_out);
318
319 g_string_free(response, TRUE);
320 } else if (g_hash_table_lookup(parts, "rspauth")) {
321 char *rspauth = g_hash_table_lookup(parts, "rspauth");
322
323
324 if(rspauth && !strcmp(rspauth, js->expected_rspauth)) {
325 jabber_send_raw(js,
326 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />");
327 } else { 290 } else {
328 gaim_connection_error(js->gc, _("Invalid challenge from server")); 291 /* assemble a response, and send it */
292 /* see RFC 2831 */
293 GString *response = g_string_new("");
294 char *a2;
295 char *auth_resp;
296 char *buf;
297 char *cnonce;
298 char *realm;
299 char *nonce;
300
301 /* we're actually supposed to prompt the user for a realm if
302 * the server doesn't send one, but that really complicates things,
303 * so i'm not gonna worry about it until is poses a problem to
304 * someone, or I get really bored */
305 realm = g_hash_table_lookup(parts, "realm");
306 if(!realm)
307 realm = js->user->domain;
308
309 cnonce = g_strdup_printf("%x%u%x", g_random_int(), (int)time(NULL),
310 g_random_int());
311 nonce = g_hash_table_lookup(parts, "nonce");
312
313
314 a2 = g_strdup_printf("AUTHENTICATE:xmpp/%s", realm);
315 auth_resp = generate_response_value(js->user,
316 gaim_account_get_password(js->gc->account), nonce, cnonce, a2, realm);
317 g_free(a2);
318
319 a2 = g_strdup_printf(":xmpp/%s", realm);
320 js->expected_rspauth = generate_response_value(js->user,
321 gaim_account_get_password(js->gc->account), nonce, cnonce, a2, realm);
322 g_free(a2);
323
324
325 g_string_append_printf(response, "username=\"%s\"", js->user->node);
326 g_string_append_printf(response, ",realm=\"%s\"", realm);
327 g_string_append_printf(response, ",nonce=\"%s\"", nonce);
328 g_string_append_printf(response, ",cnonce=\"%s\"", cnonce);
329 g_string_append_printf(response, ",nc=00000001");
330 g_string_append_printf(response, ",qop=auth");
331 g_string_append_printf(response, ",digest-uri=\"xmpp/%s\"", realm);
332 g_string_append_printf(response, ",response=%s", auth_resp);
333 g_string_append_printf(response, ",charset=utf-8");
334 g_string_append_printf(response, ",authzid=\"%s@%s/%s\"",
335 js->user->node, js->user->domain, js->user->resource);
336
337 g_free(auth_resp);
338 g_free(cnonce);
339
340 enc_out = gaim_base64_encode(response->str, response->len);
341
342 gaim_debug(GAIM_DEBUG_MISC, "jabber", "decoded response (%d): %s\n", response->len, response->str);
343
344 buf = g_strdup_printf("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</response>", enc_out);
345
346 jabber_send_raw(js, buf);
347
348 g_free(buf);
349
350 g_free(enc_out);
351
352 g_string_free(response, TRUE);
329 } 353 }
330 g_free(js->expected_rspauth); 354
331 } 355 g_free(enc_in);
332 356 g_free(dec_in);
333 g_free(enc_in); 357 g_hash_table_destroy(parts);
334 g_free(dec_in); 358 }
335 g_hash_table_destroy(parts);
336 } 359 }
337 360
338 void jabber_auth_handle_success(JabberStream *js, xmlnode *packet) 361 void jabber_auth_handle_success(JabberStream *js, xmlnode *packet)
339 { 362 {
340 const char *ns = xmlnode_get_attrib(packet, "xmlns"); 363 const char *ns = xmlnode_get_attrib(packet, "xmlns");