Changeset devel,411

Show
Ignore:
Timestamp:
2008-07-31T20:44:43Z (2 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
branch-nick:
devel
revision id:
wilmer@gaast.net-20080731204443-lvon6xxb8erdw240
Message:

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

Location:
devel/protocols/msn
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • devel/protocols/msn/ns.c

    r405 r411  
    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} 
  • devel/protocols/msn/passport.c

    r336 r411  
    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} 
  • devel/protocols/msn/passport.h

    r336 r411  
     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__ */