source: protocols/msn/passport.c @ c1a3c27

Last change on this file since c1a3c27 was 9186d15, checked in by Wilmer van der Gaast <wilmer@…>, at 2008-02-17T11:26:44Z

Automatically truncate MSN passports to 16 characters because that's the
maximum supported by MSN and giving a longer password will make the
authentication fail.

  • Property mode set to 100644
File size: 5.6 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       
[9186d15]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       
[e6648bf]60        return passport_get_token_real( mad );
[ad8b8a3]61}
62
[e6648bf]63static int passport_get_token_real( struct msn_auth_data *mad )
[ad8b8a3]64{
[e6648bf]65        char *post_payload, *post_request;
[ad8b8a3]66        struct http_request *req;
[e6648bf]67        url_t url;
[ad8b8a3]68       
[e6648bf]69        url_set( &url, mad->url );
[ad8b8a3]70       
[e6648bf]71        post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD,
72                                                mad->username,
73                                                mad->password,
74                                                mad->cookie );
[ad8b8a3]75       
[e6648bf]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 );
[ad8b8a3]83       
[e6648bf]84        g_free( post_request );
85        g_free( post_payload );
[ad8b8a3]86       
[e6648bf]87        return req != NULL;
[b7d3cc34]88}
89
[e6648bf]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 );
92
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 )
[ad8b8a3]100{
[e6648bf]101        struct msn_auth_data *mad = req->data;
102        struct xt_parser *parser;
[ad8b8a3]103       
[e6648bf]104        g_free( mad->url );
105        g_free( mad->error );
106        mad->url = mad->error = NULL;
[ad8b8a3]107       
[e6648bf]108        if( req->status_code == 200 )
[ad8b8a3]109        {
[e6648bf]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 );
[a2582c8]114        }
115        else
116        {
[e6648bf]117                mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code,
118                                              req->status_string ? req->status_string : "unknown" );
[ad8b8a3]119        }
120       
[e6648bf]121        if( mad->error == NULL && mad->token == NULL )
122                mad->error = g_strdup( "Could not parse Passport server response" );
[b7d3cc34]123       
[e6648bf]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        }
[b7d3cc34]140}
141
[e6648bf]142static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data )
[b7d3cc34]143{
[e6648bf]144        struct msn_auth_data *mad = data;
145        char *s;
[b7d3cc34]146       
[e6648bf]147        if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 )
148                mad->token = g_memdup( node->text, node->text_len + 1 );
[b7d3cc34]149       
[e6648bf]150        return XT_HANDLED;
[b7d3cc34]151}
152
[e6648bf]153static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data )
[b7d3cc34]154{
[e6648bf]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" );
[b7d3cc34]159       
[e6648bf]160        if( redirect && redirect->text_len && mad->ttl-- > 0 )
161                mad->url = g_memdup( redirect->text, redirect->text_len + 1 );
[a2582c8]162       
[e6648bf]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" );
[b7d3cc34]168       
[e6648bf]169        return XT_HANDLED;
[b7d3cc34]170}
Note: See TracBrowser for help on using the repository browser.