Index: lib/sha1.c
===================================================================
--- lib/sha1.c	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ lib/sha1.c	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -36,4 +36,5 @@
  */
 
+#include <string.h>
 #include "sha1.h"
 
@@ -374,2 +375,48 @@
 	sha1_process_block(context);
 }
+
+#define HMAC_BLOCK_SIZE 64
+
+/* BitlBee addition: */
+void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, uint8_t Message_Digest[sha1_hash_size])
+{
+	sha1_state_t sha1;
+	uint8_t hash[sha1_hash_size];
+	uint8_t key[HMAC_BLOCK_SIZE+1];
+	int i;
+	
+	if( key_len == 0 )
+		key_len = strlen( key_ );
+	if( payload_len == 0 )
+		payload_len = strlen( payload );
+	
+	/* Create K. If our current key is >64 chars we have to hash it,
+	   otherwise just pad. */
+	memset( key, 0, HMAC_BLOCK_SIZE + 1 );
+	if( key_len > HMAC_BLOCK_SIZE )
+	{
+		sha1_init( &sha1 );
+		sha1_append( &sha1, (uint8_t*) key_, key_len );
+		sha1_finish( &sha1, key );
+	}
+	else
+	{
+		memcpy( key, key_, key_len );
+	}
+	
+	/* Inner part: H(K XOR 0x36, text) */
+	sha1_init( &sha1 );
+	for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )
+		key[i] ^= 0x36;
+	sha1_append( &sha1, key, HMAC_BLOCK_SIZE );
+	sha1_append( &sha1, (const uint8_t*) payload, payload_len );
+	sha1_finish( &sha1, hash );
+	
+	/* Final result: H(K XOR 0x5C, inner stuff) */
+	sha1_init( &sha1 );
+	for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )
+		key[i] ^= 0x36 ^ 0x5c;
+	sha1_append( &sha1, key, HMAC_BLOCK_SIZE );
+	sha1_append( &sha1, hash, sha1_hash_size );
+	sha1_finish( &sha1, Message_Digest );
+}
Index: lib/sha1.h
===================================================================
--- lib/sha1.h	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ lib/sha1.h	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -67,4 +67,5 @@
 G_MODULE_EXPORT int sha1_append(sha1_state_t *, const uint8_t *, unsigned int);
 G_MODULE_EXPORT int sha1_finish(sha1_state_t *, uint8_t Message_Digest[sha1_hash_size]);
+G_MODULE_EXPORT void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, uint8_t Message_Digest[sha1_hash_size]);
 
 #endif
Index: lib/ssl_client.h
===================================================================
--- lib/ssl_client.h	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ lib/ssl_client.h	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -78,2 +78,4 @@
    the same action as the handler that just received the SSL_AGAIN.) */
 G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn );
+
+G_MODULE_EXPORT size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res);
Index: lib/ssl_openssl.c
===================================================================
--- lib/ssl_openssl.c	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ lib/ssl_openssl.c	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -272,2 +272,26 @@
 	return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ );
 }
+
+size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res)
+{
+	OpenSSL_add_all_algorithms();
+	int output_length = 0;    
+	
+	*res = g_new0(unsigned char, 72);
+	
+	EVP_CIPHER_CTX ctx;
+	/* Don't set key or IV because we will modify the parameters */
+	EVP_CIPHER_CTX_init(&ctx);
+	EVP_CipherInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, NULL, NULL, 1);
+	EVP_CIPHER_CTX_set_key_length(&ctx, key_len);
+	EVP_CIPHER_CTX_set_padding(&ctx, 0);
+	/* We finished modifying parameters so now we can set key and IV */
+	EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1);
+	EVP_CipherUpdate(&ctx, *res, &output_length, input, input_len);
+	EVP_CipherFinal_ex(&ctx, *res, &output_length);
+	
+	EVP_CIPHER_CTX_cleanup(&ctx);   
+	EVP_cleanup();
+	
+	return output_length;
+}
Index: protocols/msn/Makefile
===================================================================
--- protocols/msn/Makefile	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/Makefile	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -43,3 +43,3 @@
 	@$(LD) $(LFLAGS) $(objects) -o msn_mod.o
 	
-
+soap.o: soap.h soap.c
Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/msn.c	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -103,5 +103,6 @@
 			g_free( md->grouplist[--md->groupcount] );
 		g_free( md->grouplist );
-		g_free( md->passport_token );
+		g_free( md->tokens[0] );
+		g_free( md->tokens[1] );
 		g_free( md->lock_key );
 		
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/msn.h	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -76,5 +76,5 @@
 	
 	int trId;
-	char *passport_token;
+	char *tokens[2];
 	char *lock_key;
 	
@@ -171,4 +171,5 @@
 /* ns.c */
 gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
+void msn_auth_got_passport_token( struct im_connection *ic, char *token );
 
 /* msn_util.c */
Index: protocols/msn/msn_util.c
===================================================================
--- protocols/msn/msn_util.c	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/msn_util.c	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -33,4 +33,10 @@
 	struct msn_data *md = ic->proto_data;
 	int st;
+	
+	if( getenv( "BITLBEE_DEBUG" ) )
+	{
+		write( 2, "->NS:", 5 );
+		write( 2, s, len );
+	}
 	
 	st = write( md->fd, s, len );
@@ -280,4 +286,10 @@
 	if( st <= 0 )
 		return( -1 );
+	
+	if( getenv( "BITLBEE_DEBUG" ) )
+	{
+		write( 2, "->C:", 4 );
+		write( 2, h->rxq + h->rxlen - st, st );
+	}
 	
 	while( st )
@@ -446,25 +458,4 @@
 }
 
-unsigned int little_endian( unsigned int dw )
-{
-#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
-	return dw;
-#else
-	/* We're still not sure if this machine is big endian since the
-	   constants above are not that portable. Don't swap bytes, just
-	   force-compose a 32-bit little endian integer. */
-	unsigned int ret = 0, i;
-	char *dst = (char*) (&ret + 1);
-	
-	for (i = 0; i < 4; i ++)
-	{
-		*(--dst) = dw >> 24;
-		dw <<= 8;
-	}
-	
-	return ret;
-#endif
-}
-
 /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */
 char *msn_p11_challenge( char *challenge )
@@ -487,5 +478,5 @@
 	for (i = 0; i < 4; i ++)
 	{  
-		md5Parts[i] = little_endian(md5Parts[i]);
+		md5Parts[i] = GUINT32_TO_LE(md5Parts[i]);
 		
 		/* & each integer with 0x7FFFFFFF */
@@ -508,6 +499,6 @@
 		long long temp;
 
-		chlStringParts[i]   = little_endian(chlStringParts[i]);
-		chlStringParts[i+1] = little_endian(chlStringParts[i+1]);
+		chlStringParts[i]   = GUINT32_TO_LE(chlStringParts[i]);
+		chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]);
 
 		temp  = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF;
@@ -525,5 +516,5 @@
 	/* swap more bytes if big endian */
 	for (i = 0; i < 4; i ++)
-		newHashParts[i] = little_endian(newHashParts[i]); 
+		newHashParts[i] = GUINT32_TO_LE(newHashParts[i]); 
 	
 	/* make a string of the parts */
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/ns.c	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -35,5 +35,4 @@
 static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
 
-static void msn_auth_got_passport_token( struct msn_auth_data *mad );
 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name );
 
@@ -74,5 +73,5 @@
 	md->handler->rxq = g_new0( char, 1 );
 	
-	g_snprintf( s, sizeof( s ), "VER %d MSNP14 CVR0\r\n", ++md->trId );
+	g_snprintf( s, sizeof( s ), "VER %d MSNP15 CVR0\r\n", ++md->trId );
 	if( msn_write( ic, s, strlen( s ) ) )
 	{
@@ -114,5 +113,5 @@
 	if( strcmp( cmd[0], "VER" ) == 0 )
 	{
-		if( cmd[2] && strncmp( cmd[2], "MSNP14", 5 ) != 0 )
+		if( cmd[2] && strncmp( cmd[2], "MSNP15", 5 ) != 0 )
 		{
 			imcb_error( ic, "Unsupported protocol" );
@@ -128,5 +127,5 @@
 	{
 		/* We don't give a damn about the information we just received */
-		g_snprintf( buf, sizeof( buf ), "USR %d TWN I %s\r\n", ++md->trId, ic->acc->user );
+		g_snprintf( buf, sizeof( buf ), "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user );
 		return( msn_write( ic, buf, strlen( buf ) ) );
 	}
@@ -221,13 +220,8 @@
 	else if( strcmp( cmd[0], "USR" ) == 0 )
 	{
-		if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 )
-		{
-			/* Time for some Passport black magic... */
-			if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) )
-			{
-				imcb_error( ic, "Error while contacting Passport server" );
-				imc_logout( ic, TRUE );
-				return( 0 );
-			}
+		if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
+		    strcmp( cmd[3], "S" ) == 0 )
+		{
+			msn_soap_passport_sso_request( ic, cmd[4], cmd[5] );
 		}
 		else if( strcmp( cmd[2], "OK" ) == 0 )
@@ -775,7 +769,6 @@
 }
 
-static void msn_auth_got_passport_token( struct msn_auth_data *mad )
+void msn_auth_got_passport_token( struct im_connection *ic, char *token )
 {
-	struct im_connection *ic = mad->data;
 	struct msn_data *md;
 	
@@ -785,17 +778,10 @@
 	
 	md = ic->proto_data;
-	if( mad->token )
+	
 	{
 		char buf[1024];
 		
-		md->passport_token = g_strdup( mad->token );
-		
-		g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token );
+		g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token );
 		msn_write( ic, buf, strlen( buf ) );
-	}
-	else
-	{
-		imcb_error( ic, "Error during Passport authentication: %s", mad->error );
-		imc_logout( ic, TRUE );
 	}
 }
Index: protocols/msn/sb.c
===================================================================
--- protocols/msn/sb.c	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/sb.c	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -39,4 +39,10 @@
 {
 	int st;
+	
+	if( getenv( "BITLBEE_DEBUG" ) )
+	{
+		write( 2, "->SB:", 5 );
+		write( 2, s, len );
+	}
 	
 	st = write( sb->fd, s, len );
Index: protocols/msn/soap.c
===================================================================
--- protocols/msn/soap.c	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/soap.c	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -28,4 +28,5 @@
 #include "url.h"
 #include "misc.h"
+#include "sha1.h"
 #include "base64.h"
 #include "xmltree.h"
@@ -83,19 +84,16 @@
 static int msn_soap_send_request( struct msn_soap_req_data *soap_req )
 {
-	struct msn_data *md = soap_req->ic->proto_data;
 	char *http_req;
-	char *pom, *s;
+	char *soap_action = NULL;
 	url_t url;
 	
 	soap_req->build_request( soap_req );
 	
-	pom = g_new0( char, strlen( md->passport_token ) * 3 );
-	strcpy( pom, md->passport_token + 2 );
-	if( ( s = strchr( pom, '&' ) ) )
-		*s = '\0';
+	if( soap_req->action )
+		soap_action = g_strdup_printf( "SOAPAction: \"%s\"\r\n", soap_req->action );
 	
 	url_set( &url, soap_req->url );
 	http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host,
-		soap_req->action, pom,
+		soap_action ? soap_action : "",
 		strlen( soap_req->payload ), soap_req->payload );
 	
@@ -104,4 +102,5 @@
 	
 	g_free( http_req );
+	g_free( soap_action );
 	
 	return soap_req->http_req != NULL;
@@ -140,4 +139,158 @@
 
 
+/* passport_sso: Authentication MSNP15+ */
+
+struct msn_soap_passport_sso_data
+{
+	char *policy;
+	char *nonce;
+	char *secret;
+};
+
+static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req )
+{
+	struct msn_soap_passport_sso_data *sd = soap_req->data;
+	struct im_connection *ic = soap_req->ic;
+	
+	soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL );
+	soap_req->payload = g_markup_printf_escaped( SOAP_PASSPORT_SSO_PAYLOAD,
+		ic->acc->user, ic->acc->pass, sd->policy );
+	
+	return MSN_SOAP_OK;
+}
+
+static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer data )
+{
+	struct msn_soap_req_data *soap_req = data;
+	struct msn_soap_passport_sso_data *sd = soap_req->data;
+	struct msn_data *md = soap_req->ic->proto_data;
+	struct xt_node *p;
+	char *id;
+	
+	if( ( id = xt_find_attr( node, "Id" ) ) == NULL )
+		return XT_HANDLED;
+	id += strlen( id ) - 1;
+	if( *id == '1' &&
+	    ( p = node->parent ) && ( p = p->parent ) &&
+	    ( p = xt_find_node( p->children, "wst:RequestedProofToken" ) ) &&
+	    ( p = xt_find_node( p->children, "wst:BinarySecret" ) ) &&
+	    p->text )
+	    	sd->secret = g_strdup( p->text );
+	
+	if( *id == '1' )
+		md->tokens[0] = g_strdup( node->text );
+	else if( *id == '2' )
+		md->tokens[1] = g_strdup( node->text );
+	
+	return XT_HANDLED;
+}
+
+static const struct xt_handler_entry msn_soap_passport_sso_parser[] = {
+	{ "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", msn_soap_passport_sso_token },
+	{ NULL, NULL, NULL }
+};
+
+static char *msn_key_fuckery( char *key, int key_len, char *type )
+{
+	unsigned char hash1[20+strlen(type)+1];
+	unsigned char hash2[20];
+	char *ret;
+	
+	sha1_hmac( key, key_len, type, 0, hash1 );
+	strcpy( (char*) hash1 + 20, type );
+	sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash2 );
+	
+	/* This is okay as hash1 is read completely before it's overwritten. */
+	sha1_hmac( key, key_len, (char*) hash1, 20, hash1 );
+	sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash1 );
+	
+	ret = g_malloc( 24 );
+	memcpy( ret, hash2, 20 );
+	memcpy( ret + 20, hash1, 4 );
+	return ret;
+}
+
+static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap_req )
+{
+	struct msn_soap_passport_sso_data *sd = soap_req->data;
+	struct im_connection *ic = soap_req->ic;
+	char *key1, *key2, *key3, *blurb64;
+	int key1_len;
+	unsigned char *padnonce, *des3res;
+	struct
+	{
+		unsigned int uStructHeaderSize; // 28. Does not count data
+		unsigned int uCryptMode; // CRYPT_MODE_CBC (1)
+		unsigned int uCipherType; // TripleDES (0x6603)
+		unsigned int uHashType; // SHA1 (0x8004)
+		unsigned int uIVLen;    // 8
+		unsigned int uHashLen;  // 20
+		unsigned int uCipherLen; // 72
+		unsigned char iv[8];
+		unsigned char hash[20];
+		unsigned char cipherbytes[72];
+	} blurb = {
+		GUINT32_TO_LE( 28 ),
+		GUINT32_TO_LE( 1 ),
+		GUINT32_TO_LE( 0x6603 ),
+		GUINT32_TO_LE( 0x8004 ),
+		GUINT32_TO_LE( 8 ),
+		GUINT32_TO_LE( 20 ),
+		GUINT32_TO_LE( 72 ),
+	};
+
+	key1_len = base64_decode( sd->secret, (unsigned char**) &key1 );
+	
+	key2 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY HASH" );
+	key3 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY ENCRYPTION" );
+	
+	sha1_hmac( key2, 24, sd->nonce, 0, blurb.hash );
+	padnonce = g_malloc( strlen( sd->nonce ) + 8 );
+	strcpy( (char*) padnonce, sd->nonce );
+	memset( padnonce + strlen( sd->nonce ), 8, 8 );
+	
+	random_bytes( blurb.iv, 8 );
+	
+	ssl_des3_encrypt( (unsigned char*) key3, 24, padnonce, strlen( sd->nonce ) + 8, blurb.iv, &des3res );
+	memcpy( blurb.cipherbytes, des3res, 72 );
+	
+	blurb64 = base64_encode( (unsigned char*) &blurb, sizeof( blurb ) );
+	msn_auth_got_passport_token( ic, blurb64 );
+	
+	g_free( padnonce );
+	g_free( blurb64 );
+	g_free( des3res );
+	g_free( key1 );
+	g_free( key2 );
+	g_free( key3 );
+	
+	return MSN_SOAP_OK;
+}
+
+static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req )
+{
+	struct msn_soap_passport_sso_data *sd = soap_req->data;
+	
+	g_free( sd->policy );
+	g_free( sd->nonce );
+	g_free( sd->secret );
+	
+	return MSN_SOAP_OK;
+}
+
+int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce )
+{
+	struct msn_soap_passport_sso_data *sd = g_new0( struct msn_soap_passport_sso_data, 1 );
+	
+	sd->policy = g_strdup( policy );
+	sd->nonce = g_strdup( nonce );
+	
+	return msn_soap_start( ic, sd, msn_soap_passport_sso_build_request,
+	                               msn_soap_passport_sso_parser,
+	                               msn_soap_passport_sso_handle_response,
+	                               msn_soap_passport_sso_free_data );
+}
+
+
 /* oim_send: Sending offline messages */
 
@@ -162,5 +315,5 @@
 	soap_req->action = g_strdup( SOAP_OIM_SEND_ACTION );
 	soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD,
-		ic->acc->user, display_name_b64, oim->to, md->passport_token,
+		ic->acc->user, display_name_b64, oim->to, "bla", //md->passport_token,
 		MSNP11_PROD_ID, md->lock_key ? md->lock_key : "",
 		oim->number, oim->number, oim->msg );
@@ -168,5 +321,5 @@
 	g_free( display_name_b64 );
 	
-	return 1;
+	return MSN_SOAP_OK;
 }
 
@@ -220,5 +373,5 @@
 	g_free( oim );
 	
-	return 0;
+	return MSN_SOAP_OK;
 }
 
@@ -263,4 +416,6 @@
 		*msgq = g_slist_remove( *msgq, m );
 	}
+	
+	return 1;
 }
 
Index: protocols/msn/soap.h
===================================================================
--- protocols/msn/soap.h	(revision 7db65b7df08a3c7cab28e065b2ffa3d9941ceccb)
+++ protocols/msn/soap.h	(revision 523fb2324a351e9607ad2a803c6e866c5175aa16)
@@ -43,12 +43,77 @@
 "Host: %s\r\n" \
 "Accept: */*\r\n" \
-"SOAPAction: \"%s\"\r\n" \
 "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \
 "Content-Type: text/xml; charset=utf-8\r\n" \
-"Cookie: MSPAuth=%s\r\n" \
-"Content-Length: %d\r\n" \
+"%s" \
+"Content-Length: %zd\r\n" \
 "Cache-Control: no-cache\r\n" \
 "\r\n" \
 "%s"
+
+
+#define SOAP_PASSPORT_SSO_URL "https://login.live.com/RST.srf"
+#define SOAP_PASSPORT_SSO_URL_MSN "https://msnia.login.live.com/pp550/RST.srf"
+
+#define SOAP_PASSPORT_SSO_PAYLOAD \
+"<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>" \
+           "<wst:RequestSecurityToken Id=\"RST1\">" \
+               "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \
+               "<wsp:AppliesTo>" \
+                   "<wsa:EndpointReference>" \
+                       "<wsa:Address>messengerclear.live.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 xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI\"></wsse:PolicyReference>" \
+           "</wst:RequestSecurityToken>" \
+       "</ps:RequestMultipleSecurityTokens>" \
+   "</Body>" \
+"</Envelope>"
+
+int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce );
 
 
