|
|
|
@ -1,12 +1,18 @@
|
|
|
|
|
#include "oauth.h"
|
|
|
|
|
#include "http_server/http_request.h"
|
|
|
|
|
#include "http_server/escape.h"
|
|
|
|
|
|
|
|
|
|
#include "model/client_app.h"
|
|
|
|
|
#include "model/account.h"
|
|
|
|
|
#include "model/owner.h"
|
|
|
|
|
|
|
|
|
|
#include "form.h"
|
|
|
|
|
#include "json/json.h"
|
|
|
|
|
#include "json/layout.h"
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
|
|
static bool handle_oauth_authorize( struct http_request* req )
|
|
|
|
|
{
|
|
|
|
@ -161,56 +167,99 @@ access_denied:
|
|
|
|
|
static bool handle_oauth_get_token( struct http_request* req )
|
|
|
|
|
{
|
|
|
|
|
bool result = true;
|
|
|
|
|
char* auth_code = NULL;
|
|
|
|
|
struct account* owner_account = NULL;
|
|
|
|
|
struct owner* owner = NULL;
|
|
|
|
|
struct client_app* app = NULL;
|
|
|
|
|
char* redirect_uri = NULL;
|
|
|
|
|
char* client_secret = NULL;
|
|
|
|
|
struct data_t
|
|
|
|
|
{
|
|
|
|
|
char* auth_code;
|
|
|
|
|
char* redirect_uri;
|
|
|
|
|
char* client_secret;
|
|
|
|
|
char* client_id;
|
|
|
|
|
char* grant_type;
|
|
|
|
|
char* username;
|
|
|
|
|
char* password;
|
|
|
|
|
} data;
|
|
|
|
|
memset(&data,0,sizeof(data));
|
|
|
|
|
|
|
|
|
|
FILE* post_data = http_request_get_request_data(req);
|
|
|
|
|
const char* content_type = http_request_get_header( req, "Content-Type" );
|
|
|
|
|
if( 0 == strcasecmp(content_type,"application/json") ) {
|
|
|
|
|
static struct json_object_field layout[] = {
|
|
|
|
|
{ "code", offsetof( struct data_t, auth_code ), false, &json_field_string },
|
|
|
|
|
{ "redirect_uri", offsetof( struct data_t, redirect_uri ), true, &json_field_string },
|
|
|
|
|
{ "grant_type", offsetof( struct data_t, grant_type ), false, &json_field_string },
|
|
|
|
|
{ "client_secret", offsetof( struct data_t, client_secret ), false, &json_field_string },
|
|
|
|
|
{ "client_id", offsetof( struct data_t, client_id ), false, &json_field_string },
|
|
|
|
|
{ "username", offsetof( struct data_t, username ), false, &json_field_string },
|
|
|
|
|
{ "password", offsetof( struct data_t, password ), false, &json_field_string },
|
|
|
|
|
{ NULL },
|
|
|
|
|
};
|
|
|
|
|
if( !json_read_object_layout_from_FILE( post_data, layout, &data ) ) {
|
|
|
|
|
printf( "A" );
|
|
|
|
|
goto invalid_request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE* body = http_request_get_request_data(req);
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
struct form_parser* fp = form_pull_parser_new(body);
|
|
|
|
|
if( !fp ) {
|
|
|
|
|
goto invalid_request;
|
|
|
|
|
}
|
|
|
|
|
struct form_parser* fp = form_pull_parser_new(post_data);
|
|
|
|
|
if( !fp ) {
|
|
|
|
|
goto invalid_request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* key;
|
|
|
|
|
while( key = form_pull_parser_read_key( fp ) ) {
|
|
|
|
|
if( 0 == strcmp(key,"grant_type") ) {
|
|
|
|
|
if( 0 != strcmp(form_pull_parser_read_value(fp),"authorization_code") ) {
|
|
|
|
|
goto invalid_request;
|
|
|
|
|
}
|
|
|
|
|
char* key;
|
|
|
|
|
// TODO: extend form parser to use a data layout
|
|
|
|
|
while( key = form_pull_parser_read_key( fp ) ) {
|
|
|
|
|
if( 0 == strcmp(key,"grant_type") ) {
|
|
|
|
|
data.grant_type = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
|
|
|
|
|
} else if( 0 == strcmp(key,"code") ) {
|
|
|
|
|
auth_code = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
} else if( 0 == strcmp(key,"code") ) {
|
|
|
|
|
data.auth_code = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
|
|
|
|
|
} else if( 0 == strcmp(key,"client_id") ) {
|
|
|
|
|
const char* client_id = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
app = client_app_from_id( client_id );
|
|
|
|
|
if( !app ) { goto invalid_request; }
|
|
|
|
|
} else if( 0 == strcmp(key,"client_id") ) {
|
|
|
|
|
data.client_id = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
|
|
|
|
|
} else if( 0 == strcmp(key,"client_secret") ) {
|
|
|
|
|
client_secret = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
} else if( 0 == strcmp(key,"client_secret") ) {
|
|
|
|
|
data.client_secret = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
|
|
|
|
|
} else if( 0 == strcmp(key,"redirect_uri") ) {
|
|
|
|
|
redirect_uri = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
} else if( 0 == strcmp(key,"redirect_uri") ) {
|
|
|
|
|
data.redirect_uri = strdup(form_pull_parser_read_value(fp));
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
printf( "%s=", key );
|
|
|
|
|
printf( "%s\n", form_pull_parser_read_value(fp) );
|
|
|
|
|
} else {
|
|
|
|
|
printf( "%s=", key );
|
|
|
|
|
printf( "%s\n", form_pull_parser_read_value(fp) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
form_pull_parser_release(fp);
|
|
|
|
|
}
|
|
|
|
|
form_pull_parser_release(fp);
|
|
|
|
|
|
|
|
|
|
if( !auth_code ) { goto invalid_request; }
|
|
|
|
|
if( !app ) { goto invalid_request; }
|
|
|
|
|
printf( "2" );
|
|
|
|
|
if( !data.redirect_uri ) { goto invalid_request; }
|
|
|
|
|
printf( "3" );
|
|
|
|
|
if( !data.client_id ) { goto invalid_request; }
|
|
|
|
|
printf( "4" );
|
|
|
|
|
|
|
|
|
|
if( redirect_uri ) {
|
|
|
|
|
if( 0 != strcmp( app->redirect_uri, redirect_uri ) ) {
|
|
|
|
|
goto invalid_request;
|
|
|
|
|
}
|
|
|
|
|
app = client_app_from_id( data.client_id );
|
|
|
|
|
if( !app ) { goto invalid_request; }
|
|
|
|
|
printf( "5" );
|
|
|
|
|
|
|
|
|
|
if( !app->redirect_uri ) { goto invalid_request; }
|
|
|
|
|
if( 0 != strcmp( app->redirect_uri, data.redirect_uri ) ) { goto invalid_request; }
|
|
|
|
|
printf( "6" );
|
|
|
|
|
if( 0 != strcmp( app->client.secret, data.client_secret ) ) { goto access_denied; }
|
|
|
|
|
if( 0 == strcmp("authorization_code",data.grant_type) ) {
|
|
|
|
|
if( !data.auth_code ) { goto invalid_request; }
|
|
|
|
|
if( 0 != strcmp( app->auth_code, data.auth_code ) ) { goto access_denied; }
|
|
|
|
|
} else if( 0 == strcmp("password", data.grant_type ) ) {
|
|
|
|
|
owner_account = account_from_id(0);
|
|
|
|
|
owner = owner_new();
|
|
|
|
|
|
|
|
|
|
if( 0 != strcmp( owner_account->handle, data.username ) ) { goto access_denied; }
|
|
|
|
|
if( !owner_check_password( owner, data.password ) ) { goto access_denied; }
|
|
|
|
|
} else {
|
|
|
|
|
printf( "7" );
|
|
|
|
|
goto invalid_request;
|
|
|
|
|
}
|
|
|
|
|
if( 0 != strcmp( app->auth_code, auth_code ) ) { goto access_denied; }
|
|
|
|
|
if( 0 != strcmp( app->client.secret, client_secret ) ) { goto access_denied; }
|
|
|
|
|
|
|
|
|
|
// TODO: check code has not expired
|
|
|
|
|
|
|
|
|
@ -227,19 +276,25 @@ static bool handle_oauth_get_token( struct http_request* req )
|
|
|
|
|
#undef RENDER
|
|
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
|
if( app ) {
|
|
|
|
|
client_app_free(app);
|
|
|
|
|
}
|
|
|
|
|
free(auth_code);
|
|
|
|
|
free(client_secret);
|
|
|
|
|
free(redirect_uri);
|
|
|
|
|
client_app_free(app);
|
|
|
|
|
free(data.auth_code);
|
|
|
|
|
free(data.redirect_uri);
|
|
|
|
|
free(data.client_secret);
|
|
|
|
|
free(data.client_id);
|
|
|
|
|
free(data.grant_type);
|
|
|
|
|
free(data.password);
|
|
|
|
|
free(data.username);
|
|
|
|
|
owner_free(owner);
|
|
|
|
|
account_free(owner_account);
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
access_denied:
|
|
|
|
|
printf( "Access denied\n" );
|
|
|
|
|
result = false;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|
invalid_request:
|
|
|
|
|
printf( "Invalid request\n" );
|
|
|
|
|
result = false;
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
|
|