aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2010-05-01 14:53:59 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2010-05-01 14:53:59 +0100
commitc2ecadc08daa5163f4c90aef36de0e33d0d44f16 (patch)
treea88c01b58c6ec593f47b6efffec5be6d80555737
parent85ef57f94436f23447c0d8603b52977824381854 (diff)
Cleaned up OAuth stuff: consumer key/secret should *not* be in lib/oauth.c.
Keep it in the Twitter module, and use the oauth_info struct through the whole session to keep all this together.
-rw-r--r--lib/oauth.c91
-rw-r--r--lib/oauth.h22
-rw-r--r--protocols/twitter/twitter.c46
-rw-r--r--protocols/twitter/twitter.h5
-rw-r--r--protocols/twitter/twitter_http.c10
-rw-r--r--protocols/twitter/twitter_http.h4
-rw-r--r--protocols/twitter/twitter_lib.c12
7 files changed, 98 insertions, 92 deletions
diff --git a/lib/oauth.c b/lib/oauth.c
index 4a465a2f..4c93cbf4 100644
--- a/lib/oauth.c
+++ b/lib/oauth.c
@@ -32,14 +32,10 @@
#include "url.h"
#include "oauth.h"
-#define CONSUMER_KEY "xsDNKJuNZYkZyMcu914uEA"
-#define CONSUMER_SECRET "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo"
-/* How can it be a secret if it's right here in the source code? No clue... */
-
#define HMAC_BLOCK_SIZE 64
static char *oauth_sign( const char *method, const char *url,
- const char *params, const char *token_secret )
+ const char *params, struct oauth_info *oi )
{
sha1_state_t sha1;
uint8_t hash[sha1_hash_size];
@@ -50,20 +46,20 @@ static char *oauth_sign( const char *method, const char *url,
/* Create K. If our current key is >64 chars we have to hash it,
otherwise just pad. */
memset( key, 0, HMAC_BLOCK_SIZE );
- i = strlen( CONSUMER_SECRET ) + 1 + ( token_secret ? strlen( token_secret ) : 0 );
+ i = strlen( oi->sp->consumer_secret ) + 1 + ( oi->token_secret ? strlen( oi->token_secret ) : 0 );
if( i > HMAC_BLOCK_SIZE )
{
sha1_init( &sha1 );
- sha1_append( &sha1, (uint8_t*) CONSUMER_SECRET, strlen( CONSUMER_SECRET ) );
+ sha1_append( &sha1, (uint8_t*) oi->sp->consumer_secret, strlen( oi->sp->consumer_secret ) );
sha1_append( &sha1, (uint8_t*) "&", 1 );
- if( token_secret )
- sha1_append( &sha1, (uint8_t*) token_secret, strlen( token_secret ) );
+ if( oi->token_secret )
+ sha1_append( &sha1, (uint8_t*) oi->token_secret, strlen( oi->token_secret ) );
sha1_finish( &sha1, key );
}
else
{
g_snprintf( (gchar*) key, HMAC_BLOCK_SIZE + 1, "%s&%s",
- CONSUMER_SECRET, token_secret ? : "" );
+ oi->sp->consumer_secret, oi->token_secret ? : "" );
}
/* Inner part: H(K XOR 0x36, text) */
@@ -228,18 +224,19 @@ void oauth_info_free( struct oauth_info *info )
{
if( info )
{
- g_free( info->auth_params );
+ g_free( info->auth_url );
g_free( info->request_token );
- g_free( info->access_token );
+ g_free( info->token );
+ g_free( info->token_secret );
g_free( info );
}
}
-static void oauth_add_default_params( GSList **params )
+static void oauth_add_default_params( GSList **params, struct oauth_service *sp )
{
char *s;
- oauth_params_set( params, "oauth_consumer_key", CONSUMER_KEY );
+ oauth_params_set( params, "oauth_consumer_key", sp->consumer_key );
oauth_params_set( params, "oauth_signature_method", "HMAC-SHA1" );
s = g_strdup_printf( "%d", (int) time( NULL ) );
@@ -253,7 +250,7 @@ static void oauth_add_default_params( GSList **params )
oauth_params_set( params, "oauth_version", "1.0" );
}
-static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, void *data )
+static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, struct oauth_info *oi )
{
GSList *params = NULL;
char *s, *params_s, *post;
@@ -269,12 +266,12 @@ static void *oauth_post_request( const char *url, GSList **params_, http_input_f
if( params_ )
params = *params_;
- oauth_add_default_params( &params );
+ oauth_add_default_params( &params, oi->sp );
params_s = oauth_params_string( params );
oauth_params_free( &params );
- s = oauth_sign( "POST", url, params_s, NULL );
+ s = oauth_sign( "POST", url, params_s, oi );
post = g_strdup_printf( "%s&oauth_signature=%s", params_s, s );
g_free( params_s );
g_free( s );
@@ -288,7 +285,7 @@ static void *oauth_post_request( const char *url, GSList **params_, http_input_f
g_free( post );
req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS,
- s, func, data );
+ s, func, oi );
g_free( s );
return req;
@@ -296,17 +293,18 @@ static void *oauth_post_request( const char *url, GSList **params_, http_input_f
static void oauth_request_token_done( struct http_request *req );
-struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data )
+struct oauth_info *oauth_request_token( struct oauth_service *sp, oauth_cb func, void *data )
{
struct oauth_info *st = g_new0( struct oauth_info, 1 );
GSList *params = NULL;
st->func = func;
st->data = data;
+ st->sp = sp;
oauth_params_add( &params, "oauth_callback", "oob" );
- if( !oauth_post_request( url, &params, oauth_request_token_done, st ) )
+ if( !oauth_post_request( sp->url_request_token, &params, oauth_request_token_done, st ) )
{
oauth_info_free( st );
return NULL;
@@ -325,28 +323,26 @@ static void oauth_request_token_done( struct http_request *req )
{
GSList *params = NULL;
- st->auth_params = g_strdup( req->reply_body );
- oauth_params_parse( &params, st->auth_params );
+ st->auth_url = g_strdup_printf( "%s?%s", st->sp->url_authorize, req->reply_body );
+ oauth_params_parse( &params, req->reply_body );
st->request_token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
oauth_params_free( &params );
}
st->stage = OAUTH_REQUEST_TOKEN;
- if( !st->func( st ) )
- oauth_info_free( st );
+ st->func( st );
}
static void oauth_access_token_done( struct http_request *req );
-void oauth_access_token( const char *url, const char *pin, struct oauth_info *st )
+gboolean oauth_access_token( const char *pin, struct oauth_info *st )
{
GSList *params = NULL;
oauth_params_add( &params, "oauth_token", st->request_token );
oauth_params_add( &params, "oauth_verifier", pin );
- if( !oauth_post_request( url, &params, oauth_access_token_done, st ) )
- oauth_info_free( st );
+ return oauth_post_request( st->sp->url_access_token, &params, oauth_access_token_done, st ) != NULL;
}
static void oauth_access_token_done( struct http_request *req )
@@ -358,39 +354,32 @@ static void oauth_access_token_done( struct http_request *req )
if( req->status_code == 200 )
{
GSList *params = NULL;
- const char *token, *token_secret;
oauth_params_parse( &params, req->reply_body );
- token = oauth_params_get( &params, "oauth_token" );
- token_secret = oauth_params_get( &params, "oauth_token_secret" );
- st->access_token = g_strdup_printf(
- "oauth_token=%s&oauth_token_secret=%s", token, token_secret );
+ st->token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
+ st->token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
oauth_params_free( &params );
}
st->stage = OAUTH_ACCESS_TOKEN;
- st->func( st );
- oauth_info_free( st );
+ if( st->func( st ) )
+ {
+ /* Don't need these anymore, but keep the rest. */
+ g_free( st->auth_url );
+ st->auth_url = NULL;
+ g_free( st->request_token );
+ st->request_token = NULL;
+ }
}
-char *oauth_http_header( char *access_token, const char *method, const char *url, char *args )
+char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args )
{
GSList *params = NULL, *l;
- char *token_secret = NULL, *sig = NULL, *params_s, *s;
+ char *sig = NULL, *params_s, *s;
GString *ret = NULL;
- /* First, get the two pieces of info from the access token that we need. */
- oauth_params_parse( &params, access_token );
- if( params == NULL )
- goto err;
-
- /* Pick out the token secret, we shouldn't include it but use it for signing. */
- token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
- if( token_secret == NULL )
- goto err;
- oauth_params_del( &params, "oauth_token_secret" );
-
- oauth_add_default_params( &params );
+ oauth_params_add( &params, "oauth_token", oi->token );
+ oauth_add_default_params( &params, oi->sp );
/* Start building the OAuth header. 'key="value", '... */
ret = g_string_new( "OAuth " );
@@ -420,20 +409,18 @@ char *oauth_http_header( char *access_token, const char *method, const char *url
if( ( s = strchr( url, '?' ) ) )
{
s = g_strdup( s + 1 );
- oauth_params_parse( &params, s + 1 );
+ oauth_params_parse( &params, s );
g_free( s );
}
/* Append the signature and we're done! */
params_s = oauth_params_string( params );
- sig = oauth_sign( method, url, params_s, token_secret );
+ sig = oauth_sign( method, url, params_s, oi );
g_string_append_printf( ret, "oauth_signature=\"%s\"", sig );
g_free( params_s );
-err:
oauth_params_free( &params );
g_free( sig );
- g_free( token_secret );
return ret ? g_string_free( ret, FALSE ) : NULL;
}
diff --git a/lib/oauth.h b/lib/oauth.h
index a61650cc..849375be 100644
--- a/lib/oauth.h
+++ b/lib/oauth.h
@@ -39,36 +39,48 @@ typedef enum
struct oauth_info
{
oauth_stage_t stage;
+ struct oauth_service *sp;
oauth_cb func;
void *data;
struct http_request *http;
- char *auth_params;
+ char *auth_url;
char *request_token;
- char *access_token;
+ char *token;
+ char *token_secret;
+};
+
+struct oauth_service
+{
+ char *url_request_token;
+ char *url_access_token;
+ char *url_authorize;
+
+ char *consumer_key;
+ char *consumer_secret;
};
/* http://oauth.net/core/1.0a/#auth_step1 (section 6.1)
Request an initial anonymous token which can be used to construct an
authorization URL for the user. This is passed to the callback function
in a struct oauth_info. */
-struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data );
+struct oauth_info *oauth_request_token( struct oauth_service *sp, oauth_cb func, void *data );
/* http://oauth.net/core/1.0a/#auth_step3 (section 6.3)
The user gets a PIN or so which we now exchange for the final access
token. This is passed to the callback function in the same
struct oauth_info. */
-void oauth_access_token( const char *url, const char *pin, struct oauth_info *st );
+gboolean oauth_access_token( const char *pin, struct oauth_info *st );
/* http://oauth.net/core/1.0a/#anchor12 (section 7)
Generate an OAuth Authorization: HTTP header. access_token should be
saved/fetched using the functions above. args can be a string with
whatever's going to be in the POST body of the request. GET args will
automatically be grabbed from url. */
-char *oauth_http_header( char *access_token, const char *method, const char *url, char *args );
+char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args );
/* Shouldn't normally be required unless the process is aborted by the user. */
void oauth_info_free( struct oauth_info *info );
diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c
index f5baeeea..6d43d819 100644
--- a/protocols/twitter/twitter.c
+++ b/protocols/twitter/twitter.c
@@ -27,7 +27,6 @@
#include "twitter_http.h"
#include "twitter_lib.h"
-
/**
* Main loop function
*/
@@ -65,6 +64,16 @@ static void twitter_main_loop_start( struct im_connection *ic )
td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic);
}
+
+static struct oauth_service twitter_oauth =
+{
+ "http://api.twitter.com/oauth/request_token",
+ "http://api.twitter.com/oauth/access_token",
+ "http://api.twitter.com/oauth/authorize",
+ .consumer_key = "xsDNKJuNZYkZyMcu914uEA",
+ .consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo",
+};
+
static gboolean twitter_oauth_callback( struct oauth_info *info );
static void twitter_oauth_start( struct im_connection *ic )
@@ -73,8 +82,7 @@ static void twitter_oauth_start( struct im_connection *ic )
imcb_log( ic, "Requesting OAuth request token" );
- td->oauth_info = oauth_request_token(
- TWITTER_OAUTH_REQUEST_TOKEN, twitter_oauth_callback, ic );
+ td->oauth_info = oauth_request_token( &twitter_oauth, twitter_oauth_callback, ic );
}
static gboolean twitter_oauth_callback( struct oauth_info *info )
@@ -99,26 +107,24 @@ static gboolean twitter_oauth_callback( struct oauth_info *info )
sprintf( name, "twitter_%s", ic->acc->user );
msg = g_strdup_printf( "To finish OAuth authentication, please visit "
- "%s?%s and respond with the resulting PIN code.",
- TWITTER_OAUTH_AUTHORIZE, info->auth_params );
+ "%s and respond with the resulting PIN code.",
+ info->auth_url );
imcb_buddy_msg( ic, name, msg, 0, 0 );
g_free( msg );
}
else if( info->stage == OAUTH_ACCESS_TOKEN )
{
- if( info->access_token == NULL )
+ if( info->token == NULL )
{
imcb_error( ic, "OAuth error: %s", info->http->status_string );
imc_logout( ic, TRUE );
return FALSE;
}
- td->oauth = g_strdup( info->access_token );
-
/* IM mods didn't do this so far and it's ugly but I should
be able to get away with it... */
- g_free( ic->acc->pass );
- ic->acc->pass = g_strdup( info->access_token );
+ //g_free( ic->acc->pass );
+ //ic->acc->pass = g_strdup( info->access_token );
twitter_main_loop_start( ic );
}
@@ -126,6 +132,7 @@ static gboolean twitter_oauth_callback( struct oauth_info *info )
return TRUE;
}
+
static char *set_eval_mode( set_t *set, char *value )
{
if( g_strcasecmp( value, "one" ) == 0 ||
@@ -163,15 +170,15 @@ static void twitter_login( account_t *acc )
td->user = acc->user;
if( !set_getbool( &acc->set, "oauth" ) )
td->pass = g_strdup( acc->pass );
- else if( strstr( acc->pass, "oauth_token=" ) )
- td->oauth = g_strdup( acc->pass );
+ //else if( strstr( acc->pass, "oauth_token=" ) )
+ // td->oauth = g_strdup( acc->pass );
td->home_timeline_id = 0;
sprintf( name, "twitter_%s", acc->user );
imcb_add_buddy( ic, name, NULL );
imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
- if( td->pass || td->oauth )
+ if( td->pass || td->oauth_info )
twitter_main_loop_start( ic );
else
twitter_oauth_start( ic );
@@ -196,9 +203,7 @@ static void twitter_logout( struct im_connection *ic )
if( td )
{
oauth_info_free( td->oauth_info );
-
g_free( td->pass );
- g_free( td->oauth );
g_free( td );
}
@@ -215,10 +220,15 @@ static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message
if (g_strncasecmp(who, "twitter_", 8) == 0 &&
g_strcasecmp(who + 8, ic->acc->user) == 0)
{
- if( set_getbool( &ic->acc->set, "oauth" ) && td->oauth_info )
+ if( set_getbool( &ic->acc->set, "oauth" ) &&
+ td->oauth_info && td->oauth_info->token == NULL )
{
- oauth_access_token( TWITTER_OAUTH_ACCESS_TOKEN, message, td->oauth_info );
- td->oauth_info = NULL;
+ if( !oauth_access_token( message, td->oauth_info ) )
+ {
+ imcb_error( ic, "OAuth error: %s", "Failed to send access token request" );
+ imc_logout( ic, TRUE );
+ return FALSE;
+ }
}
else
twitter_post_status(ic, message);
diff --git a/protocols/twitter/twitter.h b/protocols/twitter/twitter.h
index 9c046b66..24f61e42 100644
--- a/protocols/twitter/twitter.h
+++ b/protocols/twitter/twitter.h
@@ -36,7 +36,6 @@ struct twitter_data
{
char* user;
char* pass;
- char* oauth;
struct oauth_info *oauth_info;
guint64 home_timeline_id;
gint main_loop_id;
@@ -51,8 +50,4 @@ struct twitter_data
*/
GSList *twitter_connections;
-#define TWITTER_OAUTH_REQUEST_TOKEN "http://api.twitter.com/oauth/request_token"
-#define TWITTER_OAUTH_ACCESS_TOKEN "http://api.twitter.com/oauth/access_token"
-#define TWITTER_OAUTH_AUTHORIZE "http://api.twitter.com/oauth/authorize"
-
#endif //_TWITTER_H
diff --git a/protocols/twitter/twitter_http.c b/protocols/twitter/twitter_http.c
index 93e315fa..51f437df 100644
--- a/protocols/twitter/twitter_http.c
+++ b/protocols/twitter/twitter_http.c
@@ -28,7 +28,6 @@
* *
****************************************************************************/
-#include "twitter_http.h"
#include "twitter.h"
#include "bitlbee.h"
#include "url.h"
@@ -38,6 +37,8 @@
#include <ctype.h>
#include <errno.h>
+#include "twitter_http.h"
+
char *twitter_url_append(char *url, char *key, char* value);
@@ -45,7 +46,7 @@ char *twitter_url_append(char *url, char *key, char* value);
* Do a request.
* This is actually pretty generic function... Perhaps it should move to the lib/http_client.c
*/
-void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, char* oauth_token, char** arguments, int arguments_len)
+void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, struct oauth_info* oi, char** arguments, int arguments_len)
{
url_t *url = g_new0( url_t, 1 );
char *tmp;
@@ -110,12 +111,11 @@ void *twitter_http(char *url_string, http_input_function func, gpointer data, in
is_post ? "POST" : "GET", url->file, url->host );
// If a pass and user are given we append them to the request.
- if (oauth_token)
+ if (oi)
{
char *full_header;
- full_header = oauth_http_header(oauth_token,
- is_post ? "POST" : "GET",
+ full_header = oauth_http_header(oi, is_post ? "POST" : "GET",
url_string, url_arguments);
tmp = g_strdup_printf("%sAuthorization: %s\r\n", request, full_header);
diff --git a/protocols/twitter/twitter_http.h b/protocols/twitter/twitter_http.h
index 1e29fb99..5ef2530f 100644
--- a/protocols/twitter/twitter_http.h
+++ b/protocols/twitter/twitter_http.h
@@ -27,8 +27,10 @@
#include "nogaim.h"
#include "http_client.h"
+struct oauth_info;
+
void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post,
- char* user, char* pass, char *oauth_token, char** arguments, int arguments_len);
+ char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);
#endif //_TWITTER_HTTP_H
diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c
index c91f8bbf..ee6e39fe 100644
--- a/protocols/twitter/twitter_lib.c
+++ b/protocols/twitter/twitter_lib.c
@@ -129,7 +129,7 @@ void twitter_get_friends_ids(struct im_connection *ic, int next_cursor)
char* args[2];
args[0] = "cursor";
args[1] = g_strdup_printf ("%d", next_cursor);
- twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth, args, 2);
+ twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
g_free(args[1]);
}
@@ -395,7 +395,7 @@ void twitter_get_home_timeline(struct im_connection *ic, int next_cursor)
args[3] = g_strdup_printf ("%llu", (long long unsigned int) td->home_timeline_id);
}
- twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, td->oauth, args, td->home_timeline_id ? 4 : 2);
+ twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, td->oauth_info, args, td->home_timeline_id ? 4 : 2);
g_free(args[1]);
if (td->home_timeline_id) {
@@ -509,7 +509,7 @@ static void twitter_http_get_home_timeline(struct http_request *req)
if (req->status_code == 200)
{
td->http_fails = 0;
- if (!ic->flags & OPT_LOGGED_IN)
+ if (!(ic->flags & OPT_LOGGED_IN))
imcb_connected(ic);
}
else if (req->status_code == 401)
@@ -619,7 +619,7 @@ void twitter_get_statuses_friends(struct im_connection *ic, int next_cursor)
args[0] = "cursor";
args[1] = g_strdup_printf ("%d", next_cursor);
- twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth, args, 2);
+ twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
g_free(args[1]);
}
@@ -653,7 +653,7 @@ void twitter_post_status(struct im_connection *ic, char* msg)
char* args[2];
args[0] = "status";
args[1] = msg;
- twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth, args, 2);
+ twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
// g_free(args[1]);
}
@@ -671,7 +671,7 @@ void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg)
args[2] = "text";
args[3] = msg;
// Use the same callback as for twitter_post_status, since it does basically the same.
- twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth, args, 4);
+ twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 4);
// g_free(args[1]);
// g_free(args[3]);
}