pidgin/pidgin

Remove Cyrus SASL from XMPP

14 months ago, Gary Kramlich
0601c6f60bff
Parents f22bea74160d
Children 33ed4a2a7593
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/
--- a/libpurple/protocols/jabber/auth.c Sun Feb 26 01:31:03 2023 -0600
+++ b/libpurple/protocols/jabber/auth.c Tue Feb 28 03:20:33 2023 -0600
@@ -197,12 +197,6 @@
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 @@
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
--- a/libpurple/protocols/jabber/auth.h Sun Feb 26 01:31:03 2023 -0600
+++ b/libpurple/protocols/jabber/auth.h Tue Feb 28 03:20:33 2023 -0600
@@ -56,7 +56,6 @@
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);
--- a/libpurple/protocols/jabber/auth_cyrus.c Sun Feb 26 01:31:03 2023 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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;
-}
--- a/libpurple/protocols/jabber/jabber.c Sun Feb 26 01:31:03 2023 -0600
+++ b/libpurple/protocols/jabber/jabber.c Tue Feb 28 03:20:33 2023 -0600
@@ -465,47 +465,6 @@
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 @@
}
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 @@
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 @@
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);
--- a/libpurple/protocols/jabber/jabber.h Sun Feb 26 01:31:03 2023 -0600
+++ b/libpurple/protocols/jabber/jabber.h Tue Feb 28 03:20:33 2023 -0600
@@ -69,8 +69,6 @@
#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 @@
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 */
--- a/libpurple/protocols/jabber/meson.build Sun Feb 26 01:31:03 2023 -0600
+++ b/libpurple/protocols/jabber/meson.build Tue Feb 28 03:20:33 2023 -0600
@@ -78,10 +78,6 @@
'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 @@
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)