Ignore:
Timestamp:
2010-08-11T08:08:39Z (14 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
7f34ce2
Parents:
7db65b7
Message:

Implement MSNP15 SSO (Sadistic Sign-On).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/msn/soap.c

    r7db65b7 r523fb23  
    2828#include "url.h"
    2929#include "misc.h"
     30#include "sha1.h"
    3031#include "base64.h"
    3132#include "xmltree.h"
     
    8384static int msn_soap_send_request( struct msn_soap_req_data *soap_req )
    8485{
    85         struct msn_data *md = soap_req->ic->proto_data;
    8686        char *http_req;
    87         char *pom, *s;
     87        char *soap_action = NULL;
    8888        url_t url;
    8989       
    9090        soap_req->build_request( soap_req );
    9191       
    92         pom = g_new0( char, strlen( md->passport_token ) * 3 );
    93         strcpy( pom, md->passport_token + 2 );
    94         if( ( s = strchr( pom, '&' ) ) )
    95                 *s = '\0';
     92        if( soap_req->action )
     93                soap_action = g_strdup_printf( "SOAPAction: \"%s\"\r\n", soap_req->action );
    9694       
    9795        url_set( &url, soap_req->url );
    9896        http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host,
    99                 soap_req->action, pom,
     97                soap_action ? soap_action : "",
    10098                strlen( soap_req->payload ), soap_req->payload );
    10199       
     
    104102       
    105103        g_free( http_req );
     104        g_free( soap_action );
    106105       
    107106        return soap_req->http_req != NULL;
     
    140139
    141140
     141/* passport_sso: Authentication MSNP15+ */
     142
     143struct msn_soap_passport_sso_data
     144{
     145        char *policy;
     146        char *nonce;
     147        char *secret;
     148};
     149
     150static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req )
     151{
     152        struct msn_soap_passport_sso_data *sd = soap_req->data;
     153        struct im_connection *ic = soap_req->ic;
     154       
     155        soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL );
     156        soap_req->payload = g_markup_printf_escaped( SOAP_PASSPORT_SSO_PAYLOAD,
     157                ic->acc->user, ic->acc->pass, sd->policy );
     158       
     159        return MSN_SOAP_OK;
     160}
     161
     162static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer data )
     163{
     164        struct msn_soap_req_data *soap_req = data;
     165        struct msn_soap_passport_sso_data *sd = soap_req->data;
     166        struct msn_data *md = soap_req->ic->proto_data;
     167        struct xt_node *p;
     168        char *id;
     169       
     170        if( ( id = xt_find_attr( node, "Id" ) ) == NULL )
     171                return XT_HANDLED;
     172        id += strlen( id ) - 1;
     173        if( *id == '1' &&
     174            ( p = node->parent ) && ( p = p->parent ) &&
     175            ( p = xt_find_node( p->children, "wst:RequestedProofToken" ) ) &&
     176            ( p = xt_find_node( p->children, "wst:BinarySecret" ) ) &&
     177            p->text )
     178                sd->secret = g_strdup( p->text );
     179       
     180        if( *id == '1' )
     181                md->tokens[0] = g_strdup( node->text );
     182        else if( *id == '2' )
     183                md->tokens[1] = g_strdup( node->text );
     184       
     185        return XT_HANDLED;
     186}
     187
     188static const struct xt_handler_entry msn_soap_passport_sso_parser[] = {
     189        { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", msn_soap_passport_sso_token },
     190        { NULL, NULL, NULL }
     191};
     192
     193static char *msn_key_fuckery( char *key, int key_len, char *type )
     194{
     195        unsigned char hash1[20+strlen(type)+1];
     196        unsigned char hash2[20];
     197        char *ret;
     198       
     199        sha1_hmac( key, key_len, type, 0, hash1 );
     200        strcpy( (char*) hash1 + 20, type );
     201        sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash2 );
     202       
     203        /* This is okay as hash1 is read completely before it's overwritten. */
     204        sha1_hmac( key, key_len, (char*) hash1, 20, hash1 );
     205        sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash1 );
     206       
     207        ret = g_malloc( 24 );
     208        memcpy( ret, hash2, 20 );
     209        memcpy( ret + 20, hash1, 4 );
     210        return ret;
     211}
     212
     213static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap_req )
     214{
     215        struct msn_soap_passport_sso_data *sd = soap_req->data;
     216        struct im_connection *ic = soap_req->ic;
     217        char *key1, *key2, *key3, *blurb64;
     218        int key1_len;
     219        unsigned char *padnonce, *des3res;
     220        struct
     221        {
     222                unsigned int uStructHeaderSize; // 28. Does not count data
     223                unsigned int uCryptMode; // CRYPT_MODE_CBC (1)
     224                unsigned int uCipherType; // TripleDES (0x6603)
     225                unsigned int uHashType; // SHA1 (0x8004)
     226                unsigned int uIVLen;    // 8
     227                unsigned int uHashLen;  // 20
     228                unsigned int uCipherLen; // 72
     229                unsigned char iv[8];
     230                unsigned char hash[20];
     231                unsigned char cipherbytes[72];
     232        } blurb = {
     233                GUINT32_TO_LE( 28 ),
     234                GUINT32_TO_LE( 1 ),
     235                GUINT32_TO_LE( 0x6603 ),
     236                GUINT32_TO_LE( 0x8004 ),
     237                GUINT32_TO_LE( 8 ),
     238                GUINT32_TO_LE( 20 ),
     239                GUINT32_TO_LE( 72 ),
     240        };
     241
     242        key1_len = base64_decode( sd->secret, (unsigned char**) &key1 );
     243       
     244        key2 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY HASH" );
     245        key3 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY ENCRYPTION" );
     246       
     247        sha1_hmac( key2, 24, sd->nonce, 0, blurb.hash );
     248        padnonce = g_malloc( strlen( sd->nonce ) + 8 );
     249        strcpy( (char*) padnonce, sd->nonce );
     250        memset( padnonce + strlen( sd->nonce ), 8, 8 );
     251       
     252        random_bytes( blurb.iv, 8 );
     253       
     254        ssl_des3_encrypt( (unsigned char*) key3, 24, padnonce, strlen( sd->nonce ) + 8, blurb.iv, &des3res );
     255        memcpy( blurb.cipherbytes, des3res, 72 );
     256       
     257        blurb64 = base64_encode( (unsigned char*) &blurb, sizeof( blurb ) );
     258        msn_auth_got_passport_token( ic, blurb64 );
     259       
     260        g_free( padnonce );
     261        g_free( blurb64 );
     262        g_free( des3res );
     263        g_free( key1 );
     264        g_free( key2 );
     265        g_free( key3 );
     266       
     267        return MSN_SOAP_OK;
     268}
     269
     270static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req )
     271{
     272        struct msn_soap_passport_sso_data *sd = soap_req->data;
     273       
     274        g_free( sd->policy );
     275        g_free( sd->nonce );
     276        g_free( sd->secret );
     277       
     278        return MSN_SOAP_OK;
     279}
     280
     281int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce )
     282{
     283        struct msn_soap_passport_sso_data *sd = g_new0( struct msn_soap_passport_sso_data, 1 );
     284       
     285        sd->policy = g_strdup( policy );
     286        sd->nonce = g_strdup( nonce );
     287       
     288        return msn_soap_start( ic, sd, msn_soap_passport_sso_build_request,
     289                                       msn_soap_passport_sso_parser,
     290                                       msn_soap_passport_sso_handle_response,
     291                                       msn_soap_passport_sso_free_data );
     292}
     293
     294
    142295/* oim_send: Sending offline messages */
    143296
     
    162315        soap_req->action = g_strdup( SOAP_OIM_SEND_ACTION );
    163316        soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD,
    164                 ic->acc->user, display_name_b64, oim->to, md->passport_token,
     317                ic->acc->user, display_name_b64, oim->to, "bla", //md->passport_token,
    165318                MSNP11_PROD_ID, md->lock_key ? md->lock_key : "",
    166319                oim->number, oim->number, oim->msg );
     
    168321        g_free( display_name_b64 );
    169322       
    170         return 1;
     323        return MSN_SOAP_OK;
    171324}
    172325
     
    220373        g_free( oim );
    221374       
    222         return 0;
     375        return MSN_SOAP_OK;
    223376}
    224377
     
    263416                *msgq = g_slist_remove( *msgq, m );
    264417        }
     418       
     419        return 1;
    265420}
    266421
Note: See TracChangeset for help on using the changeset viewer.