im.pidgin.pidgin.khc.msnp15: b0c629c93a639eddf8a8fcc3e16b33d21217d1f4
quantum.analyst at gmail.com
quantum.analyst at gmail.com
Fri Dec 28 02:21:24 EST 2007
-----------------------------------------------------------------
Revision: b0c629c93a639eddf8a8fcc3e16b33d21217d1f4
Ancestor: a13ab86228a43d576c769fe321ba1375c7e4cab8
Author: quantum.analyst at gmail.com
Date: 2007-12-26T00:34:12
Branch: im.pidgin.pidgin.khc.msnp15
Modified files:
libpurple/protocols/msn/nexus.c
libpurple/protocols/msn/nexus.h
libpurple/protocols/msn/notification.c
ChangeLog:
Patch 2 from Qulogic, this one adds SSO authentication
-------------- next part --------------
============================================================
--- libpurple/protocols/msn/nexus.c 2a84e972ed3df60af3b4a0f0106b750c1f1ee56f
+++ libpurple/protocols/msn/nexus.c 3b601281b1115522e49740ab3136c1f05216ba6b
@@ -26,9 +26,26 @@
#include "nexus.h"
#include "notification.h"
-#undef NEXUS_LOGIN_TWN
/**************************************************************************
+ * Valid Ticket Tokens
+ **************************************************************************/
+
+#define SSO_VALID_TICKET_DOMAIN 0
+#define SSO_VALID_TICKET_POLICY 1
+static char *ticket_domains[][2] = {
+ /* http://msnpiki.msnfanatic.com/index.php/MSNP15:SSO */
+ /* {"Domain", "Policy Ref URI"}, Purpose */
+ {"messengerclear.live.com", NULL}, /* Authentication for messenger. */
+ {"messenger.msn.com", "?id=507"}, /* Messenger website authentication. */
+ {"contacts.msn.com", "MBI"}, /* Authentication for the Contact server. */
+ {"messengersecure.live.com", "MBI_SSL"}, /* Unknown */
+ {"spaces.live.com", "MBI"}, /* Authentication for the Windows Live Spaces */
+ {"livecontacts.live.com", "MBI"}, /* Live Contacts API, a simplified version of the Contacts SOAP service */
+ {"storage.live.com", "MBI"}, /* Storage REST API */
+};
+
+/**************************************************************************
* Main
**************************************************************************/
@@ -36,60 +53,216 @@ msn_nexus_new(MsnSession *session)
msn_nexus_new(MsnSession *session)
{
MsnNexus *nexus;
+ int i;
nexus = g_new0(MsnNexus, 1);
nexus->session = session;
- nexus->challenge_data = g_hash_table_new_full(g_str_hash,
- g_str_equal, g_free, g_free);
+ nexus->token_len = sizeof(ticket_domains) / sizeof(char *[2]);
+ nexus->tokens = g_malloc(sizeof(MsnTicketToken) * nexus->token_len);
+ for (i = 0; i < nexus->token_len; i++)
+ nexus->tokens[i].token = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, g_free);
+
return nexus;
}
void
msn_nexus_destroy(MsnNexus *nexus)
{
- if (nexus->challenge_data != NULL)
- g_hash_table_destroy(nexus->challenge_data);
+ int i;
+ for (i = 0; i < nexus->token_len; i++) {
+ g_hash_table_destroy(nexus->tokens[i].token);
+ g_free(nexus->tokens[i].secret);
+ }
+ g_free(nexus->tokens);
+ g_free(nexus->policy);
+ g_free(nexus->nonce);
g_free(nexus);
}
/**************************************************************************
+ * RPS/SSO Authentication
+ **************************************************************************/
+
+static char *
+sha1_hmac(const char *key, int key_len, const char *message, int msg_len)
+{
+ PurpleCipherContext *context;
+ char *result;
+ gboolean ret;
+
+ context = purple_cipher_context_new_by_name("hmac", NULL);
+ purple_cipher_context_set_option(context, "hash", "sha1");
+ purple_cipher_context_set_key_with_len(context, (guchar *)key, key_len);
+
+ purple_cipher_context_append(context, (guchar *)message, msg_len);
+ result = g_malloc(20);
+ ret = purple_cipher_context_digest(context, 20, (guchar *)result, NULL);
+
+ purple_cipher_context_destroy(context);
+
+ return result;
+}
+
+static char *
+rps_create_key(const char *key, int key_len, const char *data, size_t data_len)
+{
+ char *hash1, *hash2, *hash3, *hash4;
+ char *result;
+
+ hash1 = sha1_hmac(key, key_len, data, data_len);
+ hash1 = g_realloc(hash1, 20 + data_len);
+ memcpy(hash1 + 20, data, data_len);
+ hash2 = sha1_hmac(key, key_len, hash1, 20 + data_len);
+
+ hash3 = sha1_hmac(key, key_len, hash1, 20);
+
+ hash3 = g_realloc(hash3, 20 + data_len);
+ memcpy(hash3 + 20, data, data_len);
+ hash4 = sha1_hmac(key, key_len, hash3, 20 + data_len);
+
+ result = g_malloc(24);
+ memcpy(result, hash2, 20);
+ memcpy(result + 20, hash4, 4);
+
+ g_free(hash1);
+ g_free(hash2);
+ g_free(hash3);
+ g_free(hash4);
+
+ return result;
+}
+
+static char *
+des3_cbc(const char *key, const char *iv, const char *data, int len)
+{
+ PurpleCipherContext *des3;
+ char *out;
+ size_t outlen;
+
+ des3 = purple_cipher_context_new_by_name("des3", NULL);
+ purple_cipher_context_set_key(des3, (guchar *)key);
+ purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC);
+ purple_cipher_context_set_iv(des3, (guchar *)iv, 8);
+
+ out = g_malloc(len);
+ purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, &outlen);
+
+ purple_cipher_context_destroy(des3);
+
+ return out;
+}
+
+#define CRYPT_MODE_CBC 1
+#define CIPHER_TRIPLE_DES 0x6603
+#define HASH_SHA1 0x8004
+static char *
+msn_rps_encrypt(MsnNexus *nexus)
+{
+ MsnUsrKey *usr_key;
+ const char *magic1 = "WS-SecureConversationSESSION KEY HASH";
+ const char *magic2 = "WS-SecureConversationSESSION KEY ENCRYPTION";
+ size_t len;
+ char *hash;
+ char *key1, *key2, *key3;
+ gsize key1_len;
+ char *nonce_fixed;
+ char *cipher;
+ char *response;
+
+ usr_key = g_malloc(sizeof(MsnUsrKey));
+ usr_key->size = GUINT32_TO_LE(28);
+ usr_key->crypt_mode = GUINT32_TO_LE(CRYPT_MODE_CBC);
+ usr_key->cipher_type = GUINT32_TO_LE(CIPHER_TRIPLE_DES);
+ usr_key->hash_type = GUINT32_TO_LE(HASH_SHA1);
+ usr_key->iv_len = GUINT32_TO_LE(8);
+ usr_key->hash_len = GUINT32_TO_LE(20);
+ usr_key->cipher_len = GUINT32_TO_LE(72);
+
+ key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len);
+ len = strlen(magic1);
+ key2 = rps_create_key(key1, key1_len, magic1, len);
+ len = strlen(magic2);
+ key3 = rps_create_key(key1, key1_len, magic2, len);
+
+ usr_key->iv[0] = 0x46; //rand() % 256;
+ usr_key->iv[1] = 0xC4;
+ usr_key->iv[2] = 0x14;
+ usr_key->iv[3] = 0x9F;
+ usr_key->iv[4] = 0xFF;
+ usr_key->iv[5] = 0xFC;
+ usr_key->iv[6] = 0x91;
+ usr_key->iv[7] = 0x61;
+
+ len = strlen(nexus->nonce);
+ hash = sha1_hmac(key2, 24, nexus->nonce, len);
+
+ /* We need to pad this to 72 bytes, apparently */
+ nonce_fixed = g_malloc(len + 8);
+ memcpy(nonce_fixed, nexus->nonce, len);
+ memset(nonce_fixed + len, 0x08, 8);
+ cipher = des3_cbc(key3, usr_key->iv, nonce_fixed, len + 8);
+ g_free(nonce_fixed);
+
+ memcpy(usr_key->hash, hash, 20);
+ memcpy(usr_key->cipher, cipher, 72);
+
+ g_free(key1);
+ g_free(key2);
+ g_free(key3);
+ g_free(hash);
+ g_free(cipher);
+
+ response = purple_base64_encode((guchar *)usr_key, sizeof(MsnUsrKey));
+
+ g_free(usr_key);
+
+ return response;
+}
+
+/**************************************************************************
* Login
**************************************************************************/
-static void
-nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+static gboolean
+nexus_parse_response(MsnNexus *nexus, xmlnode *xml)
{
- MsnNexus *nexus = data;
- MsnSession *session = nexus->session;
xmlnode *node;
+ gboolean result = FALSE;
- if (resp == NULL) {
- msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect"));
- return;
- }
+ node = msn_soap_xml_get(xml, "Body/RequestSecurityTokenResponseCollection/RequestSecurityTokenResponse");
- node = msn_soap_xml_get(resp->xml, "Body/"
- "RequestSecurityTokenResponseCollection/RequestSecurityTokenResponse");
+ if (node)
+ node = node->next; /* The first one is not useful */
+ else
+ return FALSE;
for (; node; node = node->next) {
- xmlnode *token = msn_soap_xml_get(node,
- "RequestedSecurityToken/BinarySecurityToken");
+ xmlnode *token = msn_soap_xml_get(node, "RequestedSecurityToken/BinarySecurityToken");
+ xmlnode *secret = msn_soap_xml_get(node, "RequestedProofToken/BinarySecret");
+ xmlnode *expires = msn_soap_xml_get(node, "LifeTime/Expires");
if (token) {
char *token_str = xmlnode_get_data(token);
+ const char *id_str = xmlnode_get_attrib(token, "Id");
char **elems, **cur, **tokens;
- char *msn_twn_t, *msn_twn_p, *cert_str;
+ int id;
if (token_str == NULL) continue;
+ if (id_str == NULL) continue;
+ id = atol(id_str + 7) - 1; /* 'Compact#' or 'PPToken#' */
+ if (id >= nexus->token_len)
+ continue; /* Where did this come from? */
+
elems = g_strsplit(token_str, "&", 0);
for (cur = elems; *cur != NULL; cur++){
tokens = g_strsplit(*cur, "=", 2);
- g_hash_table_insert(nexus->challenge_data, tokens[0], tokens[1]);
+ g_hash_table_insert(nexus->tokens[id].token, tokens[0], tokens[1]);
/* Don't free each of the tokens, only the array. */
g_free(tokens);
}
@@ -97,33 +270,55 @@ nexus_got_response_cb(MsnSoapMessage *re
g_free(token_str);
g_strfreev(elems);
- msn_twn_t = g_hash_table_lookup(nexus->challenge_data, "t");
- msn_twn_p = g_hash_table_lookup(nexus->challenge_data, "p");
+ if (secret)
+ nexus->tokens[id].secret = g_strdup(xmlnode_get_data(secret));
+ else
+ nexus->tokens[id].secret = NULL;
- /*setup the t and p parameter for session*/
- if (session->passport_info.t != NULL){
- g_free(session->passport_info.t);
- }
- session->passport_info.t = g_strdup(msn_twn_t);
+ /* Yay for MS using ISO-8601 */
+ nexus->tokens[id].expiry = purple_str_to_time(xmlnode_get_data(expires),
+ FALSE, NULL, NULL, NULL);
- if (session->passport_info.p != NULL)
- g_free(session->passport_info.p);
- session->passport_info.p = g_strdup(msn_twn_p);
+ purple_debug_info("msnp15", "Updated ticket for domain '%s'\n",
+ ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
+ result = TRUE;
+ }
+ }
- cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p);
- msn_got_login_params(session, cert_str);
+ return result;
+}
- purple_debug_info("MSN Nexus","Close nexus connection!\n");
- g_free(cert_str);
- msn_nexus_destroy(nexus);
- session->nexus = NULL;
+static void
+nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+{
+ MsnNexus *nexus = data;
+ MsnSession *session = nexus->session;
+ char *msn_twn_t, *msn_twn_p, *ticket;
+ char *response;
- return;
- }
+ if (resp == NULL) {
+ msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect"));
+ return;
}
- /* we must have failed! */
- msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication: cannot find authenticate token in server response"));
+ if (!nexus_parse_response(nexus, resp->xml)) {
+ msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Invalid response"));
+ return;
+ }
+
+ /*setup the t and p parameter for session*/
+ msn_twn_t = g_hash_table_lookup(nexus->tokens[MSN_AUTH_MESSENGER].token, "t");
+ msn_twn_p = g_hash_table_lookup(nexus->tokens[MSN_AUTH_MESSENGER].token, "p");
+ g_free(session->passport_info.t);
+ session->passport_info.t = g_strdup(msn_twn_t);
+ g_free(session->passport_info.p);
+ session->passport_info.p = g_strdup(msn_twn_p);
+
+ ticket = g_strdup_printf("t=%s&p=%s", msn_twn_t, msn_twn_p);
+ response = msn_rps_encrypt(nexus);
+ msn_got_login_params(session, ticket, response);
+ g_free(ticket);
+ g_free(response);
}
/*when connect, do the SOAP Style windows Live ID authentication */
@@ -131,92 +326,113 @@ msn_nexus_connect(MsnNexus *nexus)
msn_nexus_connect(MsnNexus *nexus)
{
MsnSession *session = nexus->session;
- char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf;
- char *fs0,*fs;
char *username, *password;
- char *tail;
-#ifdef NEXUS_LOGIN_TWN
- char *challenge_str;
-#else
- char *rst1_str,*rst2_str,*rst3_str;
-#endif
+ GString *domains;
+ char *request;
+ int i;
MsnSoapMessage *soap;
- purple_debug_info("MSN Nexus","Starting Windows Live ID authentication\n");
msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
- /*prepare the Windows Live ID authentication token*/
username = g_strdup(purple_account_get_username(session->account));
password = g_strndup(purple_connection_get_password(session->account->gc), 16);
- lc = (char *)g_hash_table_lookup(nexus->challenge_data, "lc");
- id = (char *)g_hash_table_lookup(nexus->challenge_data, "id");
- tw = (char *)g_hash_table_lookup(nexus->challenge_data, "tw");
- fs0= (char *)g_hash_table_lookup(nexus->challenge_data, "fs");
- ru = (char *)g_hash_table_lookup(nexus->challenge_data, "ru");
- ct = (char *)g_hash_table_lookup(nexus->challenge_data, "ct");
- kpp= (char *)g_hash_table_lookup(nexus->challenge_data, "kpp");
- kv = (char *)g_hash_table_lookup(nexus->challenge_data, "kv");
- ver= (char *)g_hash_table_lookup(nexus->challenge_data, "ver");
- rn = (char *)g_hash_table_lookup(nexus->challenge_data, "rn");
- tpf= (char *)g_hash_table_lookup(nexus->challenge_data, "tpf");
+ purple_debug_info("msnp15", "Logging on %s, with policy '%s', nonce '%s'\n",
+ username, nexus->policy, nexus->nonce);
- /*
- * add some fail-safe code to avoid windows Purple Crash bug #1540454
- * If any of these string is NULL, will return Authentication Fail!
- * for when windows g_strdup_printf() implementation get NULL point,It crashed!
- */
- if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){
- purple_debug_error("MSN Nexus","WLM Authenticate Key Error!\n");
- msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed"));
- g_free(username);
- g_free(password);
- msn_nexus_destroy(nexus);
- session->nexus = NULL;
- return;
+ domains = g_string_new(NULL);
+ for (i = 0; i < nexus->token_len; i++) {
+ g_string_append_printf(domains, MSN_SSO_RST_TEMPLATE,
+ i+1,
+ ticket_domains[i][SSO_VALID_TICKET_DOMAIN],
+ ticket_domains[i][SSO_VALID_TICKET_POLICY] != NULL ?
+ ticket_domains[i][SSO_VALID_TICKET_POLICY] :
+ nexus->policy);
}
- /*
- * in old MSN NS server's "USR TWN S" return,didn't include fs string
- * so we use a default "1" for fs.
- */
- if(fs0){
- fs = g_strdup(fs0);
- }else{
- fs = g_strdup("1");
- }
+ request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password, domains->str);
+ g_free(username);
+ g_free(password);
+ g_string_free(domains, TRUE);
-#ifdef NEXUS_LOGIN_TWN
- challenge_str = g_strdup_printf(
- "lc=%s&id=%s&tw=%s&fs=%s&ru=%s&ct=%s&kpp=%s&kv=%s&ver=%s&rn=%s&tpf=%s\r\n",
- lc,id,tw,fs,ru,ct,kpp,kv,ver,rn,tpf
- );
+ soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
+ g_free(request);
+ msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL,
+ nexus_got_response_cb, nexus);
+}
- /*build the SOAP windows Live ID XML body */
- tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE, username, password, challenge_str);
- g_free(challenge_str);
-#else
- rst1_str = g_strdup_printf(
- "id=%s&tw=%s&fs=%s&kpp=%s&kv=%s&ver=%s&rn=%s",
- id,tw,fs,kpp,kv,ver,rn
- );
- rst2_str = g_strdup_printf(
- "fs=%s&id=%s&kv=%s&rn=%s&tw=%s&ver=%s",
- fs,id,kv,rn,tw,ver
- );
- rst3_str = g_strdup_printf("id=%s",id);
- tail = g_strdup_printf(TWN_LIVE_ENVELOP_TEMPLATE,username,password,rst1_str,rst2_str,rst3_str);
- g_free(rst1_str);
- g_free(rst2_str);
- g_free(rst3_str);
-#endif
- g_free(fs);
+static void
+nexus_got_update_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+{
+ MsnNexus *nexus = data;
+
+ nexus_parse_response(nexus, resp->xml);
+}
+
+static void
+msn_nexus_update_token(MsnNexus *nexus, int id)
+{
+ MsnSession *session = nexus->session;
+ char *username, *password;
+ char *domain;
+ char *request;
+
+ MsnSoapMessage *soap;
+
+ username = g_strdup(purple_account_get_username(session->account));
+ password = g_strndup(purple_connection_get_password(session->account->gc), 16);
+
+ purple_debug_info("msnp15", "Updating ticket for user '%s' on domain '%s'\n",
+ username, ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
+
+ /* TODO: This really assumes if we send RSTn, the server responds with
+ Compactn, even if there is no RST(n-1). This needs checking.
+ */
+ domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE,
+ id,
+ ticket_domains[id][SSO_VALID_TICKET_DOMAIN],
+ ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ?
+ ticket_domains[id][SSO_VALID_TICKET_POLICY] :
+ nexus->policy);
+
+ request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password, domain);
+ g_free(username);
g_free(password);
+ g_free(domain);
- soap = msn_soap_message_new(NULL, xmlnode_from_str(tail, -1));
- g_free(tail);
- msn_soap_message_send(nexus->session, soap, MSN_TWN_SERVER, TWN_POST_URL,
- nexus_got_response_cb, nexus);
+ soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
+ g_free(request);
+ msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL,
+ nexus_got_update_cb, nexus);
}
+GHashTable *
+msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id)
+{
+ g_return_val_if_fail(nexus != NULL, NULL);
+ g_return_val_if_fail(id < nexus->token_len, NULL);
+
+ if (time(NULL) > nexus->tokens[id].expiry)
+ msn_nexus_update_token(nexus, id);
+
+ return g_hash_table_ref(nexus->tokens[id].token);
+}
+
+char *
+msn_nexus_get_token_str(MsnNexus *session, MsnAuthDomains id)
+{
+#if 0
+ GHashTable *token = msn_nexus_get_token(nexus, id);
+ GString *token_str;
+
+ g_return_val_if_fail(token != NULL, NULL);
+
+ token_str = g_string_new(NULL);
+ g_hash_table_foreach(token, GHFunc func, token_str);
+
+ g_hash_table_unref (token);
+#endif
+ return NULL;
+}
+
============================================================
--- libpurple/protocols/msn/nexus.h 8509a2a084e386fadfc7da29cbe9cf6ae3dfbbe5
+++ libpurple/protocols/msn/nexus.h 4856b18aba79e0f24a3053d02379e895107ec0e2
@@ -26,125 +26,115 @@
#include "soap.h"
-/*#define MSN_TWN_SERVER "loginnet.passport.com"*/
-#define MSN_TWN_SERVER "login.live.com"
+/* Index into ticket_tokens in nexus.c Keep updated! */
+typedef enum
+{
+ MSN_AUTH_MESSENGER = 0,
+ MSN_AUTH_MESSENGER_WEB = 1,
+ MSN_AUTH_CONTACTS = 2,
+ MSN_AUTH_LIVE_UNKNOWN = 3,
+ MSN_AUTH_SPACES = 4,
+ MSN_AUTH_LIVE_CONTACTS = 5,
+ MSN_AUTH_STORAGE = 6
+} MsnAuthDomains;
-#define TWN_START_TOKEN "<wsse:BinarySecurityToken Id=\"PPToken1\">"
-#define TWN_END_TOKEN "</wsse:BinarySecurityToken>"
+#define MSN_SSO_SERVER "login.live.com"
+#define SSO_POST_URL "/RST.srf"
-#define TWN_POST_URL "/RST.srf"
-#define TWN_ENVELOP_TEMPLATE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"\
- "<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
- "<Header>"\
- "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\
- "<ps:HostingApp>{3:B}</ps:HostingApp>"\
- "<ps:BinaryVersion>4</ps:BinaryVersion>"\
- "<ps:UIVersion>1</ps:UIVersion>"\
- "<ps:Cookies></ps:Cookies>"\
- "<ps:RequestParams>AQAAAAIAAABsYwQAAAAzMDg0</ps:RequestParams>"\
- "</ps:AuthInfo>"\
- "<wsse:Security>"\
- "<wsse:UsernameToken Id=\"user\">"\
- "<wsse:Username>%s</wsse:Username>"\
- "<wsse:Password>%s</wsse:Password>"\
- "</wsse:UsernameToken>"\
- "</wsse:Security>"\
- "</Header>"\
- "<Body>"\
- "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">"\
- "<wst:RequestSecurityToken Id=\"RST0\">"\
- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
- "<wsp:AppliesTo>"\
- "<wsa:EndpointReference>"\
- "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\
- "</wsa:EndpointReference>"\
- "</wsp:AppliesTo>"\
- "</wst:RequestSecurityToken>"\
- "<wst:RequestSecurityToken Id=\"RST1\">"\
- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
- "<wsp:AppliesTo>"\
- "<wsa:EndpointReference>"\
- "<wsa:Address>messenger.msn.com</wsa:Address>"\
- "</wsa:EndpointReference>"\
- "</wsp:AppliesTo>"\
- "<wsse:PolicyReference URI=\"?%s\">"\
- "</wsse:PolicyReference>"\
- "</wst:RequestSecurityToken>"\
- "</ps:RequestMultipleSecurityTokens>"\
- "</Body>"\
- "</Envelope>"
+#define MSN_SSO_RST_TEMPLATE \
+"<wst:RequestSecurityToken Id=\"RST%d\">"\
+ "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
+ "<wsp:AppliesTo>"\
+ "<wsa:EndpointReference>"\
+ "<wsa:Address>%s</wsa:Address>"\
+ "</wsa:EndpointReference>"\
+ "</wsp:AppliesTo>"\
+ "<wsse:PolicyReference URI=\"%s\"></wsse:PolicyReference>"\
+"</wst:RequestSecurityToken>"
-#define TWN_LIVE_START_TOKEN "<wsse:BinarySecurityToken Id=\"PPToken1\">"
-#define TWN_LIVE_END_TOKEN "</wsse:BinarySecurityToken>"
-#define TWN_LIVE_ENVELOP_TEMPLATE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"\
-"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
- "<Header>"\
- "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\
- "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
- "<ps:BinaryVersion>4</ps:BinaryVersion>"\
- "<ps:UIVersion>1</ps:UIVersion>"\
- "<ps:Cookies></ps:Cookies>"\
- "<ps:RequestParams>AQAAAAIAAABsYwQAAAAyMDUy</ps:RequestParams>"\
- "</ps:AuthInfo>"\
- "<wsse:Security>"\
- "<wsse:UsernameToken Id=\"user\">"\
- "<wsse:Username>%s</wsse:Username>"\
- "<wsse:Password>%s</wsse:Password>"\
- "</wsse:UsernameToken>"\
- "</wsse:Security>"\
- "</Header>"\
- "<Body>"\
- "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">"\
- "<wst:RequestSecurityToken Id=\"RST0\">"\
- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
- "<wsp:AppliesTo>"\
- "<wsa:EndpointReference>"\
- "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\
- "</wsa:EndpointReference>"\
- "</wsp:AppliesTo>"\
- "</wst:RequestSecurityToken>"\
- "<wst:RequestSecurityToken Id=\"RST1\">"\
- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
- "<wsp:AppliesTo>"\
- "<wsa:EndpointReference>"\
- "<wsa:Address>messenger.msn.com</wsa:Address>"\
- "</wsa:EndpointReference>"\
- "</wsp:AppliesTo>"\
- "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>"\
- "</wst:RequestSecurityToken>"\
- "<wst:RequestSecurityToken Id=\"RST2\">"\
- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
- "<wsp:AppliesTo>"\
- "<wsa:EndpointReference>"\
- "<wsa:Address>contacts.msn.com</wsa:Address>"\
- "</wsa:EndpointReference>"\
- "</wsp:AppliesTo>"\
- "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>"\
- " </wst:RequestSecurityToken>"\
- "<wst:RequestSecurityToken Id=\"RST3\">"\
- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
- "<wsp:AppliesTo>"\
- "<wsa:EndpointReference>"\
- "<wsa:Address>voice.messenger.msn.com</wsa:Address>"\
- "</wsa:EndpointReference>"\
- " </wsp:AppliesTo>"\
- "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>"\
- "</wst:RequestSecurityToken>"\
- "</ps:RequestMultipleSecurityTokens>"\
- "</Body>"\
+#define MSN_SSO_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\
+"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+ " xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\
+ " xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\
+ " xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\
+ " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\
+ " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\
+ " xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\
+ " xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
+ "<Header>"\
+ "<ps:AuthInfo"\
+ " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
+ " Id=\"PPAuthInfo\">"\
+ "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
+ "<ps:BinaryVersion>4</ps:BinaryVersion>"\
+ "<ps:UIVersion>1</ps:UIVersion>"\
+ "<ps:Cookies></ps:Cookies>"\
+ "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>"\
+ "</ps:AuthInfo>"\
+ "<wsse:Security>"\
+ "<wsse:UsernameToken Id=\"user\">"\
+ "<wsse:Username>%s</wsse:Username>"\
+ "<wsse:Password>%s</wsse:Password>"\
+ "</wsse:UsernameToken>"\
+ "</wsse:Security>"\
+ "</Header>"\
+ "<Body>"\
+ "<ps:RequestMultipleSecurityTokens"\
+ " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
+ " Id=\"RSTS\">"\
+ "<wst:RequestSecurityToken Id=\"RST0\">"\
+ "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
+ "<wsp:AppliesTo>"\
+ "<wsa:EndpointReference>"\
+ "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\
+ "</wsa:EndpointReference>"\
+ "</wsp:AppliesTo>"\
+ "</wst:RequestSecurityToken>"\
+ "%s" /* Other RSTn tokens */\
+ "</ps:RequestMultipleSecurityTokens>"\
+ "</Body>"\
"</Envelope>"
+typedef struct _MsnUsrKey MsnUsrKey;
+struct _MsnUsrKey
+{
+ int size; // 28. Does not count data
+ int crypt_mode; // CRYPT_MODE_CBC (1)
+ int cipher_type; // TripleDES (0x6603)
+ int hash_type; // SHA1 (0x8004)
+ int iv_len; // 8
+ int hash_len; // 20
+ int cipher_len; // 72
+ // Data
+ char iv[8];
+ char hash[20];
+ char cipher[72];
+};
+
+typedef struct _MsnTicketToken MsnTicketToken;
+struct _MsnTicketToken {
+ GHashTable *token;
+ char *secret;
+ time_t expiry;
+};
+
typedef struct _MsnNexus MsnNexus;
struct _MsnNexus
{
MsnSession *session;
- char * challenge_data_str;
- GHashTable *challenge_data;
+ char *policy;
+ char *nonce;
+
+ MsnTicketToken *tokens;
+ int token_len;
};
void msn_nexus_connect(MsnNexus *nexus);
MsnNexus *msn_nexus_new(MsnSession *session);
void msn_nexus_destroy(MsnNexus *nexus);
+GHashTable *msn_nexus_get_token(MsnNexus *session, MsnAuthDomains id);
+char *msn_nexus_get_token_str(MsnNexus *session, MsnAuthDomains id);
#endif /* _MSN_NEXUS_H_ */
+
============================================================
--- libpurple/protocols/msn/notification.c 86890bb08028eee3504314d06c13821ad52000a7
+++ libpurple/protocols/msn/notification.c 39c4c50e583f3d564231bbae933e95dfb0a6cac2
@@ -204,7 +204,7 @@ void
**************************************************************************/
void
-msn_got_login_params(MsnSession *session, const char *login_params)
+msn_got_login_params(MsnSession *session, const char *ticket, const char *response)
{
MsnCmdProc *cmdproc;
@@ -212,7 +212,7 @@ msn_got_login_params(MsnSession *session
msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END);
- msn_cmdproc_send(cmdproc, "USR", "TWN S %s", login_params);
+ msn_cmdproc_send(cmdproc, "USR", "SSO S %s %s", ticket, response);
}
static void
@@ -221,8 +221,8 @@ cvr_cmd(MsnCmdProc *cmdproc, MsnCommand
PurpleAccount *account;
account = cmdproc->session->account;
- msn_cmdproc_send(cmdproc, "USR", "TWN I %s",
- purple_account_get_username(account));
+
+ msn_cmdproc_send(cmdproc, "USR", "SSO I %s", purple_account_get_username(account));
}
static void
@@ -248,33 +248,15 @@ usr_cmd(MsnCmdProc *cmdproc, MsnCommand
// msn_cmdproc_send(cmdproc, "SYN", "%s", "0");
//TODO we should use SOAP contact to fetch contact list
}
- else if (!g_ascii_strcasecmp(cmd->params[1], "TWN"))
+ else if (!g_ascii_strcasecmp(cmd->params[1], "SSO"))
{
- /* Passport authentication */
- char **elems, **cur, **tokens;
+ /* RPS authentication */
session->nexus = msn_nexus_new(session);
- /* Parse the challenge data. */
- session->nexus->challenge_data_str = g_strdup(cmd->params[3]);
- elems = g_strsplit(cmd->params[3], ",", 0);
+ session->nexus->policy = g_strdup(cmd->params[3]);
+ session->nexus->nonce = g_strdup(cmd->params[4]);
- for (cur = elems; *cur != NULL; cur++)
- {
- tokens = g_strsplit(*cur, "=", 2);
- if(tokens[0] && tokens[1])
- {
- purple_debug_info("MSNP14","challenge %p,key:%s,value:%s\n",
- session->nexus->challenge_data,tokens[0],tokens[1]);
- g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]);
- /* Don't free each of the tokens, only the array. */
- g_free(tokens);
- } else
- g_strfreev(tokens);
- }
-
- g_strfreev(elems);
-
msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START);
msn_nexus_connect(session->nexus);
More information about the Commits
mailing list