aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2011-07-31 16:44:37 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2011-07-31 16:44:37 +0100
commite1c926f53750ca288f30f3d62eecdc763b67d642 (patch)
tree4e45932aebdf449131ca714ebf51e925840955d7
parent39a939ce4ef6717d65c36c97e6a7adf05b125cad (diff)
Facebook authentication. This isn't really OAuth in the end: FB doesn't
really support desktop app OAuth in a way that would work with BitlBee. Plus, it's only OAuth-compliant by, err, name?
-rw-r--r--lib/md5.c1
-rw-r--r--protocols/jabber/jabber.h2
-rw-r--r--protocols/jabber/sasl.c51
3 files changed, 52 insertions, 2 deletions
diff --git a/lib/md5.c b/lib/md5.c
index e989ac6a..355f5495 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <string.h> /* for memcpy() */
+#include <stdio.h>
#include "md5.h"
static void md5_transform(uint32_t buf[4], uint32_t const in[16]);
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 8d65a7e3..c68ae343 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -46,6 +46,8 @@ typedef enum
activates all XEP-85 related code. */
JFLAG_XMLCONSOLE = 64, /* If the user added an xmlconsole buddy. */
JFLAG_STARTTLS_DONE = 128, /* If a plaintext session was converted to TLS. */
+
+ JFLAG_SASL_FB = 0x10000, /* Trying Facebook authentication. */
} jabber_flags_t;
typedef enum
diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c
index a7c3dd6f..89571d8d 100644
--- a/protocols/jabber/sasl.c
+++ b/protocols/jabber/sasl.c
@@ -26,6 +26,7 @@
#include "jabber.h"
#include "base64.h"
#include "oauth2.h"
+#include "oauth.h"
xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )
{
@@ -33,7 +34,7 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )
struct jabber_data *jd = ic->proto_data;
struct xt_node *c, *reply;
char *s;
- int sup_plain = 0, sup_digest = 0, sup_oauth2 = 0;
+ int sup_plain = 0, sup_digest = 0, sup_oauth2 = 0, sup_fb = 0;
if( !sasl_supported( ic ) )
{
@@ -61,6 +62,8 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )
sup_digest = 1;
if( c->text && g_strcasecmp( c->text, "X-OAUTH2" ) == 0 )
sup_oauth2 = 1;
+ if( c->text && g_strcasecmp( c->text, "X-FACEBOOK-PLATFORM" ) == 0 )
+ sup_fb = 1;
c = c->next;
}
@@ -101,6 +104,11 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )
reply->text_len = strlen( reply->text );
g_free( s );
}
+ else if( sup_fb && strstr( ic->acc->pass, "session_key=" ) )
+ {
+ xt_add_attr( reply, "mechanism", "X-FACEBOOK-PLATFORM" );
+ jd->flags |= JFLAG_SASL_FB;
+ }
else if( sup_digest )
{
xt_add_attr( reply, "mechanism", "DIGEST-MD5" );
@@ -238,7 +246,45 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data )
dec = frombase64( node->text );
- if( !( s = sasl_get_part( dec, "rspauth" ) ) )
+ if( jd->flags & JFLAG_SASL_FB )
+ {
+ GSList *p_in = NULL, *p_out = NULL, *p;
+ md5_state_t md5;
+ char time[33], *fmt, *token;
+ const char *secret;
+
+ oauth_params_parse( &p_in, dec );
+ oauth_params_add( &p_out, "nonce", oauth_params_get( &p_in, "nonce" ) );
+ oauth_params_add( &p_out, "method", oauth_params_get( &p_in, "method" ) );
+ oauth_params_free( &p_in );
+
+ token = g_strdup( ic->acc->pass );
+ oauth_params_parse( &p_in, token );
+ g_free( token );
+ oauth_params_add( &p_out, "session_key", oauth_params_get( &p_in, "session_key" ) );
+
+ g_snprintf( time, sizeof( time ), "%lld", (long long) ( gettime() * 1000 ) );
+ oauth_params_add( &p_out, "call_id", time );
+ oauth_params_add( &p_out, "api_key", oauth2_service_facebook.consumer_key );
+ oauth_params_add( &p_out, "v", "1.0" );
+ oauth_params_add( &p_out, "format", "XML" );
+
+ md5_init( &md5 );
+ for( p = p_out; p; p = p->next )
+ md5_append( &md5, p->data, strlen( p->data ) );
+
+ secret = oauth_params_get( &p_in, "secret" );
+ md5_append( &md5, (unsigned char*) secret, strlen( secret ) );
+ md5_finish_ascii( &md5, time );
+ oauth_params_add( &p_out, "sig", time );
+
+ fmt = oauth_params_string( p_out );
+ oauth_params_free( &p_out );
+ oauth_params_free( &p_in );
+ s = tobase64( fmt );
+ g_free( fmt );
+ }
+ else if( !( s = sasl_get_part( dec, "rspauth" ) ) )
{
/* See RFC 2831 for for information. */
md5_state_t A1, A2, H;
@@ -444,6 +490,7 @@ static void sasl_oauth2_got_token( gpointer data, const char *access_token, cons
{
imcb_error( ic, "OAuth failure (missing access token)" );
imc_logout( ic, TRUE );
+ return;
}
if( refresh_token != NULL )
{