diff options
author | Gary Kramlich <grim@reaperworld.com> | 2023-02-28 03:20:33 -0600 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2023-02-28 03:20:33 -0600 |
commit | 349731e9a959acedcd01ca0c03374436610071b6 (patch) | |
tree | 7e4fe6736ceb2dd7faf92ef65a875184e0d0a9cb /libpurple/protocols | |
parent | a36beced54501cced2f7403655800d55aa1df0c9 (diff) | |
download | pidgin-349731e9a959acedcd01ca0c03374436610071b6.tar.gz |
Remove Cyrus SASL from XMPP
This will eventually be replaced by Hasl, but XMPP has it's own built-in SASL
mechanisms as well as Cyrus, so removing Cyrus first is just the first step.
Testing Done:
Connected an XMPP account, sent direct messages from both sides, and joined a muc and sent messages from both sides as well.
Also ran the unit tests.
Reviewed at https://reviews.imfreedom.org/r/2295/
Diffstat (limited to 'libpurple/protocols')
-rw-r--r-- | libpurple/protocols/jabber/auth.c | 7 | ||||
-rw-r--r-- | libpurple/protocols/jabber/auth.h | 1 | ||||
-rw-r--r-- | libpurple/protocols/jabber/auth_cyrus.c | 672 | ||||
-rw-r--r-- | libpurple/protocols/jabber/jabber.c | 99 | ||||
-rw-r--r-- | libpurple/protocols/jabber/jabber.h | 14 | ||||
-rw-r--r-- | libpurple/protocols/jabber/meson.build | 6 |
6 files changed, 1 insertions, 798 deletions
diff --git a/libpurple/protocols/jabber/auth.c b/libpurple/protocols/jabber/auth.c index 2ad5ecb7e7..d22e282862 100644 --- a/libpurple/protocols/jabber/auth.c +++ b/libpurple/protocols/jabber/auth.c @@ -197,12 +197,6 @@ jabber_auth_start(JabberStream *js, PurpleXmlNode *packet) for (l = auth_mechs; l; l = l->next) { JabberSaslMech *possible = l->data; - /* Is this the Cyrus SASL mechanism? */ - if (purple_strequal(possible->name, "*")) { - js->auth_mech = possible; - break; - } - /* Can we find this mechanism in the server's list? */ if (g_slist_find_custom(mechanisms, possible->name, (GCompareFunc)strcmp)) { js->auth_mech = possible; @@ -551,7 +545,6 @@ void jabber_auth_init(void) jabber_auth_add_mech(jabber_auth_get_plain_mech()); jabber_auth_add_mech(jabber_auth_get_digest_md5_mech()); - jabber_auth_add_mech(jabber_auth_get_cyrus_mech()); #ifdef HAVE_WEBEX_TOKEN jabber_auth_add_mech(jabber_auth_get_webex_token_mech()); #endif diff --git a/libpurple/protocols/jabber/auth.h b/libpurple/protocols/jabber/auth.h index 34886fb32e..764afa4fe3 100644 --- a/libpurple/protocols/jabber/auth.h +++ b/libpurple/protocols/jabber/auth.h @@ -56,7 +56,6 @@ void jabber_auth_handle_failure(JabberStream *js, PurpleXmlNode *packet); JabberSaslMech *jabber_auth_get_plain_mech(void); JabberSaslMech *jabber_auth_get_digest_md5_mech(void); JabberSaslMech **jabber_auth_get_scram_mechs(gint *count); -JabberSaslMech *jabber_auth_get_cyrus_mech(void); JabberSaslMech *jabber_auth_get_webex_token_mech(void); void jabber_auth_init(void); diff --git a/libpurple/protocols/jabber/auth_cyrus.c b/libpurple/protocols/jabber/auth_cyrus.c deleted file mode 100644 index bc68a6eb66..0000000000 --- a/libpurple/protocols/jabber/auth_cyrus.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * purple - Jabber Protocol Plugin - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ - -#include <config.h> - -#include <glib/gi18n-lib.h> - -#include <purple.h> - -#include "auth.h" -#include "jabber.h" - -static JabberSaslState jabber_auth_start_cyrus(JabberStream *js, PurpleXmlNode **reply, - char **error); -static void jabber_sasl_build_callbacks(JabberStream *); - -static void disallow_plaintext_auth(PurpleAccount *account) -{ - purple_connection_error(purple_account_get_connection(account), - PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Server may require plaintext authentication over an unencrypted stream")); -} - -static void start_cyrus_wrapper(JabberStream *js) -{ - char *error = NULL; - PurpleXmlNode *response = NULL; - JabberSaslState state = jabber_auth_start_cyrus(js, &response, &error); - - if (state == JABBER_SASL_STATE_FAIL) { - purple_connection_error(js->gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, - error); - g_free(error); - } else if (response) { - jabber_send(js, response); - purple_xmlnode_free(response); - } -} - - -/* Callbacks for Cyrus SASL */ - -static int -jabber_sasl_cb_realm(void *ctx, int id, G_GNUC_UNUSED const char **avail, - const char **result) -{ - JabberStream *js = ctx; - - if (id != SASL_CB_GETREALM || !result) return SASL_BADPARAM; - - *result = js->user->domain; - - return SASL_OK; -} - -static int jabber_sasl_cb_simple(void *ctx, int id, const char **res, unsigned *len) -{ - JabberStream *js = ctx; - - switch(id) { - case SASL_CB_AUTHNAME: - *res = js->user->node; - break; - case SASL_CB_USER: - *res = ""; - break; - default: - return SASL_BADPARAM; - } - if (len) *len = strlen((char *)*res); - return SASL_OK; -} - -static int jabber_sasl_cb_secret(sasl_conn_t *conn, void *ctx, int id, sasl_secret_t **secret) -{ - JabberStream *js = ctx; - size_t len; - - if (!conn || !secret || id != SASL_CB_PASS) - return SASL_BADPARAM; - - len = strlen(js->sasl_password); - /* Not an off-by-one because sasl_secret_t defines char data[1] */ - /* TODO: This can probably be moved to glib's allocator */ - js->sasl_secret = malloc(sizeof(sasl_secret_t) + len); - if (!js->sasl_secret) - return SASL_NOMEM; - - js->sasl_secret->len = len; - strcpy((char*)js->sasl_secret->data, js->sasl_password); - - *secret = js->sasl_secret; - return SASL_OK; -} - -static void allow_cyrus_plaintext_auth(PurpleAccount *account) -{ - PurpleConnection *gc; - JabberStream *js; - - gc = purple_account_get_connection(account); - js = purple_connection_get_protocol_data(gc); - - purple_account_set_bool(account, "auth_plain_in_clear", TRUE); - - start_cyrus_wrapper(js); -} - -static void auth_pass_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - PurpleAccount *account; - JabberStream *js; - const char *entry; - gboolean remember; - - /* TODO: the password prompt dialog doesn't get disposed if the account disconnects */ - PURPLE_ASSERT_CONNECTION_IS_VALID(gc); - - account = purple_connection_get_account(gc); - js = purple_connection_get_protocol_data(gc); - - entry = purple_request_fields_get_string(fields, "password"); - remember = purple_request_fields_get_bool(fields, "remember"); - - if (!entry || !*entry) - { - purple_notify_error(account, NULL, - _("Password is required to sign on."), NULL, - purple_request_cpar_from_connection(gc)); - return; - } - - if(remember) { - PurpleCredentialManager *manager = NULL; - - purple_account_set_remember_password(account, TRUE); - - manager = purple_credential_manager_get_default(); - purple_credential_manager_write_password_async(manager, account, entry, - NULL, NULL, NULL); - } - - js->sasl_password = g_strdup(entry); - - /* Rebuild our callbacks as we now have a password to offer */ - jabber_sasl_build_callbacks(js); - - /* Restart our negotiation */ - start_cyrus_wrapper(js); -} - -static void -auth_no_pass_cb(PurpleConnection *gc, - G_GNUC_UNUSED PurpleRequestFields *fields) -{ - PurpleAccount *account; - - /* TODO: the password prompt dialog doesn't get disposed if the account disconnects */ - PURPLE_ASSERT_CONNECTION_IS_VALID(gc); - - account = purple_connection_get_account(gc); - - /* Disable the account as the user has cancelled connecting */ - purple_account_set_enabled(account, FALSE); -} - -static void -auth_pass_read_cb(GObject *source, GAsyncResult *result, gpointer data) { - JabberStream *js = data; - PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(source); - GError *error = NULL; - char *password = NULL; - - password = purple_credential_manager_read_password_finish(manager, result, - &error); - if(password == NULL || error != NULL) { - PurpleAccount *account = NULL; - const char *message = "unknown error"; - - if(error != NULL) { - message = error->message; - } - - purple_debug_warning("jabber", "failed to read password from the " - "credential manager : %s", message); - - g_clear_error(&error); - - account = purple_connection_get_account(js->gc); - purple_account_request_password(account, G_CALLBACK(auth_pass_cb), - G_CALLBACK(auth_no_pass_cb), - js->gc); - - return; - } - - js->sasl_password = password; - - /* Rebuild our callbacks as we now have a password to offer */ - jabber_sasl_build_callbacks(js); - - /* Restart our negotiation */ - start_cyrus_wrapper(js); -} - -static gboolean remove_current_mech(JabberStream *js) { - char *pos; - if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) { - size_t len = strlen(js->current_mech); - /* Clean up space that separated this Mech from the one before or after it */ - if (pos > js->sasl_mechs->str && *(pos - 1) == ' ') { - /* Handle removing space before when current_mech isn't the first mech in the list */ - pos--; - len++; - } else if (strlen(pos) > len && *(pos + len) == ' ') { - /* Handle removing space after */ - len++; - } - g_string_erase(js->sasl_mechs, pos - js->sasl_mechs->str, len); - return TRUE; - } - return FALSE; -} - -static JabberSaslState -jabber_auth_start_cyrus(JabberStream *js, PurpleXmlNode **reply, char **error) -{ - PurpleAccount *account; - const char *clientout = NULL; - char *enc_out; - unsigned coutlen = 0; - sasl_security_properties_t secprops; - gboolean again; - gboolean plaintext = TRUE; - - /* Set up security properties and options */ - secprops.min_ssf = 0; - secprops.security_flags = SASL_SEC_NOANONYMOUS; - - account = purple_connection_get_account(js->gc); - - if (!jabber_stream_is_ssl(js)) { - secprops.max_ssf = -1; - secprops.maxbufsize = 4096; - plaintext = purple_account_get_bool(account, "auth_plain_in_clear", FALSE); - if (!plaintext) - secprops.security_flags |= SASL_SEC_NOPLAINTEXT; - } else { - secprops.max_ssf = 0; - secprops.maxbufsize = 0; - plaintext = TRUE; - } - secprops.property_names = 0; - secprops.property_values = 0; - - do { - again = FALSE; - - js->sasl_state = sasl_client_new("xmpp", js->serverFQDN, NULL, NULL, js->sasl_cb, 0, &js->sasl); - if (js->sasl_state==SASL_OK) { - sasl_setprop(js->sasl, SASL_SEC_PROPS, &secprops); - purple_debug_info("sasl", "Mechs found: %s\n", js->sasl_mechs->str); - js->sasl_state = sasl_client_start(js->sasl, js->sasl_mechs->str, NULL, &clientout, &coutlen, &js->current_mech); - } - switch (js->sasl_state) { - /* Success */ - case SASL_OK: - case SASL_CONTINUE: - break; - case SASL_NOMECH: - /* No mechanisms have offered to help */ - - /* Firstly, if we don't have a password try - * to get one - */ - - if (!js->sasl_password) { - PurpleCredentialManager *manager = NULL; - - manager = purple_credential_manager_get_default(); - purple_credential_manager_read_password_async(manager, - account, - NULL, - auth_pass_read_cb, - js); - return JABBER_SASL_STATE_CONTINUE; - - /* If we've got a password, but aren't sending - * it in plaintext, see if we can turn on - * plaintext auth - */ - /* XXX Should we just check for PLAIN/LOGIN being offered mechanisms? */ - } else if (!plaintext) { - PurpleContactInfo *info = PURPLE_CONTACT_INFO(account); - char *msg = g_strdup_printf(_("%s may require plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), - purple_contact_info_get_username(info)); - purple_request_yes_no(js->gc, _("Plaintext Authentication"), - _("Plaintext Authentication"), - msg, - 1, purple_request_cpar_from_account(account), account, - allow_cyrus_plaintext_auth, - disallow_plaintext_auth); - g_free(msg); - return JABBER_SASL_STATE_CONTINUE; - - } else - js->auth_fail_count++; - - if (js->auth_fail_count == 1 && - purple_strequal(js->sasl_mechs->str, "GSSAPI")) { - /* If we tried GSSAPI first, it failed, and it was the only method we had to try, try jabber:iq:auth - * for compatibility with iChat 10.5 Server and other jabberd based servers. - * - * iChat Server 10.5 and certain other corporate servers offer SASL GSSAPI by default, which is often - * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails. - * - * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However, - * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms. - * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers - * which would connect without issue otherwise. -evands - */ - js->auth_mech = NULL; - jabber_auth_start_old(js); - return JABBER_SASL_STATE_CONTINUE; - } - - break; - - /* Fatal errors. Give up and go home */ - case SASL_BADPARAM: - case SASL_NOMEM: - *error = g_strdup(_("SASL authentication failed")); - break; - - /* For everything else, fail the mechanism and try again */ - default: - purple_debug_info("sasl", "sasl_state is %d, failing the mech and trying again\n", js->sasl_state); - - js->auth_fail_count++; - - /* - * DAA: is this right? - * The manpage says that "mech" will contain the chosen mechanism on success. - * Presumably, if we get here that isn't the case and we shouldn't try again? - * I suspect that this never happens. - */ - /* - * SXW: Yes, this is right. What this handles is the situation where a - * mechanism, say GSSAPI, is tried. If that mechanism fails, it may be - * due to mechanism specific issues, so we want to try one of the other - * supported mechanisms. This code handles that case - */ - if (js->current_mech && *js->current_mech) { - remove_current_mech(js); - /* Should we only try again if we've removed the mech? */ - again = TRUE; - } - - sasl_dispose(&js->sasl); - } - } while (again); - - if (js->sasl_state == SASL_CONTINUE || js->sasl_state == SASL_OK) { - PurpleXmlNode *auth = purple_xmlnode_new("auth"); - purple_xmlnode_set_namespace(auth, NS_XMPP_SASL); - purple_xmlnode_set_attrib(auth, "mechanism", js->current_mech); - - if (clientout) { - if (coutlen == 0) { - purple_xmlnode_insert_data(auth, "=", -1); - } else { - enc_out = g_base64_encode((unsigned char*)clientout, coutlen); - purple_xmlnode_insert_data(auth, enc_out, -1); - g_free(enc_out); - } - } - - *reply = auth; - return JABBER_SASL_STATE_CONTINUE; - } else { - return JABBER_SASL_STATE_FAIL; - } -} - -static int -jabber_sasl_cb_log(G_GNUC_UNUSED void *context, int level, const char *message) -{ - if(level <= SASL_LOG_TRACE) - purple_debug_info("sasl", "%s\n", message); - - return SASL_OK; -} - -static void -jabber_sasl_build_callbacks(JabberStream *js) -{ - int id; - - /* Set up our callbacks structure */ - if (js->sasl_cb == NULL) - js->sasl_cb = g_new0(sasl_callback_t,6); - - id = 0; - js->sasl_cb[id].id = SASL_CB_GETREALM; - js->sasl_cb[id].proc = (void *)jabber_sasl_cb_realm; - js->sasl_cb[id].context = (void *)js; - id++; - - js->sasl_cb[id].id = SASL_CB_AUTHNAME; - js->sasl_cb[id].proc = (void *)jabber_sasl_cb_simple; - js->sasl_cb[id].context = (void *)js; - id++; - - js->sasl_cb[id].id = SASL_CB_USER; - js->sasl_cb[id].proc = (void *)jabber_sasl_cb_simple; - js->sasl_cb[id].context = (void *)js; - id++; - - if (js->sasl_password != NULL) { - js->sasl_cb[id].id = SASL_CB_PASS; - js->sasl_cb[id].proc = (void *)jabber_sasl_cb_secret; - js->sasl_cb[id].context = (void *)js; - id++; - } - - js->sasl_cb[id].id = SASL_CB_LOG; - js->sasl_cb[id].proc = (void *)jabber_sasl_cb_log; - js->sasl_cb[id].context = (void*)js; - id++; - - js->sasl_cb[id].id = SASL_CB_LIST_END; -} - -static JabberSaslState -jabber_cyrus_start(JabberStream *js, PurpleXmlNode *mechanisms, - PurpleXmlNode **reply, char **error) -{ - PurpleXmlNode *mechnode, *hostname; - JabberSaslState ret; - - js->sasl_mechs = g_string_new(""); - js->sasl_password = g_strdup(purple_connection_get_password(js->gc)); - /* XEP-0233 says we should grab the hostname for Kerberos v5, but there - * is no claim about other SASL mechanisms. Fortunately, most don't - * care what we use, so just use the domainpart. */ - hostname = purple_xmlnode_get_child_with_namespace( - mechanisms, "hostname", NS_XMPP_SERVER_REGISTRATION); - if (hostname) { - js->serverFQDN = purple_xmlnode_get_data(hostname); - } - if (js->serverFQDN == NULL) { - js->serverFQDN = g_strdup(js->user->domain); - } - - for(mechnode = purple_xmlnode_get_child(mechanisms, "mechanism"); mechnode; - mechnode = purple_xmlnode_get_next_twin(mechnode)) - { - char *mech_name = purple_xmlnode_get_data(mechnode); - - /* Ignore blank mechanisms and EXTERNAL. External isn't - * supported, and Cyrus SASL's mechanism returns - * SASL_NOMECH when the caller (us) doesn't configure it. - * Except SASL_NOMECH is supposed to mean "no concordant - * mechanisms"... Easiest just to blacklist it (for now). - */ - if (!mech_name || !*mech_name || - purple_strequal(mech_name, "EXTERNAL")) { - g_free(mech_name); - continue; - } - - g_string_append(js->sasl_mechs, mech_name); - g_string_append_c(js->sasl_mechs, ' '); - g_free(mech_name); - } - - /* Strip off the trailing ' ' */ - if (js->sasl_mechs->len > 1) - g_string_truncate(js->sasl_mechs, js->sasl_mechs->len - 1); - - jabber_sasl_build_callbacks(js); - ret = jabber_auth_start_cyrus(js, reply, error); - - /* - * Triggered if no overlap between server and client - * supported mechanisms. - */ - if (ret == JABBER_SASL_STATE_FAIL && *error == NULL) - *error = g_strdup(_("Server does not use any supported authentication method")); - - return ret; -} - -static JabberSaslState -jabber_cyrus_handle_challenge(JabberStream *js, PurpleXmlNode *packet, - PurpleXmlNode **reply, char **error) -{ - char *enc_in = purple_xmlnode_get_data(packet); - unsigned char *dec_in; - char *enc_out; - const char *c_out; - unsigned int clen; - gsize declen; - - dec_in = g_base64_decode(enc_in, &declen); - - js->sasl_state = sasl_client_step(js->sasl, (char*)dec_in, declen, - NULL, &c_out, &clen); - g_free(enc_in); - g_free(dec_in); - if (js->sasl_state != SASL_CONTINUE && js->sasl_state != SASL_OK) { - gchar *tmp = g_strdup_printf(_("SASL error: %s"), - sasl_errdetail(js->sasl)); - purple_debug_error("jabber", "Error is %d : %s\n", - js->sasl_state, sasl_errdetail(js->sasl)); - *error = tmp; - return JABBER_SASL_STATE_FAIL; - } else { - PurpleXmlNode *response = purple_xmlnode_new("response"); - purple_xmlnode_set_namespace(response, NS_XMPP_SASL); - if (clen > 0) { - /* Cyrus SASL 2.1.22 appears to contain code to add the charset - * to the response for DIGEST-MD5 but there is no possibility - * it will be executed. - * - * My reading of the digestmd5 plugin indicates the username and - * realm are always encoded in UTF-8 (they seem to be the values - * we pass in), so we need to ensure charset=utf-8 is set. - */ - if (!purple_strequal(js->current_mech, "DIGEST-MD5") || - strstr(c_out, ",charset=")) - /* If we're not using DIGEST-MD5 or Cyrus SASL is fixed */ - enc_out = g_base64_encode((unsigned char*)c_out, clen); - else { - char *tmp = g_strdup_printf("%s,charset=utf-8", c_out); - enc_out = g_base64_encode((unsigned char*)tmp, clen + 14); - g_free(tmp); - } - - purple_xmlnode_insert_data(response, enc_out, -1); - g_free(enc_out); - } - - *reply = response; - return JABBER_SASL_STATE_CONTINUE; - } -} - -static JabberSaslState -jabber_cyrus_handle_success(JabberStream *js, PurpleXmlNode *packet, - char **error) -{ - const void *x; - - /* The SASL docs say that if the client hasn't returned OK yet, we - * should try one more round against it - */ - if (js->sasl_state != SASL_OK) { - char *enc_in = purple_xmlnode_get_data(packet); - unsigned char *dec_in = NULL; - const char *c_out; - unsigned int clen; - gsize declen = 0; - - if(enc_in != NULL) - dec_in = g_base64_decode(enc_in, &declen); - - js->sasl_state = sasl_client_step(js->sasl, (char*)dec_in, declen, NULL, &c_out, &clen); - - g_free(enc_in); - g_free(dec_in); - - if (js->sasl_state != SASL_OK) { - /* This happens when the server sends back jibberish - * in the "additional data with success" case. - * Seen with Wildfire 3.0.1. - */ - *error = g_strdup(_("Invalid response from server")); - return JABBER_SASL_STATE_FAIL; - } - } - - /* If we've negotiated a security layer, we need to enable it */ - if (js->sasl) { - sasl_getprop(js->sasl, SASL_SSF, &x); - if (*(int *)x > 0) { - sasl_getprop(js->sasl, SASL_MAXOUTBUF, &x); - js->sasl_maxbuf = *(int *)x; - } - } - - return JABBER_SASL_STATE_OK; -} - -static JabberSaslState -jabber_cyrus_handle_failure(JabberStream *js, - G_GNUC_UNUSED PurpleXmlNode *packet, - PurpleXmlNode **reply, char **error) -{ - if (js->auth_fail_count++ < 5) { - if (js->current_mech && *js->current_mech) { - remove_current_mech(js); - } - - /* Should we only try again if we've actually removed a mech? */ - if (*js->sasl_mechs->str) { - /* If we have remaining mechs to try, do so */ - sasl_dispose(&js->sasl); - - return jabber_auth_start_cyrus(js, reply, error); - - } else if ((js->auth_fail_count == 1) && - purple_strequal(js->current_mech, "GSSAPI")) { - /* If we tried GSSAPI first, it failed, and it was the only method we had to try, try jabber:iq:auth - * for compatibility with iChat 10.5 Server and other jabberd based servers. - * - * iChat Server 10.5 and certain other corporate servers offer SASL GSSAPI by default, which is often - * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails. - * - * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However, - * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms. - * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers - * which would connect without issue otherwise. -evands - */ - sasl_dispose(&js->sasl); - js->sasl = NULL; - js->auth_mech = NULL; - jabber_auth_start_old(js); - return JABBER_SASL_STATE_CONTINUE; - } - } - - /* Nothing to send */ - return JABBER_SASL_STATE_FAIL; -} - -static JabberSaslMech cyrus_mech = { - 100, /* priority */ - "*", /* name; Cyrus provides a bunch of mechanisms, so use an invalid - * mechanism name (per rfc4422 3.1). */ - jabber_cyrus_start, - jabber_cyrus_handle_challenge, - jabber_cyrus_handle_success, - jabber_cyrus_handle_failure, - NULL, -}; - -JabberSaslMech *jabber_auth_get_cyrus_mech(void) -{ - return &cyrus_mech; -} diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c index 63979a1347..29e9227bfc 100644 --- a/libpurple/protocols/jabber/jabber.c +++ b/libpurple/protocols/jabber/jabber.c @@ -465,47 +465,6 @@ jabber_send_raw(G_GNUC_UNUSED PurpleProtocolServer *protocol_server, if (len == -1) len = strlen(data); - /* If we've got a security layer, we need to encode the data, - * splitting it on the maximum buffer length negotiated */ - if (js->sasl_maxbuf>0) { - int pos = 0; - - g_return_if_fail(js->input != NULL); - - while (pos < len) { - int towrite; - const char *out; - unsigned olen; - int rc; - - towrite = MIN((len - pos), js->sasl_maxbuf); - - rc = sasl_encode(js->sasl, &data[pos], towrite, - &out, &olen); - if (rc != SASL_OK) { - gchar *error = - g_strdup_printf(_("SASL error: %s"), - sasl_errdetail(js->sasl)); - purple_debug_error("jabber", - "sasl_encode error %d: %s\n", rc, - sasl_errdetail(js->sasl)); - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - error); - g_free(error); - return; - } - pos += towrite; - - /* do_jabber_send_raw returns FALSE when it throws a - * connection error. - */ - if (!do_jabber_send_raw(js, out, olen)) - break; - } - return; - } - if (js->bosh) jabber_bosh_connection_send(js->bosh, data); else @@ -626,30 +585,6 @@ jabber_recv_cb(GObject *stream, gpointer data) } purple_connection_update_last_received(gc); - if (js->sasl_maxbuf > 0) { - const char *out; - unsigned int olen; - int rc; - - rc = sasl_decode(js->sasl, buf, len, &out, &olen); - if (rc != SASL_OK) { - gchar *error = - g_strdup_printf(_("SASL error: %s"), - sasl_errdetail(js->sasl)); - purple_debug_error("jabber", - "sasl_decode_error %d: %s\n", rc, - sasl_errdetail(js->sasl)); - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - error); - } else if (olen > 0) { - purple_debug_info("jabber", "RecvSASL (%u): %s\n", olen, out); - jabber_parser_process(js, out, olen); - if (js->reinit) - jabber_stream_init(js); - } - return G_SOURCE_CONTINUE; - } buf[len] = '\0'; purple_debug_misc("jabber", "Recv (%" G_GSSIZE_FORMAT "): %s", len, buf); @@ -1117,14 +1052,6 @@ jabber_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection *gc) { if (js->auth_mech && js->auth_mech->dispose) js->auth_mech->dispose(js); - if(js->sasl) - sasl_dispose(&js->sasl); - if(js->sasl_mechs) - g_string_free(js->sasl_mechs, TRUE); - g_free(js->sasl_cb); - /* Note: _not_ g_free. See auth_cyrus.c:jabber_sasl_cb_secret */ - free(js->sasl_secret); - g_free(js->sasl_password); g_free(js->serverFQDN); g_list_free_full(js->commands, (GDestroyNotify)jabber_adhoc_commands_free); g_free(js->server_name); @@ -3243,32 +3170,6 @@ jabber_do_init(void) const gchar *type = "pc"; /* default client type, if unknown or unspecified */ const gchar *ui_name = NULL; - /* We really really only want to do this once per process */ - static gboolean sasl_initialized = FALSE; -#ifdef _WIN32 - UINT old_error_mode; - gchar *sasldir; -#endif - int ret; - - /* XXX - If any other plugin wants SASL this won't be good ... */ - if (!sasl_initialized) { - sasl_initialized = TRUE; -#ifdef _WIN32 - sasldir = g_strdup(wpurple_lib_dir("sasl2")); - sasl_set_path(SASL_PATH_TYPE_PLUGIN, sasldir); - g_free(sasldir); - /* Suppress error popups for failing to load sasl plugins */ - old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS); -#endif - if ((ret = sasl_client_init(NULL)) != SASL_OK) { - purple_debug_error("xmpp", "Error (%d) initializing SASL.\n", ret); - } -#ifdef _WIN32 - /* Restore the original error mode */ - SetErrorMode(old_error_mode); -#endif - } jabber_cmds = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, cmds_free_func); diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h index 2c85ff7dc6..5cd3f4ebae 100644 --- a/libpurple/protocols/jabber/jabber.h +++ b/libpurple/protocols/jabber/jabber.h @@ -69,8 +69,6 @@ typedef struct _JabberStream JabberStream; #include "buddy.h" #include "bosh.h" -#include <sasl/sasl.h> - #define CAPS0115_NODE "https://pidgin.im/" #define JABBER_TYPE_PROTOCOL (jabber_protocol_get_type()) @@ -191,18 +189,6 @@ struct _JabberStream char *serverFQDN; - sasl_conn_t *sasl; - sasl_callback_t *sasl_cb; - sasl_secret_t *sasl_secret; - const char *current_mech; - int auth_fail_count; - - int sasl_state; - int sasl_maxbuf; - GString *sasl_mechs; - - gchar *sasl_password; - gboolean vcard_fetched; /* Entity Capabilities hash */ diff --git a/libpurple/protocols/jabber/meson.build b/libpurple/protocols/jabber/meson.build index 08b3c78dfc..f115ee9738 100644 --- a/libpurple/protocols/jabber/meson.build +++ b/libpurple/protocols/jabber/meson.build @@ -78,10 +78,6 @@ JABBER_SOURCES = [ 'xmpp.h' ] -if sasl.found() - JABBER_SOURCES += ['auth_cyrus.c'] -endif - if IS_WIN32 jabber_link_args = ['-Wl,--export-all-symbols'] else @@ -100,7 +96,7 @@ if DYNAMIC_JABBER jabber_prpl = shared_library('jabber', JABBER_SOURCES, c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-XMPP"'], link_args : jabber_link_args, - dependencies : [gstreamer, idn, libxml, sasl, libpurple_dep, libsoup, glib, gio, math, ws2_32], + dependencies : [gstreamer, idn, libxml, libpurple_dep, libsoup, glib, gio, math, ws2_32], install : true, install_dir : PURPLE_PLUGINDIR) |