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;  } | 
