Changeset 3b878a1


Ignore:
Timestamp:
2010-05-02T21:20:09Z (9 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
6824fb3
Parents:
839189b (diff), f4b0911 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

OAuth sanity fix: Twitter-specific stuff should *not* be in lib/oauth.c.
Somewhat intrusive, should've done this right immediately. :-/

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • lib/oauth.c

    r839189b r3b878a1  
    3333#include "oauth.h"
    3434
    35 #define CONSUMER_KEY "xsDNKJuNZYkZyMcu914uEA"
    36 #define CONSUMER_SECRET "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo"
    37 /* How can it be a secret if it's right here in the source code? No clue... */
    38 
    3935#define HMAC_BLOCK_SIZE 64
    4036
    4137static char *oauth_sign( const char *method, const char *url,
    42                          const char *params, const char *token_secret )
     38                         const char *params, struct oauth_info *oi )
    4339{
    4440        sha1_state_t sha1;
     
    5147           otherwise just pad. */
    5248        memset( key, 0, HMAC_BLOCK_SIZE );
    53         i = strlen( CONSUMER_SECRET ) + 1 + ( token_secret ? strlen( token_secret ) : 0 );
     49        i = strlen( oi->sp->consumer_secret ) + 1 + ( oi->token_secret ? strlen( oi->token_secret ) : 0 );
    5450        if( i > HMAC_BLOCK_SIZE )
    5551        {
    5652                sha1_init( &sha1 );
    57                 sha1_append( &sha1, (uint8_t*) CONSUMER_SECRET, strlen( CONSUMER_SECRET ) );
     53                sha1_append( &sha1, (uint8_t*) oi->sp->consumer_secret, strlen( oi->sp->consumer_secret ) );
    5854                sha1_append( &sha1, (uint8_t*) "&", 1 );
    59                 if( token_secret )
    60                         sha1_append( &sha1, (uint8_t*) token_secret, strlen( token_secret ) );
     55                if( oi->token_secret )
     56                        sha1_append( &sha1, (uint8_t*) oi->token_secret, strlen( oi->token_secret ) );
    6157                sha1_finish( &sha1, key );
    6258        }
     
    6460        {
    6561                g_snprintf( (gchar*) key, HMAC_BLOCK_SIZE + 1, "%s&%s",
    66                             CONSUMER_SECRET, token_secret ? : "" );
     62                            oi->sp->consumer_secret, oi->token_secret ? : "" );
    6763        }
    6864       
     
    229225        if( info )
    230226        {
    231                 g_free( info->auth_params );
     227                g_free( info->auth_url );
    232228                g_free( info->request_token );
    233                 g_free( info->access_token );
     229                g_free( info->token );
     230                g_free( info->token_secret );
    234231                g_free( info );
    235232        }
    236233}
    237234
    238 static void oauth_add_default_params( GSList **params )
     235static void oauth_add_default_params( GSList **params, const struct oauth_service *sp )
    239236{
    240237        char *s;
    241238       
    242         oauth_params_set( params, "oauth_consumer_key", CONSUMER_KEY );
     239        oauth_params_set( params, "oauth_consumer_key", sp->consumer_key );
    243240        oauth_params_set( params, "oauth_signature_method", "HMAC-SHA1" );
    244241       
     
    254251}
    255252
    256 static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, void *data )
     253static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, struct oauth_info *oi )
    257254{
    258255        GSList *params = NULL;
     
    270267                params = *params_;
    271268       
    272         oauth_add_default_params( &params );
     269        oauth_add_default_params( &params, oi->sp );
    273270       
    274271        params_s = oauth_params_string( params );
    275272        oauth_params_free( &params );
    276273       
    277         s = oauth_sign( "POST", url, params_s, NULL );
     274        s = oauth_sign( "POST", url, params_s, oi );
    278275        post = g_strdup_printf( "%s&oauth_signature=%s", params_s, s );
    279276        g_free( params_s );
     
    289286       
    290287        req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS,
    291                               s, func, data );
     288                              s, func, oi );
    292289        g_free( s );
    293290       
     
    297294static void oauth_request_token_done( struct http_request *req );
    298295
    299 struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data )
     296struct oauth_info *oauth_request_token( const struct oauth_service *sp, oauth_cb func, void *data )
    300297{
    301298        struct oauth_info *st = g_new0( struct oauth_info, 1 );
     
    304301        st->func = func;
    305302        st->data = data;
     303        st->sp = sp;
    306304       
    307305        oauth_params_add( &params, "oauth_callback", "oob" );
    308306       
    309         if( !oauth_post_request( url, &params, oauth_request_token_done, st ) )
     307        if( !oauth_post_request( sp->url_request_token, &params, oauth_request_token_done, st ) )
    310308        {
    311309                oauth_info_free( st );
     
    326324                GSList *params = NULL;
    327325               
    328                 st->auth_params = g_strdup( req->reply_body );
    329                 oauth_params_parse( &params, st->auth_params );
     326                st->auth_url = g_strdup_printf( "%s?%s", st->sp->url_authorize, req->reply_body );
     327                oauth_params_parse( &params, req->reply_body );
    330328                st->request_token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
    331329                oauth_params_free( &params );
     
    333331       
    334332        st->stage = OAUTH_REQUEST_TOKEN;
    335         if( !st->func( st ) )
    336                 oauth_info_free( st );
     333        st->func( st );
    337334}
    338335
    339336static void oauth_access_token_done( struct http_request *req );
    340337
    341 void oauth_access_token( const char *url, const char *pin, struct oauth_info *st )
     338gboolean oauth_access_token( const char *pin, struct oauth_info *st )
    342339{
    343340        GSList *params = NULL;
     
    346343        oauth_params_add( &params, "oauth_verifier", pin );
    347344       
    348         if( !oauth_post_request( url, &params, oauth_access_token_done, st ) )
    349                 oauth_info_free( st );
     345        return oauth_post_request( st->sp->url_access_token, &params, oauth_access_token_done, st ) != NULL;
    350346}
    351347
     
    359355        {
    360356                GSList *params = NULL;
    361                 const char *token, *token_secret;
    362357               
    363358                oauth_params_parse( &params, req->reply_body );
    364                 token = oauth_params_get( &params, "oauth_token" );
    365                 token_secret = oauth_params_get( &params, "oauth_token_secret" );
    366                 st->access_token = g_strdup_printf(
    367                         "oauth_token=%s&oauth_token_secret=%s", token, token_secret );
     359                st->token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
     360                st->token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
    368361                oauth_params_free( &params );
    369362        }
    370363       
    371364        st->stage = OAUTH_ACCESS_TOKEN;
    372         st->func( st );
    373         oauth_info_free( st );
    374 }
    375 
    376 char *oauth_http_header( char *access_token, const char *method, const char *url, char *args )
     365        if( st->func( st ) )
     366        {
     367                /* Don't need these anymore, but keep the rest. */
     368                g_free( st->auth_url );
     369                st->auth_url = NULL;
     370                g_free( st->request_token );
     371                st->request_token = NULL;
     372        }
     373}
     374
     375char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args )
    377376{
    378377        GSList *params = NULL, *l;
    379         char *token_secret = NULL, *sig = NULL, *params_s, *s;
     378        char *sig = NULL, *params_s, *s;
    380379        GString *ret = NULL;
    381380       
    382         /* First, get the two pieces of info from the access token that we need. */
    383         oauth_params_parse( &params, access_token );
    384         if( params == NULL )
    385                 goto err;
    386        
    387         /* Pick out the token secret, we shouldn't include it but use it for signing. */
    388         token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
    389         if( token_secret == NULL )
    390                 goto err;
    391         oauth_params_del( &params, "oauth_token_secret" );
    392        
    393         oauth_add_default_params( &params );
     381        oauth_params_add( &params, "oauth_token", oi->token );
     382        oauth_add_default_params( &params, oi->sp );
    394383       
    395384        /* Start building the OAuth header. 'key="value", '... */
     
    421410        {
    422411                s = g_strdup( s + 1 );
    423                 oauth_params_parse( &params, s + 1 );
     412                oauth_params_parse( &params, s );
    424413                g_free( s );
    425414        }
     
    427416        /* Append the signature and we're done! */
    428417        params_s = oauth_params_string( params );
    429         sig = oauth_sign( method, url, params_s, token_secret );
     418        sig = oauth_sign( method, url, params_s, oi );
    430419        g_string_append_printf( ret, "oauth_signature=\"%s\"", sig );
    431420        g_free( params_s );
    432421       
    433 err:
    434422        oauth_params_free( &params );
    435423        g_free( sig );
    436         g_free( token_secret );
    437424       
    438425        return ret ? g_string_free( ret, FALSE ) : NULL;
    439426}
     427
     428char *oauth_to_string( struct oauth_info *oi )
     429{
     430        GSList *params = NULL;
     431        char *ret;
     432       
     433        oauth_params_add( &params, "oauth_token", oi->token );
     434        oauth_params_add( &params, "oauth_token_secret", oi->token_secret );
     435        ret = oauth_params_string( params );
     436        oauth_params_free( &params );
     437       
     438        return ret;
     439}
     440
     441struct oauth_info *oauth_from_string( char *in, const struct oauth_service *sp )
     442{
     443        struct oauth_info *oi = g_new0( struct oauth_info, 1 );
     444        GSList *params = NULL;
     445       
     446        oauth_params_parse( &params, in );
     447        oi->token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
     448        oi->token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
     449        oauth_params_free( &params );
     450        oi->sp = sp;
     451       
     452        return oi;
     453}
  • lib/oauth.h

    r839189b r3b878a1  
    4040{
    4141        oauth_stage_t stage;
     42        const struct oauth_service *sp;
    4243       
    4344        oauth_cb func;
     
    4647        struct http_request *http;
    4748       
    48         char *auth_params;
     49        char *auth_url;
    4950        char *request_token;
    5051       
    51         char *access_token;
     52        char *token;
     53        char *token_secret;
     54};
     55
     56struct oauth_service
     57{
     58        char *url_request_token;
     59        char *url_access_token;
     60        char *url_authorize;
     61       
     62        char *consumer_key;
     63        char *consumer_secret;
    5264};
    5365
     
    5668   authorization URL for the user. This is passed to the callback function
    5769   in a struct oauth_info. */
    58 struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data );
     70struct oauth_info *oauth_request_token( const struct oauth_service *sp, oauth_cb func, void *data );
    5971
    6072/* http://oauth.net/core/1.0a/#auth_step3 (section 6.3)
     
    6274   token. This is passed to the callback function in the same
    6375   struct oauth_info. */
    64 void oauth_access_token( const char *url, const char *pin, struct oauth_info *st );
     76gboolean oauth_access_token( const char *pin, struct oauth_info *st );
    6577
    6678/* http://oauth.net/core/1.0a/#anchor12 (section 7)
     
    6981   whatever's going to be in the POST body of the request. GET args will
    7082   automatically be grabbed from url. */
    71 char *oauth_http_header( char *access_token, const char *method, const char *url, char *args );
     83char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args );
    7284
    7385/* Shouldn't normally be required unless the process is aborted by the user. */
    7486void oauth_info_free( struct oauth_info *info );
     87
     88/* Convert to and back from strings, for easier saving. */
     89char *oauth_to_string( struct oauth_info *oi );
     90struct oauth_info *oauth_from_string( char *in, const struct oauth_service *sp );
  • protocols/twitter/twitter.c

    r839189b r3b878a1  
    2828#include "twitter_lib.h"
    2929
    30 
    3130/**
    3231 * Main loop function
     
    6665}
    6766
     67
     68static const struct oauth_service twitter_oauth =
     69{
     70        "http://api.twitter.com/oauth/request_token",
     71        "http://api.twitter.com/oauth/access_token",
     72        "http://api.twitter.com/oauth/authorize",
     73        .consumer_key = "xsDNKJuNZYkZyMcu914uEA",
     74        .consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo",
     75};
     76
    6877static gboolean twitter_oauth_callback( struct oauth_info *info );
    6978
     
    7483        imcb_log( ic, "Requesting OAuth request token" );
    7584
    76         td->oauth_info = oauth_request_token(
    77                 TWITTER_OAUTH_REQUEST_TOKEN, twitter_oauth_callback, ic );
     85        td->oauth_info = oauth_request_token( &twitter_oauth, twitter_oauth_callback, ic );
    7886}
    7987
     
    100108                sprintf( name, "twitter_%s", ic->acc->user );
    101109                msg = g_strdup_printf( "To finish OAuth authentication, please visit "
    102                                        "%s?%s and respond with the resulting PIN code.",
    103                                        TWITTER_OAUTH_AUTHORIZE, info->auth_params );
     110                                       "%s and respond with the resulting PIN code.",
     111                                       info->auth_url );
    104112                imcb_buddy_msg( ic, name, msg, 0, 0 );
    105113                g_free( msg );
     
    107115        else if( info->stage == OAUTH_ACCESS_TOKEN )
    108116        {
    109                 if( info->access_token == NULL )
     117                if( info->token == NULL || info->token_secret == NULL )
    110118                {
    111119                        imcb_error( ic, "OAuth error: %s", info->http->status_string );
     
    114122                }
    115123               
    116                 td->oauth = g_strdup( info->access_token );
    117                
    118124                /* IM mods didn't do this so far and it's ugly but I should
    119125                   be able to get away with it... */
    120126                g_free( ic->acc->pass );
    121                 ic->acc->pass = g_strdup( info->access_token );
     127                ic->acc->pass = oauth_to_string( info );
    122128               
    123129                twitter_main_loop_start( ic );
     
    126132        return TRUE;
    127133}
     134
    128135
    129136static char *set_eval_mode( set_t *set, char *value )
     
    165172                td->pass = g_strdup( acc->pass );
    166173        else if( strstr( acc->pass, "oauth_token=" ) )
    167                 td->oauth = g_strdup( acc->pass );
     174                td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );
    168175        td->home_timeline_id = 0;
    169176       
     
    172179        imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
    173180       
    174         if( td->pass || td->oauth )
     181        if( td->pass || td->oauth_info )
    175182                twitter_main_loop_start( ic );
    176183        else
     
    197204        {
    198205                oauth_info_free( td->oauth_info );
    199                
    200206                g_free( td->pass );
    201                 g_free( td->oauth );
    202207                g_free( td );
    203208        }
     
    216221            g_strcasecmp(who + 8, ic->acc->user) == 0)
    217222        {
    218                 if( set_getbool( &ic->acc->set, "oauth" ) && td->oauth_info )
     223                if( set_getbool( &ic->acc->set, "oauth" ) &&
     224                    td->oauth_info && td->oauth_info->token == NULL )
    219225                {
    220                         oauth_access_token( TWITTER_OAUTH_ACCESS_TOKEN, message, td->oauth_info );
    221                         td->oauth_info = NULL;
     226                        if( !oauth_access_token( message, td->oauth_info ) )
     227                        {
     228                                imcb_error( ic, "OAuth error: %s", "Failed to send access token request" );
     229                                imc_logout( ic, TRUE );
     230                                return FALSE;
     231                        }
    222232                }
    223233                else
  • protocols/twitter/twitter.h

    r839189b r3b878a1  
    3737        char* user;
    3838        char* pass;
    39         char* oauth;
    4039        struct oauth_info *oauth_info;
    4140        guint64 home_timeline_id;
     
    5251GSList *twitter_connections;
    5352
    54 #define TWITTER_OAUTH_REQUEST_TOKEN "http://api.twitter.com/oauth/request_token"
    55 #define TWITTER_OAUTH_ACCESS_TOKEN  "http://api.twitter.com/oauth/access_token"
    56 #define TWITTER_OAUTH_AUTHORIZE     "http://api.twitter.com/oauth/authorize"
    57 
    5853#endif //_TWITTER_H
  • protocols/twitter/twitter_http.c

    r839189b r3b878a1  
    2929****************************************************************************/
    3030
    31 #include "twitter_http.h"
    3231#include "twitter.h"
    3332#include "bitlbee.h"
     
    3938#include <errno.h>
    4039
     40#include "twitter_http.h"
     41
    4142
    4243char *twitter_url_append(char *url, char *key, char* value);
     
    4647 * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c
    4748 */
    48 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)
     49void *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)
    4950{
    5051        url_t *url = g_new0( url_t, 1 );
     
    111112
    112113        // If a pass and user are given we append them to the request.
    113         if (oauth_token)
     114        if (oi)
    114115        {
    115116                char *full_header;
    116117               
    117                 full_header = oauth_http_header(oauth_token,
    118                                                 is_post ? "POST" : "GET",
     118                full_header = oauth_http_header(oi, is_post ? "POST" : "GET",
    119119                                                url_string, url_arguments);
    120120               
  • protocols/twitter/twitter_http.h

    r839189b r3b878a1  
    2828#include "http_client.h"
    2929
     30struct oauth_info;
     31
    3032void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post,
    31                    char* user, char* pass, char *oauth_token, char** arguments, int arguments_len);
     33                   char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);
    3234
    3335#endif //_TWITTER_HTTP_H
  • protocols/twitter/twitter_lib.c

    r839189b r3b878a1  
    130130        args[0] = "cursor";
    131131        args[1] = g_strdup_printf ("%d", next_cursor);
    132         twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth, args, 2);
     132        twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
    133133
    134134        g_free(args[1]);
     
    396396        }
    397397
    398         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);
     398        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);
    399399
    400400        g_free(args[1]);
     
    510510        {
    511511                td->http_fails = 0;
    512                 if (!ic->flags & OPT_LOGGED_IN)
     512                if (!(ic->flags & OPT_LOGGED_IN))
    513513                        imcb_connected(ic);
    514514        }
     
    620620        args[1] = g_strdup_printf ("%d", next_cursor);
    621621
    622         twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth, args, 2);
     622        twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
    623623
    624624        g_free(args[1]);
     
    654654        args[0] = "status";
    655655        args[1] = msg;
    656         twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth, args, 2);
     656        twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
    657657//      g_free(args[1]);
    658658}
     
    672672        args[3] = msg;
    673673        // Use the same callback as for twitter_post_status, since it does basically the same.
    674         twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth, args, 4);
     674        twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 4);
    675675//      g_free(args[1]);
    676676//      g_free(args[3]);
Note: See TracChangeset for help on using the changeset viewer.