aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2010-08-11 09:08:39 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2010-08-11 09:08:39 +0100
commit523fb2324a351e9607ad2a803c6e866c5175aa16 (patch)
tree52e1d753a149196a50630415d51bb22f46b9b94e
parent7db65b7df08a3c7cab28e065b2ffa3d9941ceccb (diff)
Implement MSNP15 SSO (Sadistic Sign-On).
-rw-r--r--lib/sha1.c47
-rw-r--r--lib/sha1.h1
-rw-r--r--lib/ssl_client.h2
-rw-r--r--lib/ssl_openssl.c24
-rw-r--r--protocols/msn/Makefile2
-rw-r--r--protocols/msn/msn.c3
-rw-r--r--protocols/msn/msn.h3
-rw-r--r--protocols/msn/msn_util.c41
-rw-r--r--protocols/msn/ns.c32
-rw-r--r--protocols/msn/sb.c6
-rw-r--r--protocols/msn/soap.c175
-rw-r--r--protocols/msn/soap.h71
12 files changed, 343 insertions, 64 deletions
diff --git a/lib/sha1.c b/lib/sha1.c
index ee4fcc19..7ee90640 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -35,6 +35,7 @@
*
*/
+#include <string.h>
#include "sha1.h"
/*
@@ -373,3 +374,49 @@ static void sha1_pad(sha1_state_t * context)
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 );
+}
diff --git a/lib/sha1.h b/lib/sha1.h
index 4ef8ac92..a87410eb 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -66,5 +66,6 @@ typedef struct SHA1Context {
G_MODULE_EXPORT int sha1_init(sha1_state_t *);
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
diff --git a/lib/ssl_client.h b/lib/ssl_client.h
index 0a8e82d8..787d528a 100644
--- a/lib/ssl_client.h
+++ b/lib/ssl_client.h
@@ -77,3 +77,5 @@ G_MODULE_EXPORT int ssl_getfd( void *conn );
adding an event handler to the queue. (And it should perform exactly
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);
diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c
index 8abff390..1c70eb0f 100644
--- a/lib/ssl_openssl.c
+++ b/lib/ssl_openssl.c
@@ -271,3 +271,27 @@ b_input_condition ssl_getdirection( void *conn )
{
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;
+}
diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile
index b9c7ed28..28fe81c9 100644
--- a/protocols/msn/Makefile
+++ b/protocols/msn/Makefile
@@ -42,4 +42,4 @@ msn_mod.o: $(objects)
@echo '*' Linking msn_mod.o
@$(LD) $(LFLAGS) $(objects) -o msn_mod.o
-
+soap.o: soap.h soap.c
diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c
index 6222e1b6..10c27a1d 100644
--- a/protocols/msn/msn.c
+++ b/protocols/msn/msn.c
@@ -102,7 +102,8 @@ static void msn_logout( struct im_connection *ic )
while( md->groupcount > 0 )
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 );
while( md->grpq )
diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h
index f060000a..d4f3442e 100644
--- a/protocols/msn/msn.h
+++ b/protocols/msn/msn.h
@@ -75,7 +75,7 @@ struct msn_data
struct msn_handler_data *handler;
int trId;
- char *passport_token;
+ char *tokens[2];
char *lock_key;
GSList *msgq, *grpq;
@@ -170,6 +170,7 @@ extern GSList *msn_switchboards;
/* 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 */
int msn_write( struct im_connection *ic, char *s, int len );
diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c
index 954ee716..65b12476 100644
--- a/protocols/msn/msn_util.c
+++ b/protocols/msn/msn_util.c
@@ -33,6 +33,12 @@ int msn_write( struct im_connection *ic, char *s, int len )
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 );
if( st != len )
{
@@ -280,6 +286,12 @@ int msn_handler( struct msn_handler_data *h )
if( st <= 0 )
return( -1 );
+ if( getenv( "BITLBEE_DEBUG" ) )
+ {
+ write( 2, "->C:", 4 );
+ write( 2, h->rxq + h->rxlen - st, st );
+ }
+
while( st )
{
int i;
@@ -445,27 +457,6 @@ gboolean msn_set_display_name( struct im_connection *ic, const char *rawname )
return msn_write( ic, buf, strlen( buf ) ) != 0;
}
-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 )
{
@@ -486,7 +477,7 @@ char *msn_p11_challenge( char *challenge )
md5Parts = (unsigned int *)md5Hash;
for (i = 0; i < 4; i ++)
{
- md5Parts[i] = little_endian(md5Parts[i]);
+ md5Parts[i] = GUINT32_TO_LE(md5Parts[i]);
/* & each integer with 0x7FFFFFFF */
/* and save one unmodified array for later */
@@ -507,8 +498,8 @@ char *msn_p11_challenge( char *challenge )
{
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;
nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF;
@@ -524,7 +515,7 @@ char *msn_p11_challenge( char *challenge )
/* 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 */
newHash = (unsigned char *)newHashParts;
diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c
index 8236b731..f0d6a58d 100644
--- a/protocols/msn/ns.c
+++ b/protocols/msn/ns.c
@@ -34,7 +34,6 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c
static int msn_ns_command( gpointer data, char **cmd, int num_parts );
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 );
gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
@@ -73,7 +72,7 @@ gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
md->handler->fd = md->fd;
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 ) ) )
{
ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic );
@@ -113,7 +112,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
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" );
imc_logout( ic, FALSE );
@@ -127,7 +126,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
else if( strcmp( cmd[0], "CVR" ) == 0 )
{
/* 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 ) ) );
}
else if( strcmp( cmd[0], "XFR" ) == 0 )
@@ -220,15 +219,10 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
}
else if( strcmp( cmd[0], "USR" ) == 0 )
{
- if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 )
+ if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 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 );
- }
+ msn_soap_passport_sso_request( ic, cmd[4], cmd[5] );
}
else if( strcmp( cmd[2], "OK" ) == 0 )
{
@@ -774,9 +768,8 @@ static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int
return( 1 );
}
-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;
/* Dead connection? */
@@ -784,20 +777,13 @@ static void msn_auth_got_passport_token( struct msn_auth_data *mad )
return;
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 );
- }
}
static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c
index 1eb919e3..07e94072 100644
--- a/protocols/msn/sb.c
+++ b/protocols/msn/sb.c
@@ -39,6 +39,12 @@ int msn_sb_write( struct msn_switchboard *sb, char *s, int len )
{
int st;
+ if( getenv( "BITLBEE_DEBUG" ) )
+ {
+ write( 2, "->SB:", 5 );
+ write( 2, s, len );
+ }
+
st = write( sb->fd, s, len );
if( st != len )
{
diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c
index 252bddeb..e837986e 100644
--- a/protocols/msn/soap.c
+++ b/protocols/msn/soap.c
@@ -27,6 +27,7 @@
#include "bitlbee.h"
#include "url.h"
#include "misc.h"
+#include "sha1.h"
#include "base64.h"
#include "xmltree.h"
#include <ctype.h>
@@ -82,27 +83,25 @@ static void msn_soap_handle_response( struct http_request *http_req );
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 );
soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS,
http_req, msn_soap_handle_response, soap_req );
g_free( http_req );
+ g_free( soap_action );
return soap_req->http_req != NULL;
}
@@ -139,6 +138,160 @@ static void msn_soap_handle_response( struct http_request *http_req )
}
+/* 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 */
struct msn_soap_oim_send_data
@@ -161,13 +314,13 @@ static int msn_soap_oim_build_request( struct msn_soap_req_data *soap_req )
soap_req->url = g_strdup( SOAP_OIM_SEND_URL );
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 );
g_free( display_name_b64 );
- return 1;
+ return MSN_SOAP_OK;
}
static xt_status msn_soap_oim_send_challenge( struct xt_node *node, gpointer data )
@@ -219,7 +372,7 @@ static int msn_soap_oim_free_data( struct msn_soap_req_data *soap_req )
g_free( oim->msg );
g_free( oim );
- return 0;
+ return MSN_SOAP_OK;
}
int msn_soap_oim_send( struct im_connection *ic, const char *to, const char *msg )
@@ -262,6 +415,8 @@ int msn_soap_oim_send_queue( struct im_connection *ic, GSList **msgq )
*msgq = g_slist_remove( *msgq, m );
}
+
+ return 1;
}
diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h
index 78808fdf..5fbac3c4 100644
--- a/protocols/msn/soap.h
+++ b/protocols/msn/soap.h
@@ -42,16 +42,81 @@
"POST %s HTTP/1.0\r\n" \
"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 );
+
+
#define SOAP_OIM_SEND_URL "https://ows.messenger.msn.com/OimWS/oim.asmx"
#define SOAP_OIM_SEND_ACTION "http://messenger.msn.com/ws/2004/09/oim/Store"