pidgin/pidgin

Parents 413cde086275
Children 64d7e69bff25
Fix an issue where XMPP accounts weren't reading passwords from the credential manager

XMPP has passwords set to optional because of the SASL implementation. However,
the fallback for that SASL implementation wasn't checking the credential manager
for a password which lead to a prompt for the password. This patch corrects that
behavior.

Testing Done:
Connected an XMPP account with the `require password` account option set to `FALSE` with a password stored in the active credential provider and verified that it successfully logged into without prompting for a password.

Reviewed at https://reviews.imfreedom.org/r/1969/
--- a/libpurple/connection.c Fri Oct 28 01:52:28 2022 -0500
+++ b/libpurple/connection.c Fri Oct 28 03:42:47 2022 -0500
@@ -342,6 +342,22 @@
return priv->password;
}
+void
+purple_connection_set_password(PurpleConnection *connection,
+ const char *password)
+{
+ PurpleConnectionPrivate *priv = NULL;
+
+ g_return_if_fail(PURPLE_IS_CONNECTION(connection));
+
+ priv = purple_connection_get_instance_private(connection);
+
+ purple_str_wipe(priv->password);
+ priv->password = g_strdup(password);
+
+ g_object_notify_by_pspec(G_OBJECT(connection), properties[PROP_PASSWORD]);
+}
+
GSList *
purple_connection_get_active_chats(PurpleConnection *connection) {
PurpleConnectionPrivate *priv = NULL;
@@ -673,8 +689,8 @@
priv->account = g_value_get_object(value);
break;
case PROP_PASSWORD:
- g_free(priv->password);
- priv->password = g_value_dup_string(value);
+ purple_connection_set_password(connection,
+ g_value_get_string(value));
break;
case PROP_DISPLAY_NAME:
purple_connection_set_display_name(connection,
@@ -867,7 +883,7 @@
properties[PROP_PASSWORD] = g_param_spec_string(
"password", "Password",
"The password used for connection.", NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
properties[PROP_DISPLAY_NAME] = g_param_spec_string(
"display-name", "Display name",
--- a/libpurple/connection.h Fri Oct 28 01:52:28 2022 -0500
+++ b/libpurple/connection.h Fri Oct 28 03:42:47 2022 -0500
@@ -298,6 +298,23 @@
const char *purple_connection_get_password(PurpleConnection *gc);
/**
+ * purple_connection_set_password:
+ * @connection: The instance.
+ * @password: (nullable): The new password.
+ *
+ * Sets the password for @connection to @password.
+ *
+ * This will not change your password on the remote service. It just updates
+ * the password that the protocol should use when connecting.
+ *
+ * This is generally used by protocol plugins that support multiple
+ * authentication methods and need to prompt the user for a password.
+ *
+ * Since: 3.0.0
+ */
+void purple_connection_set_password(PurpleConnection *connection, const char *password);
+
+/**
* purple_connection_get_active_chats:
* @gc: The connection.
*
--- a/libpurple/protocols/jabber/auth.c Fri Oct 28 01:52:28 2022 -0500
+++ b/libpurple/protocols/jabber/auth.c Fri Oct 28 03:42:47 2022 -0500
@@ -108,7 +108,10 @@
NULL, NULL, NULL);
}
- /* Restart our connection */
+ /* Store the new password in our connection. */
+ purple_connection_set_password(gc, entry);
+
+ /* Restart our connection. */
jabber_auth_start_old(js);
}
@@ -122,6 +125,44 @@
purple_account_set_enabled(purple_connection_get_account(gc), FALSE);
}
+static void
+auth_old_read_pass_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_old_pass_cb),
+ G_CALLBACK(auth_no_pass_cb),
+ js->gc);
+
+ return;
+ }
+
+ /* Save the password in the connection. */
+ purple_connection_set_password(js->gc, password);
+ purple_str_wipe(password);
+
+ /* Restart the authentication process. */
+ jabber_auth_start_old(js);
+}
+
void
jabber_auth_start(JabberStream *js, PurpleXmlNode *packet)
{
@@ -369,7 +410,13 @@
*/
if (!purple_connection_get_password(js->gc)) {
- purple_account_request_password(account, G_CALLBACK(auth_old_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc);
+ PurpleCredentialManager *manager = NULL;
+
+ manager = purple_credential_manager_get_default();
+
+ purple_credential_manager_read_password_async(manager, account, NULL,
+ auth_old_read_pass_cb,
+ js);
return;
}
iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:auth");
--- a/libpurple/protocols/jabber/auth_cyrus.c Fri Oct 28 01:52:28 2022 -0500
+++ b/libpurple/protocols/jabber/auth_cyrus.c Fri Oct 28 03:42:47 2022 -0500
@@ -182,6 +182,45 @@
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))) {
@@ -254,7 +293,14 @@
*/
if (!js->sasl_password) {
- purple_account_request_password(account, G_CALLBACK(auth_pass_cb), G_CALLBACK(auth_no_pass_cb), js->gc);
+ 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