diff options
Diffstat (limited to 'lib/oauth.c')
-rw-r--r-- | lib/oauth.c | 507 |
1 files changed, 253 insertions, 254 deletions
diff --git a/lib/oauth.c b/lib/oauth.c index 54c272c8..f15a7135 100644 --- a/lib/oauth.c +++ b/lib/oauth.c @@ -34,396 +34,395 @@ #define HMAC_BLOCK_SIZE 64 -static char *oauth_sign( const char *method, const char *url, - const char *params, struct oauth_info *oi ) +static char *oauth_sign(const char *method, const char *url, + const char *params, struct oauth_info *oi) { uint8_t hash[SHA1_HASH_SIZE]; - GString *payload = g_string_new( "" ); + GString *payload = g_string_new(""); char *key; char *s; - - key = g_strdup_printf( "%s&%s", oi->sp->consumer_secret, oi->token_secret ? oi->token_secret : "" ); - - g_string_append_printf( payload, "%s&", method ); - - s = g_new0( char, strlen( url ) * 3 + 1 ); - strcpy( s, url ); - http_encode( s ); - g_string_append_printf( payload, "%s&", s ); - g_free( s ); - - s = g_new0( char, strlen( params ) * 3 + 1 ); - strcpy( s, params ); - http_encode( s ); - g_string_append( payload, s ); - g_free( s ); - - sha1_hmac( key, 0, payload->str, 0, hash ); - - g_free( key ); - g_string_free( payload, TRUE ); - - /* base64_encode + HTTP escape it (both consumers + + key = g_strdup_printf("%s&%s", oi->sp->consumer_secret, oi->token_secret ? oi->token_secret : ""); + + g_string_append_printf(payload, "%s&", method); + + s = g_new0(char, strlen(url) * 3 + 1); + strcpy(s, url); + http_encode(s); + g_string_append_printf(payload, "%s&", s); + g_free(s); + + s = g_new0(char, strlen(params) * 3 + 1); + strcpy(s, params); + http_encode(s); + g_string_append(payload, s); + g_free(s); + + sha1_hmac(key, 0, payload->str, 0, hash); + + g_free(key); + g_string_free(payload, TRUE); + + /* base64_encode + HTTP escape it (both consumers need it that away) and we're done. */ - s = base64_encode( hash, SHA1_HASH_SIZE ); - s = g_realloc( s, strlen( s ) * 3 + 1 ); - http_encode( s ); - + s = base64_encode(hash, SHA1_HASH_SIZE); + s = g_realloc(s, strlen(s) * 3 + 1); + http_encode(s); + return s; } static char *oauth_nonce() { unsigned char bytes[21]; - random_bytes( bytes, sizeof( bytes ) ); - return base64_encode( bytes, sizeof( bytes ) ); + + random_bytes(bytes, sizeof(bytes)); + return base64_encode(bytes, sizeof(bytes)); } -void oauth_params_add( GSList **params, const char *key, const char *value ) +void oauth_params_add(GSList **params, const char *key, const char *value) { char *item; - - if( !key || !value ) + + if (!key || !value) { return; - - item = g_strdup_printf( "%s=%s", key, value ); - *params = g_slist_insert_sorted( *params, item, (GCompareFunc) strcmp ); + } + + item = g_strdup_printf("%s=%s", key, value); + *params = g_slist_insert_sorted(*params, item, (GCompareFunc) strcmp); } -void oauth_params_del( GSList **params, const char *key ) +void oauth_params_del(GSList **params, const char *key) { - int key_len = strlen( key ); + int key_len = strlen(key); GSList *l, *n; - - if( params == NULL ) + + if (params == NULL) { return; - - for( l = *params; l; l = n ) - { + } + + for (l = *params; l; l = n) { n = l->next; - - if( strncmp( (char*) l->data, key, key_len ) == 0 && - ((char*)l->data)[key_len] == '=' ) - { - g_free( l->data ); - *params = g_slist_remove( *params, l->data ); + + if (strncmp((char *) l->data, key, key_len) == 0 && + ((char *) l->data)[key_len] == '=') { + g_free(l->data); + *params = g_slist_remove(*params, l->data); } } } -void oauth_params_set( GSList **params, const char *key, const char *value ) +void oauth_params_set(GSList **params, const char *key, const char *value) { - oauth_params_del( params, key ); - oauth_params_add( params, key, value ); + oauth_params_del(params, key); + oauth_params_add(params, key, value); } -const char *oauth_params_get( GSList **params, const char *key ) +const char *oauth_params_get(GSList **params, const char *key) { - int key_len = strlen( key ); + int key_len = strlen(key); GSList *l; - - if( params == NULL ) + + if (params == NULL) { return NULL; - - for( l = *params; l; l = l->next ) - { - if( strncmp( (char*) l->data, key, key_len ) == 0 && - ((char*)l->data)[key_len] == '=' ) - return (const char*) l->data + key_len + 1; } - + + for (l = *params; l; l = l->next) { + if (strncmp((char *) l->data, key, key_len) == 0 && + ((char *) l->data)[key_len] == '=') { + return (const char *) l->data + key_len + 1; + } + } + return NULL; } -void oauth_params_parse( GSList **params, char *in ) +void oauth_params_parse(GSList **params, char *in) { char *amp, *eq, *s; - - while( in && *in ) - { - eq = strchr( in, '=' ); - if( !eq ) + + while (in && *in) { + eq = strchr(in, '='); + if (!eq) { break; - + } + *eq = '\0'; - if( ( amp = strchr( eq + 1, '&' ) ) ) + if ((amp = strchr(eq + 1, '&'))) { *amp = '\0'; - - s = g_strdup( eq + 1 ); - http_decode( s ); - oauth_params_add( params, in, s ); - g_free( s ); - + } + + s = g_strdup(eq + 1); + http_decode(s); + oauth_params_add(params, in, s); + g_free(s); + *eq = '='; - if( amp == NULL ) + if (amp == NULL) { break; - + } + *amp = '&'; in = amp + 1; } } -void oauth_params_free( GSList **params ) +void oauth_params_free(GSList **params) { - while( params && *params ) - { - g_free( (*params)->data ); - *params = g_slist_remove( *params, (*params)->data ); + while (params && *params) { + g_free((*params)->data); + *params = g_slist_remove(*params, (*params)->data); } } -char *oauth_params_string( GSList *params ) +char *oauth_params_string(GSList *params) { GSList *l; - GString *str = g_string_new( "" ); - - for( l = params; l; l = l->next ) - { + GString *str = g_string_new(""); + + for (l = params; l; l = l->next) { char *s, *eq; - - s = g_malloc( strlen( l->data ) * 3 + 1 ); - strcpy( s, l->data ); - if( ( eq = strchr( s, '=' ) ) ) - http_encode( eq + 1 ); - g_string_append( str, s ); - g_free( s ); - - if( l->next ) - g_string_append_c( str, '&' ); + + s = g_malloc(strlen(l->data) * 3 + 1); + strcpy(s, l->data); + if ((eq = strchr(s, '='))) { + http_encode(eq + 1); + } + g_string_append(str, s); + g_free(s); + + if (l->next) { + g_string_append_c(str, '&'); + } } - - return g_string_free( str, FALSE ); + + return g_string_free(str, FALSE); } -void oauth_info_free( struct oauth_info *info ) +void oauth_info_free(struct oauth_info *info) { - if( info ) - { - g_free( info->auth_url ); - g_free( info->request_token ); - g_free( info->token ); - g_free( info->token_secret ); - oauth_params_free( &info->params ); - g_free( info ); + if (info) { + g_free(info->auth_url); + g_free(info->request_token); + g_free(info->token); + g_free(info->token_secret); + oauth_params_free(&info->params); + g_free(info); } } -static void oauth_add_default_params( GSList **params, const struct oauth_service *sp ) +static void oauth_add_default_params(GSList **params, const struct oauth_service *sp) { char *s; - - 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 ) ); - oauth_params_set( params, "oauth_timestamp", s ); - g_free( s ); - + + 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)); + oauth_params_set(params, "oauth_timestamp", s); + g_free(s); + s = oauth_nonce(); - oauth_params_set( params, "oauth_nonce", s ); - g_free( s ); - - oauth_params_set( params, "oauth_version", "1.0" ); + oauth_params_set(params, "oauth_nonce", s); + g_free(s); + + oauth_params_set(params, "oauth_version", "1.0"); } -static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, struct oauth_info *oi ) +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; void *req; url_t url_p; - - if( !url_set( &url_p, url ) ) - { - oauth_params_free( params_ ); + + if (!url_set(&url_p, url)) { + oauth_params_free(params_); return NULL; } - - if( params_ ) + + if (params_) { params = *params_; - - oauth_add_default_params( ¶ms, oi->sp ); - - params_s = oauth_params_string( params ); - oauth_params_free( ¶ms ); - - 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 ); - - s = g_strdup_printf( "POST %s HTTP/1.0\r\n" - "Host: %s\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: %zd\r\n" - "\r\n" - "%s", url_p.file, url_p.host, strlen( post ), post ); - g_free( post ); - - req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS, - s, func, oi ); - g_free( s ); - + } + + oauth_add_default_params(¶ms, oi->sp); + + params_s = oauth_params_string(params); + oauth_params_free(¶ms); + + 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); + + s = g_strdup_printf("POST %s HTTP/1.0\r\n" + "Host: %s\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: %zd\r\n" + "\r\n" + "%s", url_p.file, url_p.host, strlen(post), post); + g_free(post); + + req = http_dorequest(url_p.host, url_p.port, url_p.proto == PROTO_HTTPS, + s, func, oi); + g_free(s); + return req; } -static void oauth_request_token_done( struct http_request *req ); +static void oauth_request_token_done(struct http_request *req); -struct oauth_info *oauth_request_token( const struct oauth_service *sp, oauth_cb func, void *data ) +struct oauth_info *oauth_request_token(const struct oauth_service *sp, oauth_cb func, void *data) { - struct oauth_info *st = g_new0( struct oauth_info, 1 ); + 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( sp->url_request_token, ¶ms, oauth_request_token_done, st ) ) - { - oauth_info_free( st ); + + oauth_params_add(¶ms, "oauth_callback", "oob"); + + if (!oauth_post_request(sp->url_request_token, ¶ms, oauth_request_token_done, st)) { + oauth_info_free(st); return NULL; } - + return st; } -static void oauth_request_token_done( struct http_request *req ) +static void oauth_request_token_done(struct http_request *req) { struct oauth_info *st = req->data; - + st->http = req; - - if( req->status_code == 200 ) - { + + if (req->status_code == 200) { GSList *params = NULL; - - 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" ) ); - st->token_secret = g_strdup( oauth_params_get( ¶ms, "oauth_token_secret" ) ); - oauth_params_free( ¶ms ); + + 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")); + st->token_secret = g_strdup(oauth_params_get(¶ms, "oauth_token_secret")); + oauth_params_free(¶ms); } - + st->stage = OAUTH_REQUEST_TOKEN; - st->func( st ); + st->func(st); } -static void oauth_access_token_done( struct http_request *req ); +static void oauth_access_token_done(struct http_request *req); -gboolean oauth_access_token( 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 ); - - return oauth_post_request( st->sp->url_access_token, ¶ms, oauth_access_token_done, st ) != NULL; + + oauth_params_add(¶ms, "oauth_token", st->request_token); + oauth_params_add(¶ms, "oauth_verifier", pin); + + 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 ) +static void oauth_access_token_done(struct http_request *req) { struct oauth_info *st = req->data; - + st->http = req; - - if( req->status_code == 200 ) - { - oauth_params_parse( &st->params, req->reply_body ); - st->token = g_strdup( oauth_params_get( &st->params, "oauth_token" ) ); - g_free( st->token_secret ); - st->token_secret = g_strdup( oauth_params_get( &st->params, "oauth_token_secret" ) ); + + if (req->status_code == 200) { + oauth_params_parse(&st->params, req->reply_body); + st->token = g_strdup(oauth_params_get(&st->params, "oauth_token")); + g_free(st->token_secret); + st->token_secret = g_strdup(oauth_params_get(&st->params, "oauth_token_secret")); } - + st->stage = OAUTH_ACCESS_TOKEN; - if( st->func( st ) ) - { + if (st->func(st)) { /* Don't need these anymore, but keep the rest. */ - g_free( st->auth_url ); + g_free(st->auth_url); st->auth_url = NULL; - g_free( st->request_token ); + g_free(st->request_token); st->request_token = NULL; - oauth_params_free( &st->params ); + oauth_params_free(&st->params); } } -char *oauth_http_header( struct oauth_info *oi, 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 *sig = NULL, *params_s, *s; GString *ret = NULL; - - oauth_params_add( ¶ms, "oauth_token", oi->token ); - oauth_add_default_params( ¶ms, oi->sp ); - + + 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 " ); - for( l = params; l; l = l->next ) - { + ret = g_string_new("OAuth "); + for (l = params; l; l = l->next) { char *kv = l->data; - char *eq = strchr( kv, '=' ); - char esc[strlen(kv)*3+1]; - - if( eq == NULL ) + char *eq = strchr(kv, '='); + char esc[strlen(kv) * 3 + 1]; + + if (eq == NULL) { break; /* WTF */ - - strcpy( esc, eq + 1 ); - http_encode( esc ); - - g_string_append_len( ret, kv, eq - kv + 1 ); - g_string_append_c( ret, '"' ); - g_string_append( ret, esc ); - g_string_append( ret, "\", " ); + + } + strcpy(esc, eq + 1); + http_encode(esc); + + g_string_append_len(ret, kv, eq - kv + 1); + g_string_append_c(ret, '"'); + g_string_append(ret, esc); + g_string_append(ret, "\", "); } - + /* Now, before generating the signature, add GET/POST arguments to params since they should be included in the base signature string (but not in the HTTP header). */ - if( args ) - oauth_params_parse( ¶ms, args ); - if( ( s = strchr( url, '?' ) ) ) - { - s = g_strdup( s + 1 ); - oauth_params_parse( ¶ms, s ); - g_free( s ); + if (args) { + oauth_params_parse(¶ms, args); + } + if ((s = strchr(url, '?'))) { + s = g_strdup(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, oi ); - g_string_append_printf( ret, "oauth_signature=\"%s\"", sig ); - g_free( params_s ); - - oauth_params_free( ¶ms ); - g_free( sig ); - - return ret ? g_string_free( ret, FALSE ) : NULL; + params_s = oauth_params_string(params); + sig = oauth_sign(method, url, params_s, oi); + g_string_append_printf(ret, "oauth_signature=\"%s\"", sig); + g_free(params_s); + + oauth_params_free(¶ms); + g_free(sig); + + return ret ? g_string_free(ret, FALSE) : NULL; } -char *oauth_to_string( struct oauth_info *oi ) +char *oauth_to_string(struct oauth_info *oi) { GSList *params = NULL; char *ret; - - oauth_params_add( ¶ms, "oauth_token", oi->token ); - oauth_params_add( ¶ms, "oauth_token_secret", oi->token_secret ); - ret = oauth_params_string( params ); - oauth_params_free( ¶ms ); - + + oauth_params_add(¶ms, "oauth_token", oi->token); + oauth_params_add(¶ms, "oauth_token_secret", oi->token_secret); + ret = oauth_params_string(params); + oauth_params_free(¶ms); + return ret; } -struct oauth_info *oauth_from_string( char *in, const struct oauth_service *sp ) +struct oauth_info *oauth_from_string(char *in, const struct oauth_service *sp) { - struct oauth_info *oi = g_new0( struct oauth_info, 1 ); + struct oauth_info *oi = g_new0(struct oauth_info, 1); GSList *params = NULL; - - oauth_params_parse( ¶ms, in ); - oi->token = g_strdup( oauth_params_get( ¶ms, "oauth_token" ) ); - oi->token_secret = g_strdup( oauth_params_get( ¶ms, "oauth_token_secret" ) ); - oauth_params_free( ¶ms ); + + oauth_params_parse(¶ms, in); + oi->token = g_strdup(oauth_params_get(¶ms, "oauth_token")); + oi->token_secret = g_strdup(oauth_params_get(¶ms, "oauth_token_secret")); + oauth_params_free(¶ms); oi->sp = sp; - + return oi; } |