source: protocols/msn/passport.c @ e6648bf

Last change on this file since e6648bf was e6648bf, checked in by Wilmer van der Gaast <wilmer@…>, at 2008-02-17T11:16:01Z

Replaced old MSN Passport (v1.4) authentication code with what's described on
http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener . This was an
attempt to fix bug #360, but it didn't. However, this change may make BitlBee
a little bit more future-proof. Plus, the code is tidier and sometimes faster
than the old mechanism.

  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[e6648bf]1/** passport.c
[b7d3cc34]2 *
[e6648bf]3 * Functions to login to Microsoft Passport service for Messenger
4 * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net>
[b7d3cc34]5 *
6 * This program is free software; you can redistribute it and/or modify             
7 * it under the terms of the GNU General Public License version 2                   
8 * as published by the Free Software Foundation                                     
9 *                                                                                   
10 * This program is distributed in the hope that is will be useful,                 
11 * bit WITHOU ANY WARRANTY; without even the implied warranty of                   
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                   
13 * GNU General Public License for more details.                                     
14 *                                                                                   
15 * You should have received a copy of the GNU General Public License               
16 * along with this program; if not, write to the Free Software                     
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA         
18 *
19 */
20
[ad8b8a3]21#include "http_client.h"
[b7d3cc34]22#include "passport.h"
23#include "msn.h"
24#include "bitlbee.h"
[e6648bf]25#include "url.h"
26#include "misc.h"
27#include "xmltree.h"
[b7d3cc34]28#include <ctype.h>
29#include <errno.h>
30
[e6648bf]31static int passport_get_token_real( struct msn_auth_data *mad );
32static void passport_get_token_ready( struct http_request *req );
[b7d3cc34]33
[e6648bf]34int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie )
[b7d3cc34]35{
[e6648bf]36        struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 );
37        int i;
[b7d3cc34]38       
[e6648bf]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        return passport_get_token_real( mad );
[ad8b8a3]56}
57
[e6648bf]58static int passport_get_token_real( struct msn_auth_data *mad )
[ad8b8a3]59{
[e6648bf]60        char *post_payload, *post_request;
[ad8b8a3]61        struct http_request *req;
[e6648bf]62        url_t url;
[ad8b8a3]63       
[e6648bf]64        url_set( &url, mad->url );
[ad8b8a3]65       
[e6648bf]66        post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD,
67                                                mad->username,
68                                                mad->password,
69                                                mad->cookie );
[ad8b8a3]70       
[e6648bf]71        post_request = g_strdup_printf( SOAP_AUTHENTICATION_REQUEST,
72                                        url.file, url.host,
73                                        (int) strlen( post_payload ),
74                                        post_payload );
75                                       
76        req = http_dorequest( url.host, url.port, 1, post_request,
77                              passport_get_token_ready, mad );
[ad8b8a3]78       
[e6648bf]79        g_free( post_request );
80        g_free( post_payload );
[ad8b8a3]81       
[e6648bf]82        return req != NULL;
[b7d3cc34]83}
84
[e6648bf]85static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data );
86static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data );
87
88static const struct xt_handler_entry passport_xt_handlers[] = {
89        { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", passport_xt_extract_token },
90        { "S:Fault",                  "S:Envelope",                 passport_xt_handle_fault  },
91        { NULL,                       NULL,                         NULL                      }
92};
93
94static void passport_get_token_ready( struct http_request *req )
[ad8b8a3]95{
[e6648bf]96        struct msn_auth_data *mad = req->data;
97        struct xt_parser *parser;
[ad8b8a3]98       
[e6648bf]99        g_free( mad->url );
100        g_free( mad->error );
101        mad->url = mad->error = NULL;
[ad8b8a3]102       
[e6648bf]103        if( req->status_code == 200 )
[ad8b8a3]104        {
[e6648bf]105                parser = xt_new( passport_xt_handlers, mad );
106                xt_feed( parser, req->reply_body, req->body_size );
107                xt_handle( parser, NULL, -1 );
108                xt_free( parser );
[a2582c8]109        }
110        else
111        {
[e6648bf]112                mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code,
113                                              req->status_string ? req->status_string : "unknown" );
[ad8b8a3]114        }
115       
[e6648bf]116        if( mad->error == NULL && mad->token == NULL )
117                mad->error = g_strdup( "Could not parse Passport server response" );
[b7d3cc34]118       
[e6648bf]119        if( mad->url && mad->token == NULL )
120        {
121                passport_get_token_real( mad );
122        }
123        else
124        {
125                mad->callback( mad );
126               
127                g_free( mad->url );
128                g_free( mad->username );
129                g_free( mad->password );
130                g_free( mad->cookie );
131                g_free( mad->token );
132                g_free( mad->error );
133                g_free( mad );
134        }
[b7d3cc34]135}
136
[e6648bf]137static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data )
[b7d3cc34]138{
[e6648bf]139        struct msn_auth_data *mad = data;
140        char *s;
[b7d3cc34]141       
[e6648bf]142        if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 )
143                mad->token = g_memdup( node->text, node->text_len + 1 );
[b7d3cc34]144       
[e6648bf]145        return XT_HANDLED;
[b7d3cc34]146}
147
[e6648bf]148static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data )
[b7d3cc34]149{
[e6648bf]150        struct msn_auth_data *mad = data;
151        struct xt_node *code = xt_find_node( node->children, "faultcode" );
152        struct xt_node *string = xt_find_node( node->children, "faultstring" );
153        struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" );
[b7d3cc34]154       
[e6648bf]155        if( redirect && redirect->text_len && mad->ttl-- > 0 )
156                mad->url = g_memdup( redirect->text, redirect->text_len + 1 );
[a2582c8]157       
[e6648bf]158        if( code == NULL || code->text_len == 0 )
159                mad->error = g_strdup( "Unknown error" );
160        else
161                mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ?
162                                              string->text : "no description available" );
[b7d3cc34]163       
[e6648bf]164        return XT_HANDLED;
[b7d3cc34]165}
Note: See TracBrowser for help on using the repository browser.