| 27 |
27 |
| 28 #include "auth.h" |
28 #include "auth.h" |
| 29 #include "jabber.h" |
29 #include "jabber.h" |
| 30 |
30 |
| 31 static JabberSaslState jabber_auth_start_cyrus(JabberStream *js, xmlnode **reply, |
31 static JabberSaslState jabber_auth_start_cyrus(JabberStream *js, xmlnode **reply, |
| 32 const char **error); |
32 char **error); |
| 33 static void jabber_sasl_build_callbacks(JabberStream *); |
33 static void jabber_sasl_build_callbacks(JabberStream *); |
| 34 |
34 |
| 35 static void disallow_plaintext_auth(PurpleAccount *account) |
35 static void disallow_plaintext_auth(PurpleAccount *account) |
| 36 { |
36 { |
| 37 purple_connection_error_reason(purple_account_get_connection(account), |
37 purple_connection_error_reason(purple_account_get_connection(account), |
| 39 _("Server requires plaintext authentication over an unencrypted stream")); |
39 _("Server requires plaintext authentication over an unencrypted stream")); |
| 40 } |
40 } |
| 41 |
41 |
| 42 static void start_cyrus_wrapper(JabberStream *js) |
42 static void start_cyrus_wrapper(JabberStream *js) |
| 43 { |
43 { |
| 44 const char *error; |
44 char *error = NULL; |
| 45 xmlnode *response; |
45 xmlnode *response = NULL; |
| 46 JabberSaslState state = jabber_auth_start_cyrus(js, &response, &error); |
46 JabberSaslState state = jabber_auth_start_cyrus(js, &response, &error); |
| 47 |
47 |
| 48 if (state == JABBER_SASL_STATE_FAIL) { |
48 if (state == JABBER_SASL_STATE_FAIL) { |
| 49 purple_connection_error_reason(js->gc, |
49 purple_connection_error_reason(js->gc, |
| 50 PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, |
50 PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, |
| 51 error); |
51 error); |
| |
52 g_free(error); |
| 52 } else if (response) { |
53 } else if (response) { |
| 53 jabber_send(js, response); |
54 jabber_send(js, response); |
| 54 xmlnode_free(response); |
55 xmlnode_free(response); |
| 55 } |
56 } |
| 56 } |
57 } |
| 178 /* Disable the account as the user has canceled connecting */ |
179 /* Disable the account as the user has canceled connecting */ |
| 179 purple_account_set_enabled(account, purple_core_get_ui(), FALSE); |
180 purple_account_set_enabled(account, purple_core_get_ui(), FALSE); |
| 180 } |
181 } |
| 181 |
182 |
| 182 static JabberSaslState |
183 static JabberSaslState |
| 183 jabber_auth_start_cyrus(JabberStream *js, xmlnode **reply, const char **error) |
184 jabber_auth_start_cyrus(JabberStream *js, xmlnode **reply, char **error) |
| 184 { |
185 { |
| 185 PurpleAccount *account; |
186 PurpleAccount *account; |
| 186 const char *clientout = NULL; |
187 const char *clientout = NULL; |
| 187 char *enc_out; |
188 char *enc_out; |
| 188 unsigned coutlen = 0; |
189 unsigned coutlen = 0; |
| 385 js->sasl_cb[id].id = SASL_CB_LIST_END; |
386 js->sasl_cb[id].id = SASL_CB_LIST_END; |
| 386 } |
387 } |
| 387 |
388 |
| 388 static JabberSaslState |
389 static JabberSaslState |
| 389 jabber_cyrus_start(JabberStream *js, xmlnode *mechanisms, |
390 jabber_cyrus_start(JabberStream *js, xmlnode *mechanisms, |
| 390 xmlnode **reply, const char **error) |
391 xmlnode **reply, char **error) |
| 391 { |
392 { |
| 392 xmlnode *mechnode; |
393 xmlnode *mechnode; |
| 393 |
394 |
| 394 js->sasl_mechs = g_string_new(""); |
395 js->sasl_mechs = g_string_new(""); |
| 395 |
396 |
| 421 return jabber_auth_start_cyrus(js, reply, error); |
422 return jabber_auth_start_cyrus(js, reply, error); |
| 422 } |
423 } |
| 423 |
424 |
| 424 static JabberSaslState |
425 static JabberSaslState |
| 425 jabber_cyrus_handle_challenge(JabberStream *js, xmlnode *packet, |
426 jabber_cyrus_handle_challenge(JabberStream *js, xmlnode *packet, |
| 426 xmlnode **reply, const char **error) |
427 xmlnode **reply, char **error) |
| 427 { |
428 { |
| 428 char *enc_in = xmlnode_get_data(packet); |
429 char *enc_in = xmlnode_get_data(packet); |
| 429 unsigned char *dec_in; |
430 unsigned char *dec_in; |
| 430 char *enc_out; |
431 char *enc_out; |
| 431 const char *c_out; |
432 const char *c_out; |
| 476 } |
477 } |
| 477 } |
478 } |
| 478 |
479 |
| 479 static JabberSaslState |
480 static JabberSaslState |
| 480 jabber_cyrus_handle_success(JabberStream *js, xmlnode *packet, |
481 jabber_cyrus_handle_success(JabberStream *js, xmlnode *packet, |
| 481 const char **error) |
482 char **error) |
| 482 { |
483 { |
| 483 const void *x; |
484 const void *x; |
| 484 |
485 |
| 485 /* The SASL docs say that if the client hasn't returned OK yet, we |
486 /* The SASL docs say that if the client hasn't returned OK yet, we |
| 486 * should try one more round against it |
487 * should try one more round against it |
| 500 g_free(enc_in); |
501 g_free(enc_in); |
| 501 g_free(dec_in); |
502 g_free(dec_in); |
| 502 |
503 |
| 503 if (js->sasl_state != SASL_OK) { |
504 if (js->sasl_state != SASL_OK) { |
| 504 /* This should never happen! */ |
505 /* This should never happen! */ |
| 505 *error = _("Invalid response from server"); |
506 *error = g_strdup(_("Invalid response from server")); |
| 506 g_return_val_if_reached(JABBER_SASL_STATE_FAIL); |
507 g_return_val_if_reached(JABBER_SASL_STATE_FAIL); |
| 507 } |
508 } |
| 508 } |
509 } |
| 509 |
510 |
| 510 /* If we've negotiated a security layer, we need to enable it */ |
511 /* If we've negotiated a security layer, we need to enable it */ |
| 519 return JABBER_SASL_STATE_OK; |
520 return JABBER_SASL_STATE_OK; |
| 520 } |
521 } |
| 521 |
522 |
| 522 static JabberSaslState |
523 static JabberSaslState |
| 523 jabber_cyrus_handle_failure(JabberStream *js, xmlnode *packet, |
524 jabber_cyrus_handle_failure(JabberStream *js, xmlnode *packet, |
| 524 xmlnode **reply, const char **error) |
525 xmlnode **reply, char **error) |
| 525 { |
526 { |
| 526 if (js->auth_fail_count++ < 5) { |
527 if (js->auth_fail_count++ < 5) { |
| 527 if (js->current_mech && *js->current_mech) { |
528 if (js->current_mech && *js->current_mech) { |
| 528 char *pos; |
529 char *pos; |
| 529 if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) { |
530 if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) { |