diff --git a/src/datum_api.c b/src/datum_api.c index db7a162..e30ced1 100644 --- a/src/datum_api.c +++ b/src/datum_api.c @@ -68,6 +68,8 @@ const char *cbnames[] = { "Antmain2" }; +typedef struct MHD_Response *(*create_response_func_t)(); + static struct MHD_Response *datum_api_create_empty_mhd_response() { return MHD_create_response_from_buffer(0, "", MHD_RESPMEM_PERSISTENT); } @@ -406,16 +408,16 @@ int datum_api_do_error(struct MHD_Connection * const connection, const unsigned return datum_api_submit_uncached_response(connection, status_code, response); } -bool datum_api_check_admin_password_only(struct MHD_Connection * const connection, const char * const password) { +bool datum_api_check_admin_password_only(struct MHD_Connection * const connection, const char * const password, const create_response_func_t auth_failure_response_creator) { if (datum_secure_strequals(datum_config.api_admin_password, datum_config.api_admin_password_len, password) && datum_config.api_admin_password_len) { return true; } DLOG_DEBUG("Wrong password in request"); - datum_api_do_error(connection, MHD_HTTP_FORBIDDEN); + datum_api_submit_uncached_response(connection, MHD_HTTP_FORBIDDEN, auth_failure_response_creator()); return false; } -bool datum_api_check_admin_password_httponly(struct MHD_Connection * const connection) { +bool datum_api_check_admin_password_httponly(struct MHD_Connection * const connection, const create_response_func_t auth_failure_response_creator) { int ret; char * const username = MHD_digest_auth_get_username(connection); @@ -428,7 +430,7 @@ bool datum_api_check_admin_password_httponly(struct MHD_Connection * const conne } if (ret != MHD_YES) { DLOG_DEBUG("Wrong password in HTTP authentication"); - struct MHD_Response *response = datum_api_create_empty_mhd_response(); + struct MHD_Response * const response = auth_failure_response_creator(); ret = MHD_queue_auth_fail_response2(connection, realm, datum_config.api_csrf_token, response, (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO, MHD_DIGEST_ALG_SHA256); MHD_destroy_response(response); return false; @@ -437,26 +439,26 @@ bool datum_api_check_admin_password_httponly(struct MHD_Connection * const conne return true; } -bool datum_api_check_admin_password(struct MHD_Connection * const connection, const json_t * const j) { +bool datum_api_check_admin_password(struct MHD_Connection * const connection, const json_t * const j, const create_response_func_t auth_failure_response_creator) { const json_t * const j_password = json_object_get(j, "password"); if (json_is_string(j_password)) { - return datum_api_check_admin_password_only(connection, json_string_value(j_password)); + return datum_api_check_admin_password_only(connection, json_string_value(j_password), auth_failure_response_creator); } // Only accept HTTP authentication if there's an anti-CSRF token const json_t * const j_csrf = json_object_get(j, "csrf"); if (!json_is_string(j_csrf)) { DLOG_DEBUG("Missing CSRF token in request"); - datum_api_do_error(connection, MHD_HTTP_FORBIDDEN); + datum_api_submit_uncached_response(connection, MHD_HTTP_FORBIDDEN, auth_failure_response_creator()); return false; } if (!datum_secure_strequals(datum_config.api_csrf_token, sizeof(datum_config.api_csrf_token)-1, json_string_value(j_csrf))) { DLOG_DEBUG("Wrong CSRF token in request"); - datum_api_do_error(connection, MHD_HTTP_FORBIDDEN); + datum_api_submit_uncached_response(connection, MHD_HTTP_FORBIDDEN, auth_failure_response_creator()); return false; } - return datum_api_check_admin_password_httponly(connection); + return datum_api_check_admin_password_httponly(connection, auth_failure_response_creator); } static int datum_api_asset(struct MHD_Connection * const connection, const char * const mimetype, const char * const data, const size_t datasz) { @@ -540,7 +542,7 @@ int datum_api_cmd(struct MHD_Connection *connection, char *post, int len) { root = json_loadb(post, len, 0, &error); if (root) { if (json_is_object(root) && (cmd = json_object_get(root, "cmd"))) { - if (!datum_api_check_admin_password(connection, root)) { + if (!datum_api_check_admin_password(connection, root, datum_api_create_empty_mhd_response)) { json_decref(root); return MHD_YES; } @@ -587,7 +589,7 @@ int datum_api_cmd(struct MHD_Connection *connection, char *post, int len) { return datum_api_do_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR); } - if (!datum_api_check_admin_password(connection, root)) { + if (!datum_api_check_admin_password(connection, root, datum_api_create_empty_mhd_response)) { json_decref(root); return MHD_YES; } @@ -764,7 +766,7 @@ int datum_api_client_dashboard(struct MHD_Connection *connection) { MHD_add_response_header(response, "Content-Type", "text/html"); return datum_api_submit_uncached_response(connection, MHD_HTTP_OK, response); } - if (!datum_api_check_admin_password_httponly(connection)) { + if (!datum_api_check_admin_password_httponly(connection, datum_api_create_empty_mhd_response)) { return MHD_YES; } @@ -915,7 +917,7 @@ int datum_api_testnet_fastforward(struct MHD_Connection * const connection) { const char *time_str; time_str = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "password"); - if (!datum_api_check_admin_password_only(connection, time_str)) { + if (!datum_api_check_admin_password_only(connection, time_str, datum_api_create_empty_mhd_response)) { return MHD_YES; }