plugins/mod_http_errors.lua
author Jonas Schäfer <jonas@wielicki.name>
Mon, 10 Jan 2022 18:23:54 +0100
branch0.11
changeset 12185 783056b4e448
parent 8367 f91ab40a3105
child 9764 88640b3ea6b8
permissions -rw-r--r--
util.xml: Do not allow doctypes, comments or processing instructions Yes. This is as bad as it sounds. CVE pending. In Prosody itself, this only affects mod_websocket, which uses util.xml to parse the <open/> frame, thus allowing unauthenticated remote DoS using Billion Laughs. However, third-party modules using util.xml may also be affected by this. This commit installs handlers which disallow the use of doctype declarations and processing instructions without any escape hatch. It, by default, also introduces such a handler for comments, however, there is a way to enable comments nontheless. This is because util.xml is used to parse human-facing data, where comments are generally a desirable feature, and also because comments are generally harmless.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
module:set_global();
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
local server = require "net.http.server";
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
local codes = require "net.http.codes";
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
     5
local xml_escape = require "util.stanza".xml_escape;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
     6
local render = require "util.interpolation".new("%b{}", xml_escape);
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
local show_private = module:get_option_boolean("http_errors_detailed", false);
4737
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
     9
local always_serve = module:get_option_boolean("http_errors_always_show", true);
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
    10
local default_message = { module:get_option_string("http_errors_default_message", "That's all I know.") };
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
local default_messages = {
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    12
	[400] = { "What kind of request do you call that??" };
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    13
	[403] = { "You're not allowed to do that." };
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
	[404] = { "Whatever you were looking for is not here. %";
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    15
		"Where did you put it?", "It's behind you.", "Keep looking." };
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
	[500] = { "% Check your error log for more info.";
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
		"Gremlins.", "It broke.", "Don't look at me." };
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
};
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
local messages = setmetatable(module:get_option("http_errors_messages", {}), { __index = default_messages });
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
local html = [[
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
<!DOCTYPE html>
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
<html>
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
<head>
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    26
<meta charset="utf-8">
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    27
<title>{title}</title>
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    28
<style>
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    29
body{
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    30
	margin-top:14%;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    31
	text-align:center;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    32
	background-color:#F8F8F8;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    33
	font-family:sans-serif;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    34
}
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    35
h1{
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    36
	font-size:xx-large;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    37
}
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    38
p{
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    39
	font-size:x-large;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    40
}
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    41
p+p {
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    42
	font-size:large;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    43
	font-family:courier;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    44
}
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    45
</style>
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
</head>
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    47
<body>
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    48
<h1>{title}</h1>
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    49
<p>{message}</p>
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    50
<p>{extra?}</p>
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
</body>
7495
9a749cf8c1ba mod_http_errors: Add a newline after end of HTML
Kim Alvefur <zash@zash.se>
parents: 5776
diff changeset
    52
</html>
9a749cf8c1ba mod_http_errors: Add a newline after end of HTML
Kim Alvefur <zash@zash.se>
parents: 5776
diff changeset
    53
]];
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    55
local function get_page(code, extra)
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
	local message = messages[code];
4737
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
    57
	if always_serve or message then
7b9e2a8c4710 mod_http_errors: Add two new config options, http_errors_always_show (show even for unknown errors) and http_errors_default_message (message for unknown errors)
Matthew Wild <mwild1@gmail.com>
parents: 4711
diff changeset
    58
		message = message or default_message;
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    59
		return render(html, {
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
			title = rawget(codes, code) or ("Code "..tostring(code));
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
			message = message[1]:gsub("%%", function ()
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
				return message[math.random(2, math.max(#message,2))];
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
			end);
8367
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    64
			extra = extra;
f91ab40a3105 mod_http_errors: Use util.interpolation to render HTML template
Kim Alvefur <zash@zash.se>
parents: 8366
diff changeset
    65
		});
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
	end
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
end
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
module:hook_object_event(server, "http-error", function (event)
8366
e2460edc2a2f mod_http_errors: Set Content-Type header to HTML (fixes #1030)
Kim Alvefur <zash@zash.se>
parents: 7495
diff changeset
    70
	if event.response then
e2460edc2a2f mod_http_errors: Set Content-Type header to HTML (fixes #1030)
Kim Alvefur <zash@zash.se>
parents: 7495
diff changeset
    71
		event.response.headers.content_type = "text/html; charset=utf-8";
e2460edc2a2f mod_http_errors: Set Content-Type header to HTML (fixes #1030)
Kim Alvefur <zash@zash.se>
parents: 7495
diff changeset
    72
	end
4711
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    73
	return get_page(event.code, (show_private and event.private_message) or event.message);
4ddf3ba0c749 mod_http_errors: Module to handle HTTP errors with a HTML page
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
end);