| 224 goto err; |
224 goto err; |
| 225 |
225 |
| 226 /* Ensure that the first cnonce_len bytes of the nonce are the original |
226 /* Ensure that the first cnonce_len bytes of the nonce are the original |
| 227 * cnonce we sent to the server. |
227 * cnonce we sent to the server. |
| 228 */ |
228 */ |
| 229 if (!g_str_equal(data->cnonce, token + 2)) |
229 if (0 != strncmp(data->cnonce, token + 2, strlen(data->cnonce))) |
| 230 goto err; |
230 goto err; |
| 231 |
231 |
| 232 nonce = g_strdup(token + 2); |
232 nonce = g_strdup(token + 2); |
| 233 |
233 |
| 234 /* The Salt, base64-encoded */ |
234 /* The Salt, base64-encoded */ |
| 309 if (!ret) |
310 if (!ret) |
| 310 return FALSE; |
311 return FALSE; |
| 311 |
312 |
| 312 g_string_append_c(data->auth_message, ','); |
313 g_string_append_c(data->auth_message, ','); |
| 313 |
314 |
| 314 /* "biwsCg==" is the base64 encoding of "n,,". I promise. */ |
315 /* "biws" is the base64 encoding of "n,,". I promise. */ |
| 315 g_string_append_printf(data->auth_message, "c=%s,r=%s", "biwsCg==", nonce); |
316 g_string_append_printf(data->auth_message, "c=%s,r=%s", "biws", nonce); |
| 316 #ifdef CHANNEL_BINDING |
317 #ifdef CHANNEL_BINDING |
| 317 #error fix this |
318 #error fix this |
| 318 #endif |
319 #endif |
| 319 |
320 |
| 320 ret = jabber_scram_calc_proofs(data, salt, iterations); |
321 ret = jabber_scram_calc_proofs(data, salt, iterations); |
| 321 if (!ret) |
322 if (!ret) |
| 322 return FALSE; |
323 return FALSE; |
| 323 |
324 |
| 324 proof = purple_base64_encode((guchar *)data->client_proof->str, data->client_proof->len); |
325 proof = purple_base64_encode((guchar *)data->client_proof->str, data->client_proof->len); |
| 325 *out = g_strdup_printf("c=%s,r=%s,p=%s", "biwsCg==", nonce, proof); |
326 *out = g_strdup_printf("c=%s,r=%s,p=%s", "biws", nonce, proof); |
| 326 g_free(proof); |
327 g_free(proof); |
| 327 } else if (data->step == 2) { |
328 } else if (data->step == 2) { |
| 328 gchar *server_sig, *enc_server_sig; |
329 gchar *server_sig, *enc_server_sig; |
| 329 gsize len; |
330 gsize len; |
| 330 |
331 |
| 426 goto out; |
427 goto out; |
| 427 } |
428 } |
| 428 |
429 |
| 429 purple_debug_misc("jabber", "decoded challenge: %s\n", dec_in); |
430 purple_debug_misc("jabber", "decoded challenge: %s\n", dec_in); |
| 430 |
431 |
| 431 if (!feed_parser(data, dec_in, &dec_out)) { |
432 if (!jabber_scram_feed_parser(data, dec_in, &dec_out)) { |
| 432 reply = xmlnode_new("abort"); |
433 reply = xmlnode_new("abort"); |
| 433 xmlnode_set_namespace(reply, "urn:ietf:params:xml:ns:xmpp-sasl"); |
434 xmlnode_set_namespace(reply, "urn:ietf:params:xml:ns:xmpp-sasl"); |
| 434 data->step = -1; |
435 data->step = -1; |
| 435 goto out; |
436 goto out; |
| 436 } |
437 } |
| 477 return FALSE; |
478 return FALSE; |
| 478 } |
479 } |
| 479 |
480 |
| 480 purple_debug_misc("jabber", "decoded success: %s\n", dec_in); |
481 purple_debug_misc("jabber", "decoded success: %s\n", dec_in); |
| 481 |
482 |
| 482 if (!feed_parser(data, dec_in, &dec_out) || dec_out != NULL) { |
483 if (!jabber_scram_feed_parser(data, dec_in, &dec_out) || dec_out != NULL) { |
| 483 g_free(dec_out); |
484 g_free(dec_out); |
| 484 return FALSE; |
485 return FALSE; |
| 485 } |
486 } |
| 486 |
487 |
| 487 /* Hooray */ |
488 /* Hooray */ |
| 488 return TRUE; |
489 return TRUE; |
| 489 } |
490 } |
| 490 |
491 |
| |
492 void jabber_scram_data_destroy(JabberScramData *data) |
| |
493 { |
| |
494 g_free(data->cnonce); |
| |
495 if (data->auth_message) |
| |
496 g_string_free(data->auth_message, TRUE); |
| |
497 if (data->client_proof) |
| |
498 g_string_free(data->client_proof, TRUE); |
| |
499 if (data->server_signature) |
| |
500 g_string_free(data->server_signature, TRUE); |
| |
501 g_free(data); |
| |
502 } |
| |
503 |
| 491 static void scram_dispose(JabberStream *js) |
504 static void scram_dispose(JabberStream *js) |
| 492 { |
505 { |
| 493 if (js->auth_mech_data) { |
506 if (js->auth_mech_data) { |
| 494 JabberScramData *data = js->auth_mech_data; |
507 jabber_scram_data_destroy(js->auth_mech_data); |
| 495 |
|
| 496 g_free(data->cnonce); |
|
| 497 if (data->auth_message) |
|
| 498 g_string_free(data->auth_message, TRUE); |
|
| 499 if (data->client_proof) |
|
| 500 g_string_free(data->client_proof, TRUE); |
|
| 501 if (data->server_signature) |
|
| 502 g_string_free(data->server_signature, TRUE); |
|
| 503 g_free(data); |
|
| 504 js->auth_mech_data = NULL; |
508 js->auth_mech_data = NULL; |
| 505 } |
509 } |
| 506 } |
510 } |
| 507 |
511 |
| 508 static JabberSaslMech scram_sha1_mech = { |
512 static JabberSaslMech scram_sha1_mech = { |