Start implemeting owner model, update client app model, get first stage of Oauth2 working (issuing authorization code)

master
teknomunk 1 year ago
parent 5cd2a9ea16
commit 2fd65bd84c

@ -1,6 +1,8 @@
#include "oauth.h"
#include "http_server/http_request.h"
#include "http_server/escape.h"
#include "model/client_app.h"
#include "model/owner.h"
#include "form.h"
#include <stdlib.h>
@ -88,30 +90,70 @@ cleanup:
bool route_oauth_do_authorize( struct http_request* req )
{
char* password = NULL;
char* state = NULL;
char* redirect_uri = NULL;
struct owner* o = owner_new();
struct client_app* app = NULL;
FILE* body = http_request_get_request_data(req);
struct form_parser* fp = form_pull_parser_new(body);
if( !fp ) { return false; }
char* password = NULL;
if( !fp ) {
goto invalid_request;
}
char* key;
while( key = form_pull_parser_read_key( fp ) ) {
if( 0 == strcmp(key,"password") ) {
password = strdup(form_pull_parser_read_value(fp));
printf( "password: %s\n", password );
} else if( 0 == strcmp(key,"state") ) {
state = 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,"id") ) {
const char* client_id = strdup(form_pull_parser_read_value(fp));
app = client_app_from_id( client_id );
if( !app ) { goto invalid_request; }
}
}
form_pull_parser_release(fp);
if( !password ) {
return false;
if( !app ) { goto invalid_request; }
if( !password ) { goto invalid_request; }
if( !owner_check_password( o, password ) ) {
owner_free(o);
free(password);
goto access_denied;
}
printf( "\nTODO: perform authorization\n\n" );
client_app_gen_auth_code( app );
char location[512];
char workspace[1024];
const char* fmt = ( state ? "%s?code=%s&state=%s" : "%s?code=%s" );
snprintf( location, 512, fmt, http_escape( redirect_uri, workspace, 1024, ":/" ), app->auth_code, state );
printf( "redirecting to %s\n", location );
http_request_begin_send_headers( req, 302, false );
http_request_send_header( req, "Location", location );
http_request_end_send_headers( req, false );
free(password);
return false;
invalid_request:
printf( "Invalid request\n" );
http_request_send_headers( req, 400, "text/plain", false );
fprintf( http_request_get_response_body(req), "invalid_request" );
return true;
access_denied:
printf( "Access denied\n" );
http_request_send_headers( req, 400, "text/plain", false );
fprintf( http_request_get_response_body(req), "access_denied" );
return true;
}
bool route_oauth( struct http_request* req )

@ -1 +1 @@
Subproject commit 897cc85f52f00ce959a26d3a787aa887a37e0aad
Subproject commit e45ab8bf31bf5cd69c8d1c05baa90b5672a666cd

@ -34,6 +34,8 @@ struct client_app* client_app_from_id( const char* client_id )
app->client.secret = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp(key,"name") ) {
app->client.name = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp(key,"auth_code") ) {
app->auth_code = json_pull_parser_read_string(jpp);
}
}
free(key);
@ -96,3 +98,15 @@ void client_app_free( struct client_app* app )
free(app);
}
void client_app_gen_auth_code( struct client_app* app )
{
char* auth_code = app->auth_code = malloc(65);
for( int i = 0; i < 64; ++i ) {
auth_code[i] = 'a'+(rand()%26);
}
auth_code[64] = '\0';
client_app_save(app);
}

@ -7,10 +7,15 @@ struct client_app
char* id;
char* secret;
} client;
char* redirect_uri;
char* auth_code;
// auth_expires
};
struct client_app* client_app_from_id( const char* client_id );
struct client_app* client_app_new( const char* client_name );
void client_app_save( struct client_app* app );
void client_app_free( struct client_app* app );
void client_app_gen_auth_code( struct client_app* app );

@ -1,4 +1,5 @@
{
"secret": "%s{app->client.secret}",
"name": "%s{app->client.name}"
"name": "%s{app->client.name}",
"auth_code": "%s{ app->auth_code ? app->auth_code : "" }"
}

@ -0,0 +1,80 @@
#include "owner.h"
#include "json/json.h"
#include "sha256/sha256.h"
#include <stdlib.h>
#include <stdio.h>
struct owner* owner_new()
{
struct owner* o = malloc(sizeof(struct owner));
FILE* f = fopen("data/owner.json","r");
if( f ) {
struct json_pull_parser* jpp = json_pull_parser_new(f);
if( !jpp ) {
goto reinit;
}
// Load file from
int save;
if( !json_pull_parser_begin_object( jpp, &save ) ) { goto reinit; }
char* key;
while( key = json_pull_parser_read_object_key(jpp) ) {
if( 0 == strcmp(key,"salt") ) {
o->password_salt = json_pull_parser_read_string(jpp);
} else if( 0 == strcmp(key,"hash") ) {
o->password_hash = json_pull_parser_read_string(jpp);
}
}
if( !json_pull_parser_end_object( jpp, &save ) ) { goto reinit; }
o->initialized = true;
return o;
}
reinit:
o->initialized = false;
o->password_salt = strdup("");
o->password_hash = strdup("");
return o;
}
void owner_free( struct owner* o )
{
free(o->password_salt);
free(o->password_hash);
free(o);
}
bool owner_check_password( struct owner* o, const char* passwd )
{
char buffer[512];
snprintf( buffer, 512, "%s:%s", o->password_salt, passwd );
char hash[65] = "";
sha256_easy_hash_hex( buffer, strlen(buffer), hash );
return 0 == strcmp(hash,o->password_hash);
}
void owner_set_password( struct owner* o, const char* passwd )
{
free(o->password_salt);
free(o->password_hash);
char* new_salt = o->password_salt = malloc(65);
for( int i = 0; i < 64; ++i ) {
new_salt[i] = 'a' + (rand()%26);
}
new_salt[64] = '\0';
char buffer[512];
snprintf( buffer, 512, "%s:%s", new_salt, passwd );
char* new_hash = o->password_hash = malloc(65);
sha256_easy_hash_hex( buffer, strlen(buffer), new_hash );
}

@ -1,7 +1,18 @@
#pragma once
#include <stdbool.h>
struct owner
{
bool initialized;
char* password_salt;
char* password_hash;
};
struct owner* owner_new();
void owner_save( struct owner* );
void owner_free( struct owner* );
bool owner_check_password( struct owner* o, const char* passwd );
void owner_set_password( struct owner* o, const char* passwd );

@ -22,5 +22,7 @@
<form action="/oauth/authorize" method="post">
Password: <input type='password' name='password'/><br/>
<input type="submit" />
<input type='hidden' name='id' value='%s{app->client.id}' />
<input type='hidden' name='redirect_uri' value='%s{redirect_uri}' />
</form>

Loading…
Cancel
Save