summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2006-09-21 18:06:02 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2006-09-21 18:06:02 +0000
commit9d4c5f5c593a8cb8fdba6fe2992ee60d0888014a (patch)
tree4adf686cf0424f03fa8253be9dc2ebc96b2bc5fa
parentc75170e0e99d1053ee204418a835aeede6bac5d6 (diff)
downloadtelepathy-gabble-9d4c5f5c593a8cb8fdba6fe2992ee60d0888014a.tar.gz
gabble-register.c: Implement Nokia IV authorisation mechanism
20060921180602-53eee-544e863217841e583b0ab30796d94884902b27dc.gz
-rw-r--r--src/gabble-register.c187
1 files changed, 186 insertions, 1 deletions
diff --git a/src/gabble-register.c b/src/gabble-register.c
index e8ecc9044..668bd0f07 100644
--- a/src/gabble-register.c
+++ b/src/gabble-register.c
@@ -36,6 +36,10 @@
#include "gabble-register-signals-marshal.h"
#include "namespaces.h"
#include "util.h"
+#include "libmd5-rfc/md5.h"
+
+#define NS_NOKIA_IV "about:placeholder-xmlns-for-nokia-iv"
+#define AUTH_TYPE_NOKIA_IV "nokia-iv"
/* signal enum */
enum
@@ -191,12 +195,161 @@ gabble_register_new (GabbleConnection *conn)
}
static LmHandlerResult
+nokia_iv_set_reply_cb (GabbleConnection *conn,
+ LmMessage *sent_msg,
+ LmMessage *reply_msg,
+ GObject *object,
+ gpointer user_data)
+{
+ if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
+ {
+ LmMessageNode *node;
+ gint code = NotAvailable;
+ GString *msg;
+
+ msg = g_string_sized_new (30);
+ g_string_append (msg, "Request failed");
+
+ node = lm_message_node_get_child (reply_msg->node, "error");
+ if (node)
+ {
+ GabbleXmppError error;
+
+ error = gabble_xmpp_error_from_node (node);
+
+ if (error != INVALID_XMPP_ERROR)
+ {
+ g_string_append_printf (msg, ": %s",
+ gabble_xmpp_error_string (error));
+ }
+ }
+
+ g_signal_emit (object, signals[FINISHED], 0, FALSE, code, msg->str);
+ g_string_free (msg, TRUE);
+ }
+ else
+ {
+ g_signal_emit (object, signals[FINISHED], 0, TRUE, -1, NULL);
+ }
+
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+}
+
+static LmHandlerResult
+nokia_iv_get_reply_cb (GabbleConnection *conn,
+ LmMessage *sent_msg,
+ LmMessage *reply_msg,
+ GObject *object,
+ gpointer user_data)
+{
+ GabbleRegister *reg = GABBLE_REGISTER (object);
+ GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (reg);
+ GError *error = NULL;
+ gint err_code = -1;
+ const gchar *err_msg = NULL;
+ LmMessage *msg = NULL;
+ LmMessageNode *query_node, *challenge_node;
+ gchar *auth_identity, *auth_secret;
+ const gchar *challenge;
+ gchar response[33];
+ gint i;
+ md5_byte_t digest[16];
+ md5_state_t calculator;
+ static const char *xdigits = "0123456789abcdef";
+
+ if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
+ {
+ /* We tried, but the server doesn't seem to support it. Never mind,
+ let's try to log in anyway and see what happens. */
+ g_signal_emit (object, signals[FINISHED], 0, TRUE, -1, NULL);
+ goto OUT;
+ }
+
+ /* sanity check the reply to some degree ... */
+ query_node = lm_message_node_get_child_with_namespace (reply_msg->node,
+ "query", NS_NOKIA_IV);
+
+ if (query_node == NULL)
+ goto ERROR_MALFORMED_REPLY;
+
+ challenge_node = lm_message_node_get_child (query_node, "challenge");
+ if (!challenge_node)
+ goto ERROR_MALFORMED_REPLY;
+ challenge = lm_message_node_get_value(challenge_node);
+ if (!challenge)
+ goto ERROR_MALFORMED_REPLY;
+
+ /* craft a reply */
+ msg = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
+ LM_MESSAGE_SUB_TYPE_SET);
+
+ query_node = lm_message_node_add_child (msg->node, "query", NULL);
+ lm_message_node_set_attribute (query_node, "xmlns", NS_NOKIA_IV);
+
+ g_object_get (priv->conn,
+ "auth-identity", &auth_identity,
+ "auth-secret", &auth_secret,
+ NULL);
+
+ md5_init(&calculator);
+ md5_append(&calculator, (const md5_byte_t *)auth_secret,
+ strlen(auth_secret));
+ md5_append(&calculator, (const md5_byte_t *)":", 1);
+ md5_append(&calculator, (const md5_byte_t *)challenge, strlen(challenge));
+ md5_finish(&calculator, digest);
+
+ for (i = 0; i < 16; i++)
+ {
+ response[i*2] = xdigits[(digest[i] >> 4) & 0xf];
+ response[i*2+1] = xdigits[digest[i] & 0xf];
+ }
+ response[32] = '\0';
+
+ lm_message_node_add_child (query_node, "mac", auth_identity);
+ lm_message_node_add_child (query_node, "response", response);
+
+ g_free (auth_identity);
+ g_free (auth_secret);
+
+ if (!_gabble_connection_send_with_reply (priv->conn, msg,
+ nokia_iv_set_reply_cb,
+ G_OBJECT (reg), NULL, &error))
+ {
+ err_code = error->code;
+ err_msg = error->message;
+ }
+
+ goto OUT;
+
+ERROR_MALFORMED_REPLY:
+ err_code = NotAvailable;
+ err_msg = "Malformed reply";
+
+OUT:
+ if (err_code != -1)
+ {
+ g_signal_emit (reg, signals[FINISHED], 0, FALSE, err_code, err_msg);
+ }
+
+ if (msg)
+ lm_message_unref (msg);
+
+ if (error)
+ g_error_free (error);
+
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+}
+
+static LmHandlerResult
set_reply_cb (GabbleConnection *conn,
LmMessage *sent_msg,
LmMessage *reply_msg,
GObject *object,
gpointer user_data)
{
+ GabbleRegister *reg = GABBLE_REGISTER (object);
+ GabbleRegisterPrivate *priv = GABBLE_REGISTER_GET_PRIVATE (reg);
+
if (lm_message_get_sub_type (reply_msg) != LM_MESSAGE_SUB_TYPE_RESULT)
{
LmMessageNode *node;
@@ -229,7 +382,39 @@ set_reply_cb (GabbleConnection *conn,
}
else
{
- g_signal_emit (object, signals[FINISHED], 0, TRUE, -1, NULL);
+ gchar *auth_type;
+
+ g_object_get (priv->conn, "auth-type", &auth_type, NULL);
+
+ if (auth_type && !g_strdiff(auth_type, AUTH_TYPE_NOKIA_IV))
+ {
+ LmMessage *msg;
+ LmMessageNode *node;
+ GError *error;
+
+ msg = lm_message_new_with_sub_type (NULL, LM_MESSAGE_TYPE_IQ,
+ LM_MESSAGE_SUB_TYPE_GET);
+
+ node = lm_message_node_add_child (msg->node, "query", NULL);
+ lm_message_node_set_attribute (node, "xmlns", NS_NOKIA_IV);
+
+ if (!_gabble_connection_send_with_reply (priv->conn, msg,
+ nokia_iv_get_reply_cb,
+ G_OBJECT (reg), NULL,
+ &error))
+ {
+ g_signal_emit (reg, signals[FINISHED], 0, FALSE, error->code,
+ error->message);
+ g_error_free (error);
+ }
+ }
+ else
+ {
+ /* We don't have the necessary info, so let's hope it's not
+ necessary */
+ g_signal_emit (object, signals[FINISHED], 0, TRUE, -1, NULL);
+ }
+ g_free(auth_type);
}
return LM_HANDLER_RESULT_REMOVE_MESSAGE;