/pidgin/main: bc833d6d81a2: Merged in kakaroto/main/release-2.x....

Gary Kramlich <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: bc833d6d81a2889dfcaafb7496a8ed14a56f9da1
Author:	 Gary Kramlich <[email protected]>
Date:	 2016-06-16 15:23 -0500
Branch:	 release-2.x.y
URL: https://hg.pidgin.im/pidgin/main/rev/bc833d6d81a2

Description:

Merged in kakaroto/main/release-2.x.y (pull request #70)

Release 2.x.y

diffstat:

 ChangeLog                               |    3 +
 libpurple/protocols/oscar/Makefile.am   |    1 +
 libpurple/protocols/oscar/kerberos.c    |  441 ++++++++++++++++++++++++++++++++
 libpurple/protocols/oscar/oscar.c       |   94 ++++++-
 libpurple/protocols/oscar/oscar.h       |    5 +
 libpurple/protocols/oscar/oscarcommon.h |    9 +-
 libpurple/util.c                        |   18 +-
 libpurple/util.h                        |   26 +
 8 files changed, 585 insertions(+), 12 deletions(-)

diffs (truncated from 783 to 300 lines):

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,9 @@ version 2.10.13 (MM/DD/YY):
 	don't support rich text
 	* Fix a potential crash while exiting pidgin
 
+	AIM:
+	* Add support for the newer kerberos-based authentication of AIM 8.x
+
 	Windows-Specific Changes:
 	* Use getaddrinfo for DNS to enable IPv6 (#1075)
 
diff --git a/libpurple/protocols/oscar/Makefile.am b/libpurple/protocols/oscar/Makefile.am
--- a/libpurple/protocols/oscar/Makefile.am
+++ b/libpurple/protocols/oscar/Makefile.am
@@ -9,6 +9,7 @@ OSCARSOURCES = \
 	authorization.c     \
 	bstream.c           \
 	clientlogin.c       \
+	kerberos.c          \
 	encoding.c          \
 	encoding.h          \
 	family_admin.c      \
diff --git a/libpurple/protocols/oscar/kerberos.c b/libpurple/protocols/oscar/kerberos.c
new file mode 100644
--- /dev/null
+++ b/libpurple/protocols/oscar/kerberos.c
@@ -0,0 +1,441 @@
+/*
+ * Purple's oscar protocol plugin
+ * This file is the legal property of its developers.
+ * Please see the AUTHORS file distributed alongside this file.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+*/
+
+/**
+ * This file implements AIM's kerberos procedure for authenticating
+ * users.  This replaces the older MD5-based and XOR-based
+ * authentication methods that use SNAC family 0x0017.
+ *
+ * This doesn't use SNACs or FLAPs at all.  It makes https
+ * POSTs to AOL KDC server to validate the user based on the password they
+ * provided to us.  Upon successful authentication we receive two tokens
+ * in the response. One is assumed to be the kerberos ticket for authentication
+ * on the various AOL websites, while the other contains BOSS information, such
+ * as the hostname and port number to use, the TLS certificate name as well as
+ * the cookie to use to authenticate to the BOS server.
+ * And then everything else is the same as with BUCP.
+ *
+ */
+
+#include "oscar.h"
+#include "oscarcommon.h"
+#include "core.h"
+
+#define MAXAIMPASSLEN 16
+
+/*
+ * Incomplete X-SNAC format taken from reverse engineering doen by digsby:
+ * https://github.com/ifwe/digsby/blob/master/digsby/src/oscar/login2.py
+ */
+typedef struct {
+	aim_tlv_t *main_tlv;
+	gchar *principal1;
+	gchar *service;
+	gchar *principal1_again;
+	gchar *principal2;
+	gchar unknown;
+	guint8 *footer;
+	struct {
+		guint32 unknown1;
+		guint32 unknown2;
+		guint32 epoch_now;
+		guint32 epoch_valid;
+		guint32 epoch_renew;
+		guint32 epoch_expire;
+		guint32 unknown3;
+		guint32 unknown4;
+		guint32 unknown5;
+	} dates;
+	GSList *tlvlist;
+} aim_xsnac_token_t;
+
+typedef struct {
+	guint16 family;
+	guint16 subtype;
+	guint8 flags[8];
+	guint16 request_id;
+	guint32 epoch;
+	guint32 unknown;
+	gchar *principal1;
+	gchar *principal2;
+	guint16 num_tokens;
+	aim_xsnac_token_t *tokens;
+	GSList *tlvlist;
+} aim_xsnac_t;
+
+static gchar *get_kdc_url(OscarData *od)
+{
+	PurpleAccount *account = purple_connection_get_account(od->gc);
+	const gchar *server;
+	gchar *url;
+	gchar *port_str = NULL;
+	gint port;
+
+	server = purple_account_get_string(account, "server", AIM_DEFAULT_KDC_SERVER);
+	port = purple_account_get_int(account, "port", AIM_DEFAULT_KDC_PORT);
+	if (port != 443)
+		port_str = g_strdup_printf(":%d", port);
+	url = g_strdup_printf("https://%s%s/", server, port_str ? port_str : "");
+	g_free(port_str);
+
+	return url;
+}
+
+/*
+ * Using kerberos auth requires a developer ID. This key is for libpurple.
+ * It is the default key for all libpurple-based clients.  AOL encourages
+ * UIs (especially ones with lots of users) to override this with their
+ * own key.  This key is owned by the AIM account "markdoliner"
+ *
+ * Keys can be managed at http://developer.aim.com/manageKeys.jsp
+ */
+#define DEFAULT_CLIENT_KEY "ma15d7JTxbmVG-RP"
+
+static const char *get_client_key(OscarData *od)
+{
+	return oscar_get_ui_info_string(
+			od->icq ? "prpl-icq-clientkey" : "prpl-aim-clientkey",
+			DEFAULT_CLIENT_KEY);
+}
+
+static void
+aim_encode_password(const char *password, gchar *encoded)
+{
+	guint8 encoding_table[] = {
+		0x76, 0x91, 0xc5, 0xe7,
+		0xd0, 0xd9, 0x95, 0xdd,
+		0x9e, 0x2F, 0xea, 0xd8,
+		0x6B, 0x21, 0xc2, 0xbc,
+
+	};
+	guint i;
+
+	/*
+	 * We truncate AIM passwords to 16 characters since that's what
+	 * the official client does as well.
+	 */
+	for (i = 0; i < strlen(password) && i < MAXAIMPASSLEN; i++)
+		encoded[i] = (password[i] ^ encoding_table[i]);
+}
+
+static void
+aim_xsnac_free(aim_xsnac_t *xsnac)
+{
+	gint i;
+
+	g_free(xsnac->principal1);
+	g_free(xsnac->principal2);
+	aim_tlvlist_free(xsnac->tlvlist);
+
+	for (i = 0; i < xsnac->num_tokens; i++) {
+		g_free(xsnac->tokens[i].main_tlv->value);
+		g_free(xsnac->tokens[i].main_tlv);
+		g_free(xsnac->tokens[i].principal1);
+		g_free(xsnac->tokens[i].service);
+		g_free(xsnac->tokens[i].principal1_again);
+		g_free(xsnac->tokens[i].principal2);
+		g_free(xsnac->tokens[i].footer);
+		aim_tlvlist_free(xsnac->tokens[i].tlvlist);
+	}
+	g_free(xsnac->tokens);
+}
+
+static void
+kerberos_login_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+	const gchar *got_data, gsize got_len, const gchar *error_message)
+{
+	OscarData *od = user_data;
+	PurpleConnection *gc;
+	ByteStream bs;
+	aim_xsnac_t xsnac = {0};
+	guint16 len;
+	gchar *bosip = NULL;
+	gchar *tlsCertName = NULL;
+	guint8 *cookie = NULL;
+	guint32 cookie_len = 0;
+	char *host; int port;
+	gsize i;
+
+	gc = od->gc;
+
+	od->url_data = NULL;
+
+	if (error_message != NULL || got_len == 0) {
+		gchar *tmp;
+		gchar *url;
+
+		url = get_kdc_url(od);
+		tmp = g_strdup_printf(_("Error requesting %s: %s"),
+				url, error_message ?
+				error_message : _("The server returned an empty response"));
+		purple_connection_error_reason(gc,
+				PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		g_free(tmp);
+		g_free(url);
+		return;
+	}
+
+	purple_debug_info("oscar", "Received kerberos login HTTP response %lu : ", got_len);
+
+	byte_stream_init(&bs, (guint8 *)got_data, got_len);
+
+	xsnac.family = byte_stream_get16(&bs);
+	xsnac.subtype = byte_stream_get16(&bs);
+	byte_stream_getrawbuf(&bs, (guint8 *) xsnac.flags, 8);
+
+	if (xsnac.family == 0x50C && xsnac.subtype == 0x0005) {
+		purple_connection_error_reason(gc,
+			PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+			_("Incorrect password"));
+		return;
+	}
+	if (xsnac.family != 0x50C || xsnac.subtype != 0x0003) {
+		purple_connection_error_reason(gc,
+				PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			_("Error parsing response from authentication server"));
+		return;
+	}
+	xsnac.request_id = byte_stream_get16(&bs);
+	xsnac.epoch = byte_stream_get32(&bs);
+	xsnac.unknown = byte_stream_get32(&bs);
+	len = byte_stream_get16(&bs);
+	xsnac.principal1 = byte_stream_getstr(&bs, len);
+	len = byte_stream_get16(&bs);
+	xsnac.principal2 = byte_stream_getstr(&bs, len);
+	xsnac.num_tokens = byte_stream_get16(&bs);
+
+	purple_debug_info("oscar", "KDC: %d tokens between '%s' and '%s'\n",
+		xsnac.num_tokens, xsnac.principal1, xsnac.principal2);
+	xsnac.tokens = g_new0(aim_xsnac_token_t, xsnac.num_tokens);
+	for (i = 0; i < xsnac.num_tokens; i++) {
+		GSList *tlv;
+
+		tlv = aim_tlvlist_readnum(&bs, 1);
+		if (tlv)
+			xsnac.tokens[i].main_tlv = tlv->data;
+		g_slist_free(tlv);
+
+		len = byte_stream_get16(&bs);
+		xsnac.tokens[i].principal1 = byte_stream_getstr(&bs, len);
+		len = byte_stream_get16(&bs);
+		xsnac.tokens[i].service = byte_stream_getstr(&bs, len);
+		len = byte_stream_get16(&bs);
+		xsnac.tokens[i].principal1_again = byte_stream_getstr(&bs, len);
+		len = byte_stream_get16(&bs);
+		xsnac.tokens[i].principal2 = byte_stream_getstr(&bs, len);
+		xsnac.tokens[i].unknown = byte_stream_get8(&bs);
+		len = byte_stream_get16(&bs);
+		xsnac.tokens[i].footer = byte_stream_getraw(&bs, len);
+
+		xsnac.tokens[i].dates.unknown1 = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.unknown2 = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.epoch_now = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.epoch_valid = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.epoch_renew = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.epoch_expire = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.unknown3 = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.unknown4 = byte_stream_get32(&bs);
+		xsnac.tokens[i].dates.unknown5 = byte_stream_get32(&bs);
+
+		len = byte_stream_get16(&bs);
+		xsnac.tokens[i].tlvlist = aim_tlvlist_readnum(&bs, len);
+
+		purple_debug_info("oscar", "Token %lu has %d TLVs for service '%s'\n",
+			i, len, xsnac.tokens[i].service);
+	}
+	len = byte_stream_get16(&bs);
+	xsnac.tlvlist = aim_tlvlist_readnum(&bs, len);
+
+	for (i = 0; i < xsnac.num_tokens; i++) {
+		if (purple_strequal(xsnac.tokens[i].service, "im/boss")) {
+			aim_tlv_t *tlv;
+			GSList *tlvlist;
+			ByteStream tbs;
+

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.