diff --git a/src/datum_api.c b/src/datum_api.c index aa8a845..10d5d28 100644 --- a/src/datum_api.c +++ b/src/datum_api.c @@ -417,36 +417,38 @@ bool datum_api_check_admin_password_only(struct MHD_Connection * const connectio return false; } -static enum MHD_DigestAuthAlgorithm datum_api_pick_digest_algo(struct MHD_Connection * const connection, const bool nonce_is_stale) { +static enum MHD_DigestAuthAlgorithm datum_api_pick_digest_algo(struct MHD_Connection * const connection) { const char * const ua = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "User-Agent"); - if (strstr(ua, "AppleWebKit/") && !(strstr(ua, "Chrome/") || strstr(ua, "Brave/") || strstr(ua, "Edge/"))) { - static bool safari_warned = false; - if (!(nonce_is_stale && safari_warned)) { - DLOG_WARN("Detected login request from Apple Safari. For some reason, this browser only supports obsolete and insecure MD5 digest authentication. Login at your own risk!"); - safari_warned = true; + if (datum_config.api_allow_insecure_auth) { + if (strstr(ua, "AppleWebKit/") && !(strstr(ua, "Chrome/") || strstr(ua, "Brave/") || strstr(ua, "Edge/"))) { + return MHD_DIGEST_ALG_MD5; } - return MHD_DIGEST_ALG_MD5; } return MHD_DIGEST_ALG_SHA256; } bool datum_api_check_admin_password_httponly(struct MHD_Connection * const connection, const create_response_func_t auth_failure_response_creator) { int ret; + static bool safari_warned = false; char * const username = MHD_digest_auth_get_username(connection); + const enum MHD_DigestAuthAlgorithm algo = datum_api_pick_digest_algo(connection); const char * const realm = "DATUM Gateway"; if (username) { - ret = MHD_digest_auth_check2(connection, realm, username, datum_config.api_admin_password, 300, MHD_DIGEST_ALG_AUTO); + ret = MHD_digest_auth_check2(connection, realm, username, datum_config.api_admin_password, 300, algo); free(username); } else { ret = MHD_NO; } + if (algo == MHD_DIGEST_ALG_MD5 && (ret == MHD_NO || !safari_warned)) { + DLOG_WARN("Detected login request from Apple Safari. For some reason, this browser only supports obsolete and insecure MD5 digest authentication. Login at your own risk!"); + safari_warned = true; + } if (ret != MHD_YES) { const bool nonce_is_stale = (ret == MHD_INVALID_NONCE); if (username && !nonce_is_stale) { DLOG_DEBUG("Wrong password in HTTP authentication"); } - const enum MHD_DigestAuthAlgorithm algo = datum_api_pick_digest_algo(connection, nonce_is_stale); struct MHD_Response * const response = auth_failure_response_creator(); ret = MHD_queue_auth_fail_response2(connection, realm, datum_config.api_csrf_token, response, nonce_is_stale ? MHD_YES : MHD_NO, algo); MHD_destroy_response(response); diff --git a/src/datum_conf.c b/src/datum_conf.c index 0ad1267..cf8f935 100644 --- a/src/datum_conf.c +++ b/src/datum_conf.c @@ -108,6 +108,8 @@ const T_DATUM_CONFIG_ITEM datum_config_options[] = { .required = false, .ptr = datum_config.api_admin_password, .default_string[0] = "", .max_string_len = sizeof(datum_config.api_admin_password) }, { .var_type = DATUM_CONF_INT, .category = "api", .name = "listen_port", .description = "Port to listen for API/dashboard requests (0=disabled)", .required = false, .ptr = &datum_config.api_listen_port, .default_int = 0 }, + { .var_type = DATUM_CONF_BOOL, .category = "api", .name = "allow_insecure_auth", .description = "Allow insecure authentication (required for Safari)", + .required = false, .ptr = &datum_config.api_allow_insecure_auth, .default_bool = false }, // extra block submissions list { .var_type = DATUM_CONF_STRING_ARRAY, .category = "extra_block_submissions", .name = "urls", .description = "Array of bitcoind RPC URLs to submit our blocks to directly. Include auth info: http://user:pass@IP", diff --git a/src/datum_conf.h b/src/datum_conf.h index 2bb2095..8b216ae 100644 --- a/src/datum_conf.h +++ b/src/datum_conf.h @@ -98,6 +98,7 @@ typedef struct { size_t api_admin_password_len; char api_csrf_token[65]; int api_listen_port; + bool api_allow_insecure_auth; int extra_block_submissions_count; char extra_block_submissions_urls[DATUM_MAX_BLOCK_SUBMITS][DATUM_CONFIG_MAX_STRING_ARRAY_LEN];