/pidgin/main: bf8ed95aaa1c: Merged in kakaroto/main/oscar_auth (...
Gary Kramlich <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: bf8ed95aaa1c438bc042f249a8d420069c2c9eaf Author: Gary Kramlich <[email protected]> Date: 2016-06-17 18:11 -0500 Branch: default URL: https://hg.pidgin.im/pidgin/main/rev/bf8ed95aaa1c Description: Merged in kakaroto/main/oscar_auth (pull request #69) Adding Oscar kerberos authentication (AIM 6.x and 7.x) diffstat: ChangeLog | 3 + libpurple/protocols/oscar/Makefile.am | 1 + libpurple/protocols/oscar/aim.c | 9 +- libpurple/protocols/oscar/icq.c | 7 +- libpurple/protocols/oscar/kerberos.c | 436 ++++++++++++++++++++++++++++++++ libpurple/protocols/oscar/oscar.c | 110 +++++++- libpurple/protocols/oscar/oscar.h | 8 +- libpurple/protocols/oscar/oscarcommon.h | 9 +- 8 files changed, 556 insertions(+), 27 deletions(-) diffs (truncated from 765 to 300 lines): diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -83,6 +83,9 @@ version 3.0.0 (??/??/????): * Support file transfers up to ~9 EiB. * Invalid user moods can no longer be sent to the server. + AIM: + * Add support for the newer kerberos-based authentication of AIM 8.x + Plugins: * A new plugin API has been introduced. Plugins are no longer required to be of a predefined type (such as protocol, standard, loader etc), 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 @@ -11,6 +11,7 @@ OSCARSOURCES = \ aim.h \ bstream.c \ clientlogin.c \ + kerberos.c \ encoding.c \ encoding.h \ family_admin.c \ diff --git a/libpurple/protocols/oscar/aim.c b/libpurple/protocols/oscar/aim.c --- a/libpurple/protocols/oscar/aim.c +++ b/libpurple/protocols/oscar/aim.c @@ -36,14 +36,7 @@ aim_protocol_init(PurpleProtocol *protoc protocol->id = "prpl-aim"; protocol->name = "AIM"; - oscar_init_account_options(protocol); - - option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins", - OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("Server"), "server", oscar_get_login_server(FALSE, TRUE)); - protocol->account_options = g_list_append(protocol->account_options, option); + oscar_init_account_options(protocol, FALSE); } static void diff --git a/libpurple/protocols/oscar/icq.c b/libpurple/protocols/oscar/icq.c --- a/libpurple/protocols/oscar/icq.c +++ b/libpurple/protocols/oscar/icq.c @@ -52,13 +52,8 @@ icq_protocol_init(PurpleProtocol *protoc protocol->id = "prpl-icq"; protocol->name = "ICQ"; - oscar_init_account_options(protocol); + oscar_init_account_options(protocol, TRUE); - option = purple_account_option_string_new(_("Server"), "server", oscar_get_login_server(TRUE, TRUE)); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); - protocol->account_options = g_list_append(protocol->account_options, option); } static void 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,436 @@ +/* + * 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(PurpleHttpConnection *http_conn, + PurpleHttpResponse *response, gpointer _od) +{ + OscarData *od = _od; + PurpleConnection *gc; + const gchar *got_data; + size_t got_len; + 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->hc = NULL; + + if (!purple_http_response_is_successful(response)) { + gchar *tmp; + gchar *url; + + url = get_kdc_url(od); + tmp = g_strdup_printf(_("Error requesting %s: %s"), + url, + purple_http_response_get_error(response)); + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + g_free(tmp); + g_free(url); + return; + } + + got_data = purple_http_response_get_data(response, &got_len); + 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(gc, + PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, + _("Incorrect password")); + return; + } + if (xsnac.family != 0x50C || xsnac.subtype != 0x0003) { + purple_connection_error(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) _______________________________________________ Commits mailing list [email protected] https://pidgin.im/cgi-bin/mailman/listinfo/commits