diff options
Diffstat (limited to 'protocols/msn/passport.c')
-rw-r--r-- | protocols/msn/passport.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c new file mode 100644 index 00000000..640126a0 --- /dev/null +++ b/protocols/msn/passport.c @@ -0,0 +1,313 @@ +/* passport.c + * + * Functions to login to microsoft passport service for Messenger + * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be> + * Copyright (C) 2004 Wilmer van der Gaast <wilmer@gaast.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that is will be useful, + * bit WITHOU ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "ssl_client.h" +#include "passport.h" +#include "msn.h" +#include "bitlbee.h" +#include <ctype.h> +#include <errno.h> + +#define MSN_BUF_LEN 8192 + +static char *prd_cached = NULL; + +static char *passport_create_header( char *reply, char *email, char *pwd ); +static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ); +static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond ); +static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url ); +static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond ); +static void destroy_reply( struct passport_reply *rep ); + + +int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func ) +{ + char *header = passport_create_header( cookie, username, password ); + + if( prd_cached ) + { + int st; + + st = passport_get_id_from( data, func, header, prd_cached ); + g_free( header ); + return( st ); + } + else + { + return( passport_retrieve_dalogin( data, func, header ) ); + } +} + + +static char *passport_create_header( char *reply, char *email, char *pwd ) +{ + char *buffer = g_new0( char, 2048 ); + char *currenttoken; + char *email_enc, *pwd_enc; + + email_enc = g_new0( char, strlen( email ) * 3 + 1 ); + strcpy( email_enc, email ); + http_encode( email_enc ); + + pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 ); + strcpy( pwd_enc, pwd ); + http_encode( pwd_enc ); + + currenttoken = strstr( reply, "lc=" ); + if( currenttoken == NULL ) + return( NULL ); + + g_snprintf( buffer, 2048, + "Authorization: Passport1.4 OrgVerb=GET," + "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom," + "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc, + currenttoken ); + + g_free( email_enc ); + g_free( pwd_enc ); + + return( buffer ); +} + + +static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ) +{ + struct passport_reply *rep = g_new0( struct passport_reply, 1 ); + void *ssl; + + rep->data = data; + rep->func = func; + rep->header = header; + + ssl = ssl_connect( "nexus.passport.com", 443, passport_retrieve_dalogin_connected, rep ); + + if( !ssl ) + destroy_reply( rep ); + + return( ssl != NULL ); +} + +#define PPR_BUFFERSIZE 2048 +#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n" +static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond ) +{ + int ret; + char buffer[PPR_BUFFERSIZE+1]; + struct passport_reply *rep = data; + + if( !g_slist_find( msn_connections, rep->data ) ) + { + if( ssl ) ssl_disconnect( ssl ); + destroy_reply( rep ); + return; + } + + if( !ssl ) + { + rep->func( rep ); + destroy_reply( rep ); + return; + } + + ssl_write( ssl, PPR_REQUEST, strlen( PPR_REQUEST ) ); + + if( ( ret = ssl_read( ssl, buffer, PPR_BUFFERSIZE ) ) <= 0 ) + { + goto failure; + } + + { + char *dalogin = strstr( buffer, "DALogin=" ); + char *urlend; + + if( !dalogin ) + goto failure; + + dalogin += strlen( "DALogin=" ); + urlend = strchr( dalogin, ',' ); + if( urlend ) + *urlend = 0; + + /* strip the http(s):// part from the url */ + urlend = strstr( urlend, "://" ); + if( urlend ) + dalogin = urlend + strlen( "://" ); + + if( prd_cached == NULL ) + prd_cached = g_strdup( dalogin ); + } + + if( passport_get_id_from( rep->data, rep->func, rep->header, prd_cached ) ) + { + ssl_disconnect( ssl ); + destroy_reply( rep ); + return; + } + +failure: + ssl_disconnect( ssl ); + rep->func( rep ); + destroy_reply( rep ); +} + + +static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url ) +{ + struct passport_reply *rep = g_new0( struct passport_reply, 1 ); + char server[512], *dummy; + void *ssl; + + rep->data = data; + rep->func = func; + rep->redirects = 4; + + strncpy( server, url, 512 ); + dummy = strchr( server, '/' ); + if( dummy ) + *dummy = 0; + + ssl = ssl_connect( server, 443, passport_get_id_connected, rep ); + + if( ssl ) + { + rep->header = g_strdup( header_i ); + rep->url = g_strdup( url ); + } + else + { + destroy_reply( rep ); + } + + return( ssl != NULL ); +} + +#define PPG_BUFFERSIZE 4096 +static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond ) +{ + struct passport_reply *rep = data; + char server[512], buffer[PPG_BUFFERSIZE+1], *dummy; + int ret; + + if( !g_slist_find( msn_connections, rep->data ) ) + { + if( ssl ) ssl_disconnect( ssl ); + destroy_reply( rep ); + return; + } + + if( !ssl ) + { + rep->func( rep ); + destroy_reply( rep ); + return; + } + + memset( buffer, 0, PPG_BUFFERSIZE + 1 ); + + strncpy( server, rep->url, 512 ); + dummy = strchr( server, '/' ); + if( dummy == NULL ) + goto end; + + g_snprintf( buffer, PPG_BUFFERSIZE - 1, "GET %s HTTP/1.0\r\n" + "%s\r\n\r\n", dummy, rep->header ); + + ssl_write( ssl, buffer, strlen( buffer ) ); + memset( buffer, 0, PPG_BUFFERSIZE + 1 ); + + { + char *buffer2 = buffer; + + while( ( ( ret = ssl_read( ssl, buffer2, 512 ) ) > 0 ) && + ( buffer + PPG_BUFFERSIZE - buffer2 - ret - 512 >= 0 ) ) + { + buffer2 += ret; + } + } + + if( *buffer == 0 ) + goto end; + + if( ( dummy = strstr( buffer, "Location:" ) ) ) + { + char *urlend; + + rep->redirects --; + if( rep->redirects == 0 ) + goto end; + + dummy += strlen( "Location:" ); + while( isspace( *dummy ) ) dummy ++; + urlend = dummy; + while( !isspace( *urlend ) ) urlend ++; + *urlend = 0; + if( ( urlend = strstr( dummy, "://" ) ) ) + dummy = urlend + strlen( "://" ); + + g_free( rep->url ); + rep->url = g_strdup( dummy ); + + strncpy( server, dummy, sizeof( server ) - 1 ); + dummy = strchr( server, '/' ); + if( dummy ) *dummy = 0; + + ssl_disconnect( ssl ); + + if( ssl_connect( server, 443, passport_get_id_connected, rep ) ) + { + return; + } + else + { + rep->func( rep ); + destroy_reply( rep ); + return; + } + } + else if( strstr( buffer, "200 OK" ) ) + { + if( ( dummy = strstr( buffer, "from-PP='" ) ) ) + { + char *responseend; + + dummy += strlen( "from-PP='" ); + responseend = strchr( dummy, '\'' ); + if( responseend ) + *responseend = 0; + + rep->result = g_strdup( dummy ); + } + } + +end: + ssl_disconnect( ssl ); + rep->func( rep ); + destroy_reply( rep ); +} + + +static void destroy_reply( struct passport_reply *rep ) +{ + if( rep->result ) g_free( rep->result ); + if( rep->url ) g_free( rep->url ); + if( rep->header ) g_free( rep->header ); + if( rep ) g_free( rep ); +} |