source: protocols/msn/passport.c @ 31dbb90a

Last change on this file since 31dbb90a was f8ec890, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-05-15T00:20:33Z

Passport 3.0 authentication turns out to be slightly different from what
the msnpiki MSNP13 doc says and stuff is breaking now. This should fix
the main problem now.

  • Property mode set to 100644
File size: 5.7 KB
RevLine 
[d84e2a9]1/** passport.c
[b7d3cc34]2 *
[d84e2a9]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"
[d84e2a9]25#include "url.h"
26#include "misc.h"
27#include "xmltree.h"
[b7d3cc34]28#include <ctype.h>
29#include <errno.h>
30
[d84e2a9]31static int passport_get_token_real( struct msn_auth_data *mad );
32static void passport_get_token_ready( struct http_request *req );
[b7d3cc34]33
[d84e2a9]34int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie )
[ad8b8a3]35{
[d84e2a9]36        struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 );
37        int i;
[ad8b8a3]38       
[d84e2a9]39        mad->username = g_strdup( username );
40        mad->password = g_strdup( password );
41        mad->cookie = g_strdup( cookie );
[ad8b8a3]42       
[d84e2a9]43        mad->callback = func;
44        mad->data = data;
[ad8b8a3]45       
[d84e2a9]46        mad->url = g_strdup( SOAP_AUTHENTICATION_URL );
47        mad->ttl = 3; /* Max. # of redirects. */
[ad8b8a3]48       
[d84e2a9]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] = '&';
[ad8b8a3]54       
[d84e2a9]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;
[0f4c2734]59       
[d84e2a9]60        return passport_get_token_real( mad );
[b7d3cc34]61}
62
[d84e2a9]63static int passport_get_token_real( struct msn_auth_data *mad )
[b7d3cc34]64{
[d84e2a9]65        char *post_payload, *post_request;
66        struct http_request *req;
67        url_t url;
[0f4c2734]68       
[d84e2a9]69        url_set( &url, mad->url );
[0f4c2734]70       
[d84e2a9]71        post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD,
72                                                mad->username,
73                                                mad->password,
74                                                mad->cookie );
[b7d3cc34]75       
[d84e2a9]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 );
[b7d3cc34]83       
[d84e2a9]84        g_free( post_request );
85        g_free( post_payload );
[0f4c2734]86       
[d84e2a9]87        return req != NULL;
[b7d3cc34]88}
89
[d84e2a9]90static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data );
91static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data );
[0f4c2734]92
[d84e2a9]93static 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
99static void passport_get_token_ready( struct http_request *req )
[0f4c2734]100{
[d84e2a9]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;
[0f4c2734]107       
[d84e2a9]108        if( req->status_code == 200 )
[0f4c2734]109        {
[d84e2a9]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 );
[0f4c2734]114        }
[d84e2a9]115        else
[0f4c2734]116        {
[d84e2a9]117                mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code,
118                                              req->status_string ? req->status_string : "unknown" );
[0f4c2734]119        }
[b7d3cc34]120       
[d84e2a9]121        if( mad->error == NULL && mad->token == NULL )
122                mad->error = g_strdup( "Could not parse Passport server response" );
[0f4c2734]123       
[d84e2a9]124        if( mad->url && mad->token == NULL )
[0f4c2734]125        {
[d84e2a9]126                passport_get_token_real( mad );
[0f4c2734]127        }
[d84e2a9]128        else
[0f4c2734]129        {
[d84e2a9]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 );
[0f4c2734]139        }
[d84e2a9]140}
141
142static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data )
143{
144        struct msn_auth_data *mad = data;
145        char *s;
146       
[f8ec890]147        if( ( s = xt_find_attr( node, "Id" ) ) &&
148            ( strncmp( s, "Compact", 7 ) == 0 ||
149              strncmp( s, "PPToken", 7 ) == 0 ) )
[d84e2a9]150                mad->token = g_memdup( node->text, node->text_len + 1 );
[0f4c2734]151       
[d84e2a9]152        return XT_HANDLED;
[0f4c2734]153}
154
[d84e2a9]155static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data )
[0f4c2734]156{
[d84e2a9]157        struct msn_auth_data *mad = data;
158        struct xt_node *code = xt_find_node( node->children, "faultcode" );
159        struct xt_node *string = xt_find_node( node->children, "faultstring" );
160        struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" );
161       
162        if( redirect && redirect->text_len && mad->ttl-- > 0 )
163                mad->url = g_memdup( redirect->text, redirect->text_len + 1 );
164       
165        if( code == NULL || code->text_len == 0 )
166                mad->error = g_strdup( "Unknown error" );
167        else
168                mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ?
169                                              string->text : "no description available" );
170       
171        return XT_HANDLED;
[b7d3cc34]172}
Note: See TracBrowser for help on using the repository browser.