source: protocols/msn/passport.c @ d3307e2

Last change on this file since d3307e2 was b7d3cc34, checked in by Wilmer van der Gaast <wilmer@…>, at 2005-11-06T18:23:18Z

Initial repository (0.99 release tree)

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[b7d3cc34]1/* passport.c
2 *
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>
6 *
7 * This program is free software; you can redistribute it and/or modify             
8 * it under the terms of the GNU General Public License version 2                   
9 * as published by the Free Software Foundation                                     
10 *                                                                                   
11 * This program is distributed in the hope that is will be useful,                 
12 * bit WITHOU ANY WARRANTY; without even the implied warranty of                   
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                   
14 * GNU General Public License for more details.                                     
15 *                                                                                   
16 * You should have received a copy of the GNU General Public License               
17 * along with this program; if not, write to the Free Software                     
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA         
19 *
20 */
21
22#include "ssl_client.h"
23#include "passport.h"
24#include "msn.h"
25#include "bitlbee.h"
26#include <ctype.h>
27#include <errno.h>
28
29#define MSN_BUF_LEN 8192
30
31static char *prd_cached = NULL;
32
33static char *passport_create_header( char *reply, char *email, char *pwd );
34static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header );
35static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond );
36static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url );
37static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond );
38static void destroy_reply( struct passport_reply *rep );
39
40
41int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func )
42{
43        char *header = passport_create_header( cookie, username, password );
44       
45        if( prd_cached )
46        {
47                int st;
48               
49                st = passport_get_id_from( data, func, header, prd_cached );
50                g_free( header );
51                return( st );
52        }
53        else
54        {
55                return( passport_retrieve_dalogin( data, func, header ) );
56        }
57}
58
59
60static char *passport_create_header( char *reply, char *email, char *pwd )
61{
62        char *buffer = g_new0( char, 2048 );
63        char *currenttoken;
64        char *email_enc, *pwd_enc;
65       
66        email_enc = g_new0( char, strlen( email ) * 3 + 1 );
67        strcpy( email_enc, email );
68        http_encode( email_enc );
69       
70        pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 );
71        strcpy( pwd_enc, pwd );
72        http_encode( pwd_enc );
73       
74        currenttoken = strstr( reply, "lc=" );
75        if( currenttoken == NULL )
76                return( NULL );
77       
78        g_snprintf( buffer, 2048,
79                    "Authorization: Passport1.4 OrgVerb=GET,"
80                    "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom,"
81                    "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc,
82                    currenttoken );
83       
84        g_free( email_enc );
85        g_free( pwd_enc );
86       
87        return( buffer );
88}
89
90
91static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header )
92{
93        struct passport_reply *rep = g_new0( struct passport_reply, 1 );
94        void *ssl;
95       
96        rep->data = data;
97        rep->func = func;
98        rep->header = header;
99       
100        ssl = ssl_connect( "nexus.passport.com", 443, passport_retrieve_dalogin_connected, rep );
101       
102        if( !ssl )
103                destroy_reply( rep );
104       
105        return( ssl != NULL );
106}
107
108#define PPR_BUFFERSIZE 2048
109#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n"
110static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond )
111{
112        int ret;
113        char buffer[PPR_BUFFERSIZE+1];
114        struct passport_reply *rep = data;
115       
116        if( !g_slist_find( msn_connections, rep->data ) )
117        {
118                if( ssl ) ssl_disconnect( ssl );
119                destroy_reply( rep );
120                return;
121        }
122       
123        if( !ssl )
124        {
125                rep->func( rep );
126                destroy_reply( rep );
127                return;
128        }
129       
130        ssl_write( ssl, PPR_REQUEST, strlen( PPR_REQUEST ) );
131       
132        if( ( ret = ssl_read( ssl, buffer, PPR_BUFFERSIZE ) ) <= 0 )
133        {
134                goto failure;
135        }
136
137        {
138                char *dalogin = strstr( buffer, "DALogin=" );
139                char *urlend;
140               
141                if( !dalogin )
142                        goto failure;
143               
144                dalogin += strlen( "DALogin=" );
145                urlend = strchr( dalogin, ',' );
146                if( urlend )
147                        *urlend = 0;
148               
149                /* strip the http(s):// part from the url */
150                urlend = strstr( urlend, "://" );
151                if( urlend )
152                        dalogin = urlend + strlen( "://" );
153               
154                if( prd_cached == NULL )
155                        prd_cached = g_strdup( dalogin );
156        }
157       
158        if( passport_get_id_from( rep->data, rep->func, rep->header, prd_cached ) )
159        {
160                ssl_disconnect( ssl );
161                destroy_reply( rep );
162                return;
163        }
164       
165failure:       
166        ssl_disconnect( ssl );
167        rep->func( rep );
168        destroy_reply( rep );
169}
170
171
172static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url )
173{
174        struct passport_reply *rep = g_new0( struct passport_reply, 1 );
175        char server[512], *dummy;
176        void *ssl;
177       
178        rep->data = data;
179        rep->func = func;
180        rep->redirects = 4;
181       
182        strncpy( server, url, 512 );
183        dummy = strchr( server, '/' );
184        if( dummy )
185                *dummy = 0;
186       
187        ssl = ssl_connect( server, 443, passport_get_id_connected, rep );
188       
189        if( ssl )
190        {
191                rep->header = g_strdup( header_i );
192                rep->url = g_strdup( url );
193        }
194        else
195        {
196                destroy_reply( rep );
197        }
198       
199        return( ssl != NULL );
200}
201
202#define PPG_BUFFERSIZE 4096
203static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond )
204{
205        struct passport_reply *rep = data;
206        char server[512], buffer[PPG_BUFFERSIZE+1], *dummy;
207        int ret;
208       
209        if( !g_slist_find( msn_connections, rep->data ) )
210        {
211                if( ssl ) ssl_disconnect( ssl );
212                destroy_reply( rep );
213                return;
214        }
215       
216        if( !ssl )
217        {
218                rep->func( rep );
219                destroy_reply( rep );
220                return;
221        }
222       
223        memset( buffer, 0, PPG_BUFFERSIZE + 1 );
224       
225        strncpy( server, rep->url, 512 );
226        dummy = strchr( server, '/' );
227        if( dummy == NULL )
228                goto end;
229       
230        g_snprintf( buffer, PPG_BUFFERSIZE - 1, "GET %s HTTP/1.0\r\n"
231                    "%s\r\n\r\n", dummy, rep->header );
232       
233        ssl_write( ssl, buffer, strlen( buffer ) );
234        memset( buffer, 0, PPG_BUFFERSIZE + 1 );
235       
236        {
237                char *buffer2 = buffer;
238               
239                while( ( ( ret = ssl_read( ssl, buffer2, 512 ) ) > 0 ) &&
240                       ( buffer + PPG_BUFFERSIZE - buffer2 - ret - 512 >= 0 ) )
241                {
242                        buffer2 += ret;
243                }
244        }
245       
246        if( *buffer == 0 )
247                goto end;
248       
249        if( ( dummy = strstr( buffer, "Location:" ) ) )
250        {
251                char *urlend;
252               
253                rep->redirects --;
254                if( rep->redirects == 0 )
255                        goto end;
256               
257                dummy += strlen( "Location:" );
258                while( isspace( *dummy ) ) dummy ++;
259                urlend = dummy;
260                while( !isspace( *urlend ) ) urlend ++;
261                *urlend = 0;
262                if( ( urlend = strstr( dummy, "://" ) ) )
263                        dummy = urlend + strlen( "://" );
264               
265                g_free( rep->url );
266                rep->url = g_strdup( dummy );
267               
268                strncpy( server, dummy, sizeof( server ) - 1 );
269                dummy = strchr( server, '/' );
270                if( dummy ) *dummy = 0;
271               
272                ssl_disconnect( ssl );
273               
274                if( ssl_connect( server, 443, passport_get_id_connected, rep ) )
275                {
276                        return;
277                }
278                else
279                {
280                        rep->func( rep );
281                        destroy_reply( rep );
282                        return;
283                }
284        }
285        else if( strstr( buffer, "200 OK" ) )
286        {
287                if( ( dummy = strstr( buffer, "from-PP='" ) ) )
288                {
289                        char *responseend;
290                       
291                        dummy += strlen( "from-PP='" );
292                        responseend = strchr( dummy, '\'' );
293                        if( responseend )
294                                *responseend = 0;
295                       
296                        rep->result = g_strdup( dummy );
297                }
298        }
299       
300end:
301        ssl_disconnect( ssl );
302        rep->func( rep );
303        destroy_reply( rep );
304}
305
306
307static void destroy_reply( struct passport_reply *rep )
308{
309        if( rep->result ) g_free( rep->result );
310        if( rep->url ) g_free( rep->url );
311        if( rep->header ) g_free( rep->header );
312        if( rep ) g_free( rep );
313}
Note: See TracBrowser for help on using the repository browser.