Esempio n. 1
0
static void
msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
{
	MsnSoapConnection *conn = data;
	int count = 0, cnt, perrno;
	/* This buffer needs to be larger than any packets received from
		login.live.com or Adium will fail to receive the packet
		(something weird with the login.live.com server). With NSS it works
		fine, so I believe it's some bug with OS X */
	char buf[16 * 1024];
	gsize cursor;

	if (conn->message == NULL) {
		conn->message = msn_soap_message_new(NULL, NULL);
	}

	if (conn->buf == NULL) {
		conn->buf = g_string_new_len(buf, 0);
	}

	cursor = conn->buf->len;
	while ((cnt = purple_ssl_read(conn->ssl, buf, sizeof(buf))) > 0) {
		purple_debug_info("soap", "read %d bytes\n", cnt);
		count += cnt;
		g_string_append_len(conn->buf, buf, cnt);
	}

	perrno = errno;
	if (cnt < 0 && perrno != EAGAIN)
		purple_debug_info("soap", "read: %s\n", g_strerror(perrno));

	if (conn->current_request && conn->current_request->secure &&
		!purple_debug_is_unsafe())
		purple_debug_misc("soap", "Received secure request.\n");
	else if (count != 0)
		purple_debug_misc("soap", "current %s\n", conn->buf->str + cursor);

	/* && count is necessary for Adium, on OS X the last read always
	   return an error, so we want to proceed anyway. See #5212 for
	   discussion on this and the above buffer size issues */
	if(cnt < 0 && errno == EAGAIN && count == 0)
		return;

	/* msn_soap_process could alter errno */
	msn_soap_process(conn);

	if ((cnt < 0 && perrno != EAGAIN) || cnt == 0) {
		/* It's possible msn_soap_process closed the ssl connection */
		if (conn->ssl) {
			purple_ssl_close(conn->ssl);
			conn->ssl = NULL;
			msn_soap_connection_handle_next(conn);
		}
	}
}
Esempio n. 2
0
/*when connect, do the SOAP Style windows Live ID authentication */
void
msn_nexus_connect(MsnNexus *nexus)
{
	MsnSession *session = nexus->session;
	const char *username;
	const char *password;
	char *password_xml;
	GString *domains;
	char *request;
	int i;

	MsnSoapMessage *soap;

	purple_debug_info("msn", "Starting Windows Live ID authentication\n");
	msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);

	username = purple_account_get_username(session->account);
	password = purple_connection_get_password(session->account->gc);
	if (g_utf8_strlen(password, -1) > 16) {
		/* max byte size for 16 utf8 characters is 64 + 1 for the null */
		gchar truncated[65];
		g_utf8_strncpy(truncated, password, 16);
		password_xml = g_markup_escape_text(truncated, -1);
	} else {
		password_xml = g_markup_escape_text(password, -1);
	}

	purple_debug_info("msn", "Logging on %s, with policy '%s', nonce '%s'\n",
	                  username, nexus->policy, nexus->nonce);

	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);
	}

	request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password_xml, domains->str);
	g_free(password_xml);
	g_string_free(domains, TRUE);

	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, TRUE,
	                      nexus_got_response_cb, nexus);
}
Esempio n. 3
0
static gboolean
msn_oim_request_helper(MsnOimRequestData *data)
{
	MsnSession *session = data->oim->session;

	if (data->send) {
		/* The Sending of OIM's uses a different token for some reason. */
		xmlnode *ticket;
		ticket = xmlnode_get_child(data->body, "Header/Ticket");
		xmlnode_set_attrib(ticket, "passport",
			msn_nexus_get_token_str(session->nexus, MSN_AUTH_LIVE_SECURE));
	}
	else
	{
		xmlnode *passport;
		xmlnode *xml_t;
		xmlnode *xml_p;
		GHashTable *token;
		const char *msn_t;
		const char *msn_p;

		token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB);
		g_return_val_if_fail(token != NULL, FALSE);

		msn_t = g_hash_table_lookup(token, "t");
		msn_p = g_hash_table_lookup(token, "p");

		g_return_val_if_fail(msn_t != NULL, FALSE);
		g_return_val_if_fail(msn_p != NULL, FALSE);

		passport = xmlnode_get_child(data->body, "Header/PassportCookie");
		xml_t = xmlnode_get_child(passport, "t");
		xml_p = xmlnode_get_child(passport, "p");

		/* frees old token text, or the 'EMPTY' text if first time */
		xmlnode_free(xml_t->child);
		xmlnode_free(xml_p->child);

		xmlnode_insert_data(xml_t, msn_t, -1);
		xmlnode_insert_data(xml_p, msn_p, -1);
	}

	msn_soap_message_send(session,
		msn_soap_message_new(data->action, xmlnode_copy(data->body)),
		data->host, data->url, FALSE,
		msn_oim_request_cb, data);

	return FALSE;
}
Esempio n. 4
0
void
msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data)
{
	MsnSession *session = nexus->session;
	MsnNexusUpdateData *ud;
	MsnNexusUpdateCallback *update;
	PurpleCipherContext *sha1;
	PurpleCipherContext *hmac;

	char *key;

	guchar digest[20];

	struct tm *tm;
	time_t now;
	char *now_str;
	char *timestamp;
	char *timestamp_b64;

	char *domain;
	char *domain_b64;

	char *signedinfo;
	gint32 nonce[6];
	int i;
	char *nonce_b64;
	char *signature_b64;
	guchar signature[20];

	char *request;
	MsnSoapMessage *soap;

	update = g_new0(MsnNexusUpdateCallback, 1);
	update->cb = cb;
	update->data = data;

	if (nexus->tokens[id].updates != NULL) {
		/* Update already in progress. Just add to list and return. */
		purple_debug_info("msn",
		                  "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n",
		                  purple_account_get_username(session->account),
		                  ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
		nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
		                                            update);
		return;
	} else {
		purple_debug_info("msn",
		                  "Updating ticket for user '%s' on domain '%s'\n",
		                  purple_account_get_username(session->account),
		                  ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
		nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
		                                            update);
	}

	ud = g_new0(MsnNexusUpdateData, 1);
	ud->nexus = nexus;
	ud->id = id;

	sha1 = purple_cipher_context_new_by_name("sha1", NULL);

	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);
	purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain));
	purple_cipher_context_digest(sha1, 20, digest, NULL);
	domain_b64 = purple_base64_encode(digest, 20);

	now = time(NULL);
	tm = gmtime(&now);
	now_str = g_strdup(purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
	now += 5*60;
	tm = gmtime(&now);
	timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE,
	                            now_str,
	                            purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
	purple_cipher_context_reset(sha1, NULL);
	purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp));
	purple_cipher_context_digest(sha1, 20, digest, NULL);
	timestamp_b64 = purple_base64_encode(digest, 20);
	g_free(now_str);

	purple_cipher_context_destroy(sha1);

	signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE,
	                             id,
	                             domain_b64,
	                             timestamp_b64);

	for (i = 0; i < 6; i++)
		nonce[i] = rand();
	nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce));

	key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce));
	hmac = purple_cipher_context_new_by_name("hmac", NULL);
	purple_cipher_context_set_option(hmac, "hash", "sha1");
	purple_cipher_context_set_key_with_len(hmac, (guchar *)key, 24);
	purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo));
	purple_cipher_context_digest(hmac, 20, signature, NULL);
	purple_cipher_context_destroy(hmac);
	signature_b64 = purple_base64_encode(signature, 20);

	request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE,
	                          nexus->cipher,
	                          nonce_b64,
	                          timestamp,
	                          signedinfo,
	                          signature_b64,
	                          domain);

	g_free(nonce_b64);
	g_free(domain_b64);
	g_free(timestamp_b64);
	g_free(timestamp);
	g_free(key);
	g_free(signature_b64);
	g_free(signedinfo);
	g_free(domain);

	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, TRUE,
	                      nexus_got_update_cb, ud);
}