*/
#include "config.h"
+#include "empathy-sasl-mechanisms.h"
#include <libsoup/soup.h>
-#include <string.h>
+#include <tp-account-widgets/tpaw-utils.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
#define DEBUG_FLAG EMPATHY_DEBUG_SASL
#include "empathy-debug.h"
#include "empathy-utils.h"
-#include "empathy-sasl-mechanisms.h"
#define MECH_FACEBOOK "X-FACEBOOK-PLATFORM"
#define MECH_WLM "X-MESSENGER-OAUTH2"
#define MECH_GOOGLE "X-OAUTH2"
+#define MECH_PASSWORD "X-TELEPATHY-PASSWORD"
typedef struct
{
{ EMPATHY_SASL_MECHANISM_FACEBOOK, MECH_FACEBOOK },
{ EMPATHY_SASL_MECHANISM_WLM, MECH_WLM },
{ EMPATHY_SASL_MECHANISM_GOOGLE, MECH_GOOGLE },
+
+ /* Must be the last one, otherwise empathy_sasl_channel_select_mechanism()
+ * will prefer password over web auth for servers supporting both. */
+ { EMPATHY_SASL_MECHANISM_PASSWORD, MECH_PASSWORD }
};
static void
GSimpleAsyncResult *result = user_data;
FacebookData *data;
GHashTable *h;
- GHashTable *params;
- gchar *response;
+ GString *response_string;
GArray *response_array;
DEBUG ("new challenge: %s", challenge->data);
h = soup_form_decode (challenge->data);
- /* See https://developers.facebook.com/docs/chat/#platauth */
- params = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (params, "method", g_hash_table_lookup (h, "method"));
- g_hash_table_insert (params, "nonce", g_hash_table_lookup (h, "nonce"));
- g_hash_table_insert (params, "access_token", data->access_token);
- g_hash_table_insert (params, "api_key", data->client_id);
- g_hash_table_insert (params, "call_id", "0");
- g_hash_table_insert (params, "v", "1.0");
-
- response = soup_form_encode_hash (params);
- DEBUG ("Response: %s", response);
+ /* See https://developers.facebook.com/docs/chat/#platauth.
+ * We don't use soup_form_encode() here because it would escape parameters
+ * and facebook server is not expecting that and would reject the response. */
+ response_string = g_string_new ("v=1.0&call_id=0");
+ g_string_append (response_string, "&access_token=");
+ g_string_append_uri_escaped (response_string, data->access_token, NULL, TRUE);
+ g_string_append (response_string, "&api_key=");
+ g_string_append_uri_escaped (response_string, data->client_id, NULL, TRUE);
+ g_string_append (response_string, "&method=");
+ g_string_append_uri_escaped (response_string, g_hash_table_lookup (h, "method"), NULL, TRUE);
+ g_string_append (response_string, "&nonce=");
+ g_string_append_uri_escaped (response_string, g_hash_table_lookup (h, "nonce"), NULL, TRUE);
+
+ DEBUG ("Response: %s", response_string->str);
response_array = g_array_new (FALSE, FALSE, sizeof (gchar));
- g_array_append_vals (response_array, response, strlen (response));
+ g_array_append_vals (response_array, response_string->str, response_string->len);
tp_cli_channel_interface_sasl_authentication_call_respond (data->channel, -1,
response_array, generic_cb, g_object_ref (result), g_object_unref, NULL);
g_hash_table_unref (h);
- g_hash_table_unref (params);
- g_free (response);
+ g_string_free (response_string, TRUE);
g_array_unref (response_array);
}
g_object_unref (result);
}
+void
+empathy_sasl_auth_password_async (TpChannel *channel,
+ const gchar *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ GArray *password_array;
+
+ result = empathy_sasl_auth_common_async (channel, callback, user_data);
+
+ g_return_if_fail (result != NULL);
+ g_return_if_fail (empathy_sasl_channel_supports_mechanism (channel,
+ MECH_PASSWORD));
+ g_return_if_fail (!tp_str_empty (password));
+
+ DEBUG ("Start %s mechanism", MECH_PASSWORD);
+
+ password_array = g_array_sized_new (FALSE, FALSE, sizeof (gchar),
+ strlen (password));
+ g_array_append_vals (password_array, password, strlen (password));
+
+ tp_cli_channel_interface_sasl_authentication_call_start_mechanism_with_data (
+ channel, -1, MECH_PASSWORD, password_array,
+ generic_cb, g_object_ref (result), g_object_unref, NULL);
+
+ g_array_unref (password_array);
+ g_object_unref (result);
+}
+
gboolean
empathy_sasl_auth_finish (TpChannel *channel,
GAsyncResult *result,
GError **error)
{
- empathy_implement_finish_void (channel, empathy_sasl_auth_common_async);
+ tpaw_implement_finish_void (channel, empathy_sasl_auth_common_async);
}
gboolean
empathy_sasl_channel_supports_mechanism (TpChannel *channel,
const gchar *mechanism)
{
- GHashTable *props;
- const gchar * const *available_mechanisms;
+ GVariant *props;
+ GStrv available_mechanisms;
+ gboolean result;
- props = tp_channel_borrow_immutable_properties (channel);
- available_mechanisms = tp_asv_get_boxed (props,
+ props = tp_channel_dup_immutable_properties (channel);
+
+ g_variant_lookup (props,
TP_PROP_CHANNEL_INTERFACE_SASL_AUTHENTICATION_AVAILABLE_MECHANISMS,
- G_TYPE_STRV);
+ "^as", &available_mechanisms);
+
+ result = tp_strv_contains ((const gchar * const *) available_mechanisms,
+ mechanism);
- return tp_strv_contains (available_mechanisms, mechanism);
+ g_variant_unref (props);
+ g_strfreev (available_mechanisms);
+ return result;
}
EmpathySaslMechanism