diff options
| -rw-r--r-- | lib/oauth.c | 91 | ||||
| -rw-r--r-- | lib/oauth.h | 22 | ||||
| -rw-r--r-- | protocols/twitter/twitter.c | 46 | ||||
| -rw-r--r-- | protocols/twitter/twitter.h | 5 | ||||
| -rw-r--r-- | protocols/twitter/twitter_http.c | 10 | ||||
| -rw-r--r-- | protocols/twitter/twitter_http.h | 4 | ||||
| -rw-r--r-- | protocols/twitter/twitter_lib.c | 12 | 
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( ¶ms ); +	oauth_add_default_params( ¶ms, oi->sp );  	params_s = oauth_params_string( params );  	oauth_params_free( ¶ms ); -	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( ¶ms, "oauth_callback", "oob" ); -	if( !oauth_post_request( url, ¶ms, oauth_request_token_done, st ) ) +	if( !oauth_post_request( sp->url_request_token, ¶ms, 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( ¶ms, st->auth_params ); +		st->auth_url = g_strdup_printf( "%s?%s", st->sp->url_authorize, req->reply_body ); +		oauth_params_parse( ¶ms, req->reply_body );  		st->request_token = g_strdup( oauth_params_get( ¶ms, "oauth_token" ) );  		oauth_params_free( ¶ms );  	}  	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( ¶ms, "oauth_token", st->request_token );  	oauth_params_add( ¶ms, "oauth_verifier", pin ); -	if( !oauth_post_request( url, ¶ms, oauth_access_token_done, st ) ) -		oauth_info_free( st ); +	return oauth_post_request( st->sp->url_access_token, ¶ms, 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( ¶ms, req->reply_body ); -		token = oauth_params_get( ¶ms, "oauth_token" ); -		token_secret = oauth_params_get( ¶ms, "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( ¶ms, "oauth_token" ) ); +		st->token_secret = g_strdup( oauth_params_get( ¶ms, "oauth_token_secret" ) );  		oauth_params_free( ¶ms );  	}  	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( ¶ms, 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( ¶ms, "oauth_token_secret" ) ); -	if( token_secret == NULL ) -		goto err; -	oauth_params_del( ¶ms, "oauth_token_secret" ); -	 -	oauth_add_default_params( ¶ms ); +	oauth_params_add( ¶ms, "oauth_token", oi->token ); +	oauth_add_default_params( ¶ms, 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( ¶ms, s + 1 ); +		oauth_params_parse( ¶ms, 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( ¶ms );  	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]);  } | 
