aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/msn/passport.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/msn/passport.c')
-rw-r--r--protocols/msn/passport.c313
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 );
+}