From c3340dd73d11f66671bf37d059cd2901d0551e71 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 15 Oct 2020 15:23:52 +0000 Subject: [PATCH] Fix: Handle safe HTTP methods in unsafe context correctly Closes: #2398 --- admin/dashboard.xsl | 2 +- admin/showlog.xsl | 2 +- admin/stats.xsl | 2 +- src/admin.c | 159 ++++++++++++++++++++++++++++---------------- src/admin.h | 6 ++ src/errors.c | 3 + src/errors.h | 1 + 7 files changed, 115 insertions(+), 60 deletions(-) diff --git a/admin/dashboard.xsl b/admin/dashboard.xsl index 5ffa1d8b..3f779865 100644 --- a/admin/dashboard.xsl +++ b/admin/dashboard.xsl @@ -9,7 +9,7 @@

Overview for

diff --git a/admin/showlog.xsl b/admin/showlog.xsl index 67f634cc..da55c606 100644 --- a/admin/showlog.xsl +++ b/admin/showlog.xsl @@ -11,7 +11,7 @@
  • -
  • Mark logfiles
  • +
  • Mark logfiles
    • diff --git a/admin/stats.xsl b/admin/stats.xsl index 08d75c44..9e64d0f9 100644 --- a/admin/stats.xsl +++ b/admin/stats.xsl @@ -43,7 +43,7 @@ diff --git a/src/admin.c b/src/admin.c index 71814170..9c072697 100644 --- a/src/admin.c +++ b/src/admin.c @@ -145,66 +145,66 @@ static void command_mark_log (client_t *client, source_t *source, adm static void command_dashboard (client_t *client, source_t *source, admin_format_t response); static const admin_command_handler_t handlers[] = { - { "*", ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, NULL, NULL}, /* for ACL framework */ - { FALLBACK_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_fallback, NULL}, - { FALLBACK_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, command_fallback, NULL}, - { FALLBACK_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, command_fallback, NULL}, - { METADATA_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_metadata, NULL}, - { METADATA_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, command_metadata, NULL}, - { METADATA_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, command_metadata, NULL}, - { SHOUTCAST_METADATA_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, command_shoutcast_metadata, NULL}, - { LISTCLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_show_listeners, NULL}, - { LISTCLIENTS_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, command_show_listeners, NULL}, - { LISTCLIENTS_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, command_show_listeners, NULL}, - { STATS_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_RAW, command_stats, NULL}, - { STATS_HTML_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, command_stats, NULL}, - { STATS_JSON_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_JSON, command_stats, NULL}, - { "stats.xml", ADMINTYPE_HYBRID, ADMIN_FORMAT_RAW, command_stats, NULL}, - { PUBLICSTATS_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_RAW, command_public_stats, NULL}, - { PUBLICSTATS_JSON_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_JSON, command_public_stats, NULL}, - { QUEUE_RELOAD_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, command_queue_reload, NULL}, - { QUEUE_RELOAD_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, command_queue_reload, NULL}, - { QUEUE_RELOAD_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, command_queue_reload, NULL}, - { LISTMOUNTS_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, command_list_mounts, NULL}, - { LISTMOUNTS_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, command_list_mounts, NULL}, - { LISTMOUNTS_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, command_list_mounts, NULL}, - { STREAMLIST_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, command_list_mounts, NULL}, - { STREAMLIST_PLAINTEXT_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_PLAINTEXT, command_list_mounts, NULL}, - { STREAMLIST_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, command_list_mounts, NULL}, - { STREAMLIST_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, command_list_mounts, NULL}, - { MOVECLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_move_clients, NULL}, - { MOVECLIENTS_HTML_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, command_move_clients, NULL}, - { MOVECLIENTS_JSON_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_JSON, command_move_clients, NULL}, - { KILLCLIENT_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_kill_client, NULL}, - { KILLCLIENT_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, command_kill_client, NULL}, - { KILLCLIENT_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, command_kill_client, NULL}, - { KILLSOURCE_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_kill_source, NULL}, - { KILLSOURCE_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, command_kill_source, NULL}, - { KILLSOURCE_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, command_kill_source, NULL}, - { MANAGEAUTH_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, command_manageauth, NULL}, - { MANAGEAUTH_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, command_manageauth, NULL}, - { MANAGEAUTH_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, command_manageauth, NULL}, - { UPDATEMETADATA_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_updatemetadata, NULL}, - { UPDATEMETADATA_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, command_updatemetadata, NULL}, - { UPDATEMETADATA_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, command_updatemetadata, NULL}, - { BUILDM3U_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, command_buildm3u, NULL}, - { SHOWLOG_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, command_show_log, NULL}, - { SHOWLOG_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, command_show_log, NULL}, - { SHOWLOG_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, command_show_log, NULL}, - { MARKLOG_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, command_mark_log, NULL}, - { MARKLOG_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, command_mark_log, NULL}, - { MARKLOG_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, command_mark_log, NULL}, - { DASHBOARD_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, command_dashboard, NULL}, - { DASHBOARD_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, command_dashboard, NULL}, - { DASHBOARD_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, command_dashboard, NULL}, - { DEFAULT_HTML_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, command_default_selector, NULL}, - { DEFAULT_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, command_default_selector, NULL} + { "*", ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_UNSAFE, NULL, NULL}, /* for ACL framework */ + { FALLBACK_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_HYBRID, command_fallback, NULL}, + { FALLBACK_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, ADMINSAFE_HYBRID, command_fallback, NULL}, + { FALLBACK_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, ADMINSAFE_HYBRID, command_fallback, NULL}, + { METADATA_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_UNSAFE, command_metadata, NULL}, + { METADATA_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, ADMINSAFE_UNSAFE, command_metadata, NULL}, + { METADATA_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, ADMINSAFE_UNSAFE, command_metadata, NULL}, + { SHOUTCAST_METADATA_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, ADMINSAFE_UNSAFE, command_shoutcast_metadata, NULL}, + { LISTCLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_show_listeners, NULL}, + { LISTCLIENTS_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_show_listeners, NULL}, + { LISTCLIENTS_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_show_listeners, NULL}, + { STATS_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_stats, NULL}, + { STATS_HTML_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_stats, NULL}, + { STATS_JSON_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_stats, NULL}, + { "stats.xml", ADMINTYPE_HYBRID, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_stats, NULL}, + { PUBLICSTATS_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_public_stats, NULL}, + { PUBLICSTATS_JSON_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_public_stats, NULL}, + { QUEUE_RELOAD_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, ADMINSAFE_UNSAFE, command_queue_reload, NULL}, + { QUEUE_RELOAD_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_UNSAFE, command_queue_reload, NULL}, + { QUEUE_RELOAD_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, ADMINSAFE_UNSAFE, command_queue_reload, NULL}, + { LISTMOUNTS_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_list_mounts, NULL}, + { LISTMOUNTS_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_list_mounts, NULL}, + { LISTMOUNTS_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_list_mounts, NULL}, + { STREAMLIST_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_list_mounts, NULL}, + { STREAMLIST_PLAINTEXT_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_PLAINTEXT, ADMINSAFE_SAFE, command_list_mounts, NULL}, + { STREAMLIST_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_list_mounts, NULL}, + { STREAMLIST_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_list_mounts, NULL}, + { MOVECLIENTS_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_HYBRID, command_move_clients, NULL}, + { MOVECLIENTS_HTML_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, ADMINSAFE_HYBRID, command_move_clients, NULL}, + { MOVECLIENTS_JSON_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_JSON, ADMINSAFE_HYBRID, command_move_clients, NULL}, + { KILLCLIENT_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_UNSAFE, command_kill_client, NULL}, + { KILLCLIENT_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, ADMINSAFE_UNSAFE, command_kill_client, NULL}, + { KILLCLIENT_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, ADMINSAFE_UNSAFE, command_kill_client, NULL}, + { KILLSOURCE_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_UNSAFE, command_kill_source, NULL}, + { KILLSOURCE_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, ADMINSAFE_UNSAFE, command_kill_source, NULL}, + { KILLSOURCE_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, ADMINSAFE_UNSAFE, command_kill_source, NULL}, + { MANAGEAUTH_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, ADMINSAFE_HYBRID, command_manageauth, NULL}, + { MANAGEAUTH_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_HYBRID, command_manageauth, NULL}, + { MANAGEAUTH_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, ADMINSAFE_HYBRID, command_manageauth, NULL}, + { UPDATEMETADATA_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_updatemetadata, NULL}, + { UPDATEMETADATA_HTML_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_updatemetadata, NULL}, + { UPDATEMETADATA_JSON_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_updatemetadata, NULL}, + { BUILDM3U_RAW_REQUEST, ADMINTYPE_MOUNT, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_buildm3u, NULL}, + { SHOWLOG_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_show_log, NULL}, + { SHOWLOG_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_show_log, NULL}, + { SHOWLOG_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_show_log, NULL}, + { MARKLOG_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, ADMINSAFE_UNSAFE, command_mark_log, NULL}, + { MARKLOG_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_UNSAFE, command_mark_log, NULL}, + { MARKLOG_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, ADMINSAFE_UNSAFE, command_mark_log, NULL}, + { DASHBOARD_RAW_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_RAW, ADMINSAFE_SAFE, command_dashboard, NULL}, + { DASHBOARD_HTML_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_dashboard, NULL}, + { DASHBOARD_JSON_REQUEST, ADMINTYPE_GENERAL, ADMIN_FORMAT_JSON, ADMINSAFE_SAFE, command_dashboard, NULL}, + { DEFAULT_HTML_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_default_selector, NULL}, + { DEFAULT_RAW_REQUEST, ADMINTYPE_HYBRID, ADMIN_FORMAT_HTML, ADMINSAFE_SAFE, command_default_selector, NULL} }; static void ui_command(client_t * client, source_t * source, admin_format_t format, resourcematch_extract_t *parameters); static const admin_command_handler_t ui_handlers[] = { - { "%s", ADMINTYPE_HYBRID, ADMIN_FORMAT_AUTO, NULL, ui_command} + { "%s", ADMINTYPE_HYBRID, ADMIN_FORMAT_AUTO, ADMINSAFE_SAFE, NULL, ui_command} }; static admin_command_table_t command_tables[ADMIN_MAX_COMMAND_TABLES] = { @@ -374,6 +374,34 @@ int admin_command_table_unregister(const char *prefix) return -1; } +/* Enforces requests HTTP unsafe (e.g. POST not GET). + * Returns true if the request has been handled (rejected) and false if the request is still for open for handling (passed). + */ +static int admin_enforce_unsafe(client_t *client) +{ + // check if the client is using an unsafe method, if so just return. + if (!(httpp_request_info(client->parser->req_type) & HTTPP_REQUEST_IS_SAFE)) + return 0; + + switch (client->mode) { + case OMODE_LEGACY: + // no-op + break; + case OMODE_STRICT: + ICECAST_LOG_WARN("Client %p (role=%H, acl=%H, username=%H) rejected for use of safe method %s on %H", + client, client->role, acl_get_name(client->acl), client->username, httpp_getvar(client->parser, HTTPP_VAR_REQ_TYPE), client->uri); + client_send_error_by_id(client, ICECAST_ERROR_GEN_SAFE_METHOD_ON_UNSAFE_CALL); + return 1; + break; + default: + ICECAST_LOG_WARN("Client %p (role=%H, acl=%H, username=%H) uses safe method %s on %H", + client, client->role, acl_get_name(client->acl), client->username, httpp_getvar(client->parser, HTTPP_VAR_REQ_TYPE), client->uri); + break; + } + + return 0; +} + /* build an XML root node including some common tags */ xmlNodePtr admin_build_rootnode(xmlDocPtr doc, const char *name) { @@ -604,6 +632,11 @@ void admin_handle_request(client_t *client, const char *uri) return; } + if (handler->safeness == ADMINSAFE_UNSAFE) { + if (admin_enforce_unsafe(client)) + return; + } + if (handler->format == ADMIN_FORMAT_AUTO) { format = client_get_admin_format_by_content_negotiation(client); } else { @@ -711,6 +744,9 @@ static void command_move_clients(client_t *client, return; } + if (admin_enforce_unsafe(client)) + return; + dest = source_find_mount(dest_source); if (dest == NULL) { @@ -919,6 +955,10 @@ static void command_manageauth(client_t *client, source_t *source, admin_format_ if (!strcmp(action, "add")) { const char *password = NULL; + + if (admin_enforce_unsafe(client)) + return; + COMMAND_OPTIONAL(client, "password", password); if (username == NULL || password == NULL) { @@ -944,8 +984,10 @@ static void command_manageauth(client_t *client, source_t *source, admin_format_ auth_release(auth); return; } - } - if (!strcmp(action, "delete")) { + } else if (!strcmp(action, "delete")) { + if (admin_enforce_unsafe(client)) + return; + if (username == NULL) { ICECAST_LOG_WARN("manage auth request delete for %lu but no username", id); break; @@ -1055,6 +1097,9 @@ static void command_fallback(client_t *client, } } + if (admin_enforce_unsafe(client)) + return; + COMMAND_REQUIRE(client, "fallback", fallback); util_replace_string(&(source->fallback_mount), fallback); diff --git a/src/admin.h b/src/admin.h index 1245a194..698b00eb 100644 --- a/src/admin.h +++ b/src/admin.h @@ -29,6 +29,11 @@ #define ADMINTYPE_MOUNT 2 #define ADMINTYPE_HYBRID (ADMINTYPE_GENERAL|ADMINTYPE_MOUNT) +/* HTTP safeness */ +#define ADMINSAFE_SAFE 1 +#define ADMINSAFE_UNSAFE 2 +#define ADMINSAFE_HYBRID (ADMINSAFE_SAFE|ADMINSAFE_UNSAFE) + /* special commands */ #define ADMIN_COMMAND_ERROR ((admin_command_id_t)(-1)) #define ADMIN_COMMAND_ANY ((admin_command_id_t)0) /* for ACL framework */ @@ -40,6 +45,7 @@ typedef struct admin_command_handler { const char *route; const int type; const int format; + const int safeness; const admin_request_function_ptr function; const admin_request_function_with_parameters_ptr function_with_parameters; } admin_command_handler_t; diff --git a/src/errors.c b/src/errors.c index 06e4185c..1bd2facc 100644 --- a/src/errors.c +++ b/src/errors.c @@ -123,6 +123,9 @@ static const icecast_error_t __errors[] = { {.id = ICECAST_ERROR_GEN_MEMORY_EXHAUSTED, .http_status = 503, .uuid = "18411e73-713e-4910-b7e4-52a2e324b4e0", .message = "memory exhausted"}, + {.id = ICECAST_ERROR_GEN_SAFE_METHOD_ON_UNSAFE_CALL, .http_status = 405, + .uuid = "6f4c95e3-b446-4814-b4b8-0cb585dbe4bd", + .message = "Safe HTTP method used on unsafe call"}, {.id = ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE, .http_status = 404 /* XXX */, .uuid = "88d06875-fcf2-4417-84af-05866c97745c", .message = "Mount unavailable"}, diff --git a/src/errors.h b/src/errors.h index 62c446bc..0b836772 100644 --- a/src/errors.h +++ b/src/errors.h @@ -45,6 +45,7 @@ typedef enum { ICECAST_ERROR_GEN_CLIENT_NEEDS_TO_AUTHENTICATE, ICECAST_ERROR_GEN_HEADER_GEN_FAILED, ICECAST_ERROR_GEN_MEMORY_EXHAUSTED, + ICECAST_ERROR_GEN_SAFE_METHOD_ON_UNSAFE_CALL, ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE, ICECAST_ERROR_SOURCE_STREAM_PREPARATION_ERROR, ICECAST_ERROR_SOURCE_MAX_LISTENERS,