Changeset 0f4c2734


Ignore:
Timestamp:
2008-07-31T20:44:43Z (11 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
e0798cc
Parents:
718e05f
Message:

Reverting to the old MSN/Passport authentication mechanism, the new one
is "broken". (Bug #439)

Location:
protocols/msn
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • protocols/msn/ns.c

    r718e05f r0f4c2734  
    3434static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
    3535
    36 static void msn_auth_got_passport_token( struct msn_auth_data *mad );
     36static void msn_auth_got_passport_id( struct passport_reply *rep );
    3737
    3838gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
     
    222222                {
    223223                        /* Time for some Passport black magic... */
    224                         if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) )
     224                        if( !passport_get_id( msn_auth_got_passport_id, ic, ic->acc->user, ic->acc->pass, cmd[4] ) )
    225225                        {
    226226                                imcb_error( ic, "Error while contacting Passport server" );
     
    709709}
    710710
    711 static void msn_auth_got_passport_token( struct msn_auth_data *mad )
     711static void msn_auth_got_passport_id( struct passport_reply *rep )
    712712{
    713         struct im_connection *ic = mad->data;
    714         struct msn_data *md;
    715        
    716         /* Dead connection? */
    717         if( g_slist_find( msn_connections, ic ) == NULL )
    718                 return;
    719        
    720         md = ic->proto_data;
    721         if( mad->token )
    722         {
    723                 char buf[1024];
    724                
    725                 g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token );
     713        struct im_connection *ic = rep->data;
     714        struct msn_data *md = ic->proto_data;
     715        char *key = rep->result;
     716        char buf[1024];
     717       
     718        if( key == NULL )
     719        {
     720                imcb_error( ic, "Error during Passport authentication (%s)",
     721                               rep->error_string ? rep->error_string : "Unknown error" );
     722                imc_logout( ic, TRUE );
     723        }
     724        else
     725        {
     726                g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, key );
    726727                msn_write( ic, buf, strlen( buf ) );
    727728        }
    728         else
    729         {
    730                 imcb_error( ic, "Error during Passport authentication: %s", mad->error );
    731                 imc_logout( ic, TRUE );
    732         }
    733729}
  • protocols/msn/passport.c

    r718e05f r0f4c2734  
    1 /** passport.c
     1/* passport.c
    22 *
    3  * Functions to login to Microsoft Passport service for Messenger
    4  * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net>
     3 * Functions to login to microsoft passport service for Messenger
     4 * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be>
     5 * Copyright (C) 2004 Wilmer van der Gaast <wilmer@gaast.net>
    56 *
    67 * This program is free software; you can redistribute it and/or modify             
     
    2324#include "msn.h"
    2425#include "bitlbee.h"
    25 #include "url.h"
    26 #include "misc.h"
    27 #include "xmltree.h"
    2826#include <ctype.h>
    2927#include <errno.h>
    3028
    31 static int passport_get_token_real( struct msn_auth_data *mad );
    32 static void passport_get_token_ready( struct http_request *req );
    33 
    34 int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie )
    35 {
    36         struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 );
    37         int i;
    38        
    39         mad->username = g_strdup( username );
    40         mad->password = g_strdup( password );
    41         mad->cookie = g_strdup( cookie );
    42        
    43         mad->callback = func;
    44         mad->data = data;
    45        
    46         mad->url = g_strdup( SOAP_AUTHENTICATION_URL );
    47         mad->ttl = 3; /* Max. # of redirects. */
    48        
    49         /* HTTP-escape stuff and s/,/&/ */
    50         http_decode( mad->cookie );
    51         for( i = 0; mad->cookie[i]; i ++ )
    52                 if( mad->cookie[i] == ',' )
    53                         mad->cookie[i] = '&';
    54        
    55         /* Microsoft doesn't allow password longer than 16 chars and silently
    56            fails authentication if you give the "full version" of your passwd. */
    57         if( strlen( mad->password ) > MAX_PASSPORT_PWLEN )
    58                 mad->password[MAX_PASSPORT_PWLEN] = 0;
    59        
    60         return passport_get_token_real( mad );
    61 }
    62 
    63 static int passport_get_token_real( struct msn_auth_data *mad )
    64 {
    65         char *post_payload, *post_request;
     29#define MSN_BUF_LEN 8192
     30
     31static char *prd_cached = NULL;
     32
     33static int passport_get_id_real( gpointer func, gpointer data, char *header );
     34static void passport_get_id_ready( struct http_request *req );
     35
     36static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header );
     37static void passport_retrieve_dalogin_ready( struct http_request *req );
     38
     39static char *passport_create_header( char *cookie, char *email, char *pwd );
     40static void destroy_reply( struct passport_reply *rep );
     41
     42int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie )
     43{
     44        char *header = passport_create_header( cookie, username, password );
     45       
     46        if( prd_cached == NULL )
     47                return passport_retrieve_dalogin( func, data, header );
     48        else
     49                return passport_get_id_real( func, data, header );
     50}
     51
     52static int passport_get_id_real( gpointer func, gpointer data, char *header )
     53{
     54        struct passport_reply *rep;
     55        char *server, *dummy, *reqs;
    6656        struct http_request *req;
    67         url_t url;
    68        
    69         url_set( &url, mad->url );
    70        
    71         post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD,
    72                                                 mad->username,
    73                                                 mad->password,
    74                                                 mad->cookie );
    75        
    76         post_request = g_strdup_printf( SOAP_AUTHENTICATION_REQUEST,
    77                                         url.file, url.host,
    78                                         (int) strlen( post_payload ),
    79                                         post_payload );
    80                                        
    81         req = http_dorequest( url.host, url.port, 1, post_request,
    82                               passport_get_token_ready, mad );
    83        
    84         g_free( post_request );
    85         g_free( post_payload );
    86        
    87         return req != NULL;
    88 }
    89 
    90 static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data );
    91 static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data );
    92 
    93 static const struct xt_handler_entry passport_xt_handlers[] = {
    94         { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", passport_xt_extract_token },
    95         { "S:Fault",                  "S:Envelope",                 passport_xt_handle_fault  },
    96         { NULL,                       NULL,                         NULL                      }
    97 };
    98 
    99 static void passport_get_token_ready( struct http_request *req )
    100 {
    101         struct msn_auth_data *mad = req->data;
    102         struct xt_parser *parser;
    103        
    104         g_free( mad->url );
    105         g_free( mad->error );
    106         mad->url = mad->error = NULL;
    107        
    108         if( req->status_code == 200 )
    109         {
    110                 parser = xt_new( passport_xt_handlers, mad );
    111                 xt_feed( parser, req->reply_body, req->body_size );
    112                 xt_handle( parser, NULL, -1 );
    113                 xt_free( parser );
     57       
     58        rep = g_new0( struct passport_reply, 1 );
     59        rep->data = data;
     60        rep->func = func;
     61        rep->header = header;
     62       
     63        server = g_strdup( prd_cached );
     64        dummy = strchr( server, '/' );
     65       
     66        if( dummy == NULL )
     67        {
     68                destroy_reply( rep );
     69                return( 0 );
     70        }
     71       
     72        reqs = g_strdup_printf( "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header );
     73       
     74        *dummy = 0;
     75        req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep );
     76       
     77        g_free( server );
     78        g_free( reqs );
     79       
     80        if( req == NULL )
     81                destroy_reply( rep );
     82       
     83        return( req != NULL );
     84}
     85
     86static void passport_get_id_ready( struct http_request *req )
     87{
     88        struct passport_reply *rep = req->data;
     89       
     90        if( !g_slist_find( msn_connections, rep->data ) )
     91        {
     92                destroy_reply( rep );
     93                return;
     94        }
     95       
     96        if( req->finished && req->reply_headers && req->status_code == 200 )
     97        {
     98                char *dummy;
     99               
     100                if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) )
     101                {
     102                        char *responseend;
     103                       
     104                        dummy += strlen( "from-PP='" );
     105                        responseend = strchr( dummy, '\'' );
     106                        if( responseend )
     107                                *responseend = 0;
     108                       
     109                        rep->result = g_strdup( dummy );
     110                }
     111                else
     112                {
     113                        rep->error_string = g_strdup( "Could not parse Passport server response" );
     114                }
    114115        }
    115116        else
    116117        {
    117                 mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code,
    118                                               req->status_string ? req->status_string : "unknown" );
    119         }
    120        
    121         if( mad->error == NULL && mad->token == NULL )
    122                 mad->error = g_strdup( "Could not parse Passport server response" );
    123        
    124         if( mad->url && mad->token == NULL )
    125         {
    126                 passport_get_token_real( mad );
    127         }
    128         else
    129         {
    130                 mad->callback( mad );
    131                
    132                 g_free( mad->url );
    133                 g_free( mad->username );
    134                 g_free( mad->password );
    135                 g_free( mad->cookie );
    136                 g_free( mad->token );
    137                 g_free( mad->error );
    138                 g_free( mad );
    139         }
    140 }
    141 
    142 static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data )
    143 {
    144         struct msn_auth_data *mad = data;
    145         char *s;
    146        
    147         if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 )
    148                 mad->token = g_memdup( node->text, node->text_len + 1 );
    149        
    150         return XT_HANDLED;
    151 }
    152 
    153 static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data )
    154 {
    155         struct msn_auth_data *mad = data;
    156         struct xt_node *code = xt_find_node( node->children, "faultcode" );
    157         struct xt_node *string = xt_find_node( node->children, "faultstring" );
    158         struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" );
    159        
    160         if( redirect && redirect->text_len && mad->ttl-- > 0 )
    161                 mad->url = g_memdup( redirect->text, redirect->text_len + 1 );
    162        
    163         if( code == NULL || code->text_len == 0 )
    164                 mad->error = g_strdup( "Unknown error" );
    165         else
    166                 mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ?
    167                                               string->text : "no description available" );
    168        
    169         return XT_HANDLED;
    170 }
     118                rep->error_string = g_strdup_printf( "HTTP error: %s",
     119                                      req->status_string ? req->status_string : "Unknown error" );
     120        }
     121       
     122        rep->func( rep );
     123        destroy_reply( rep );
     124}
     125
     126static char *passport_create_header( char *cookie, char *email, char *pwd )
     127{
     128        char *buffer;
     129        char *currenttoken;
     130        char *email_enc, *pwd_enc;
     131       
     132        currenttoken = strstr( cookie, "lc=" );
     133        if( currenttoken == NULL )
     134                return NULL;
     135       
     136        email_enc = g_new0( char, strlen( email ) * 3 + 1 );
     137        strcpy( email_enc, email );
     138        http_encode( email_enc );
     139       
     140        pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 );
     141        g_snprintf( pwd_enc, 17, "%s", pwd ); /* Passwords >16 chars never succeed. (Bug #360) */
     142        strcpy( pwd_enc, pwd );
     143        http_encode( pwd_enc );
     144       
     145        buffer = g_strdup_printf( "Authorization: Passport1.4 OrgVerb=GET,"
     146                                  "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom,"
     147                                  "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc,
     148                                  currenttoken );
     149       
     150        g_free( email_enc );
     151        g_free( pwd_enc );
     152       
     153        return buffer;
     154}
     155
     156static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header )
     157{
     158        struct passport_reply *rep = g_new0( struct passport_reply, 1 );
     159        struct http_request *req;
     160       
     161        rep->data = data;
     162        rep->func = func;
     163        rep->header = header;
     164       
     165        req = http_dorequest_url( "https://nexus.passport.com/rdr/pprdr.asp", passport_retrieve_dalogin_ready, rep );
     166       
     167        if( !req )
     168                destroy_reply( rep );
     169       
     170        return( req != NULL );
     171}
     172
     173static void passport_retrieve_dalogin_ready( struct http_request *req )
     174{
     175        struct passport_reply *rep = req->data;
     176        char *dalogin;
     177        char *urlend;
     178       
     179        if( !g_slist_find( msn_connections, rep->data ) )
     180        {
     181                destroy_reply( rep );
     182                return;
     183        }
     184       
     185        if( !req->finished || !req->reply_headers || req->status_code != 200 )
     186        {
     187                rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin: %s",
     188                                        req->status_string ? req->status_string : "Unknown error" );
     189                goto failure;
     190        }
     191       
     192        dalogin = strstr( req->reply_headers, "DALogin=" );     
     193       
     194        if( !dalogin )
     195        {
     196                rep->error_string = g_strdup( "Parse error while fetching DALogin" );
     197                goto failure;
     198        }
     199       
     200        dalogin += strlen( "DALogin=" );
     201        urlend = strchr( dalogin, ',' );
     202        if( urlend )
     203                *urlend = 0;
     204       
     205        /* strip the http(s):// part from the url */
     206        urlend = strstr( urlend, "://" );
     207        if( urlend )
     208                dalogin = urlend + strlen( "://" );
     209       
     210        if( prd_cached == NULL )
     211                prd_cached = g_strdup( dalogin );
     212       
     213        if( passport_get_id_real( rep->func, rep->data, rep->header ) )
     214        {
     215                rep->header = NULL;
     216                destroy_reply( rep );
     217                return;
     218        }
     219       
     220failure:       
     221        rep->func( rep );
     222        destroy_reply( rep );
     223}
     224
     225static void destroy_reply( struct passport_reply *rep )
     226{
     227        g_free( rep->result );
     228        g_free( rep->header );
     229        g_free( rep->error_string );
     230        g_free( rep );
     231}
  • protocols/msn/passport.h

    r718e05f r0f4c2734  
     1#ifndef __PASSPORT_H__
     2#define __PASSPORT_H__
    13/* passport.h
    24 *
    3  * Functions to login to Microsoft Passport service for Messenger
    4  * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net>
     5 * Functions to login to Microsoft Passport Service for Messenger
     6 * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be>,
     7 *                    Wilmer van der Gaast <wilmer@gaast.net>
    58 *
    69 * This program is free software; you can redistribute it and/or modify             
     
    1518 * You should have received a copy of the GNU General Public License               
    1619 * along with this program; if not, write to the Free Software                     
    17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA         
     20 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA         
    1821 */
    19 
    20 /* Thanks to http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener
    21    for the specs! */
    22 
    23 #ifndef __PASSPORT_H__
    24 #define __PASSPORT_H__
    2522
    2623#include <stdio.h>
     
    3633#include "nogaim.h"
    3734
    38 #define MAX_PASSPORT_PWLEN 16
    39 
    40 struct msn_auth_data
     35struct passport_reply
    4136{
    42         char *url;
    43         int ttl;
    44        
    45         char *username;
    46         char *password;
    47         char *cookie;
    48        
    49         /* The end result, the only thing we'll really be interested in
    50            once finished. */
    51         char *token;
    52         char *error; /* Yeah, or that... */
    53        
    54         void (*callback)( struct msn_auth_data *mad );
    55         gpointer data;
     37        void (*func)( struct passport_reply * );
     38        void *data;
     39        char *result;
     40        char *header;
     41        char *error_string;
    5642};
    5743
    58 #define SOAP_AUTHENTICATION_URL "https://loginnet.passport.com/RST.srf"
    59 
    60 #define SOAP_AUTHENTICATION_REQUEST \
    61 "POST %s HTTP/1.0\r\n" \
    62 "Accept: text/*\r\n" \
    63 "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \
    64 "Host: %s\r\n" \
    65 "Content-Length: %d\r\n" \
    66 "Cache-Control: no-cache\r\n" \
    67 "\r\n" \
    68 "%s"
    69 
    70 #define SOAP_AUTHENTICATION_PAYLOAD \
    71 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
    72 "<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\">" \
    73   "<Header>" \
    74     "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">" \
    75       "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>" \
    76       "<ps:BinaryVersion>4</ps:BinaryVersion>" \
    77       "<ps:UIVersion>1</ps:UIVersion>" \
    78       "<ps:Cookies></ps:Cookies>" \
    79       "<ps:RequestParams>AQAAAAIAAABsYwQAAAAzMDg0</ps:RequestParams>" \
    80     "</ps:AuthInfo>" \
    81     "<wsse:Security>" \
    82        "<wsse:UsernameToken Id=\"user\">" \
    83          "<wsse:Username>%s</wsse:Username>" \
    84          "<wsse:Password>%s</wsse:Password>" \
    85        "</wsse:UsernameToken>" \
    86     "</wsse:Security>" \
    87   "</Header>" \
    88   "<Body>" \
    89     "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">" \
    90       "<wst:RequestSecurityToken Id=\"RST0\">" \
    91         "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \
    92         "<wsp:AppliesTo>" \
    93           "<wsa:EndpointReference>" \
    94             "<wsa:Address>http://Passport.NET/tb</wsa:Address>" \
    95           "</wsa:EndpointReference>" \
    96         "</wsp:AppliesTo>" \
    97       "</wst:RequestSecurityToken>" \
    98       "<wst:RequestSecurityToken Id=\"RST1\">" \
    99        "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \
    100         "<wsp:AppliesTo>" \
    101           "<wsa:EndpointReference>" \
    102             "<wsa:Address>messenger.msn.com</wsa:Address>" \
    103           "</wsa:EndpointReference>" \
    104         "</wsp:AppliesTo>" \
    105         "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>" \
    106       "</wst:RequestSecurityToken>" \
    107     "</ps:RequestMultipleSecurityTokens>" \
    108   "</Body>" \
    109 "</Envelope>"
    110 
    111 int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie );
     44int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie );
    11245
    11346#endif /* __PASSPORT_H__ */
Note: See TracChangeset for help on using the changeset viewer.