From 5c1d94de1b67353da7e2c348379c8a8509a9e66a Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 14 Mar 2015 22:39:03 +0000 Subject: net.http.server: Log event name when firing a request event --- net/http/server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/http/server.lua b/net/http/server.lua index 7937f87c..f091595c 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -217,7 +217,7 @@ function handle_request(conn, request, finish_cb) local event = request.method.." "..host..request.path:match("[^?]*"); local payload = { request = request, response = response }; - --log("debug", "Firing event: %s", event); + log("debug", "Firing event: %s", event); local result = events.fire_event(event, payload); if result ~= nil then if result ~= true then -- cgit v1.2.3 From 45016aef3587db22807791ad0be11d02847c496c Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 14 Mar 2015 22:39:23 +0000 Subject: mod_http: Log event name when adding a HTTP app's hooks --- plugins/mod_http.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index 86689aff..610ae0ae 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -102,6 +102,7 @@ function module.add_host(module) end if not app_handlers[event_name] then app_handlers[event_name] = handler; + module:log("debug", "Adding app '%s' to handle %s", app_name, event_name); module:hook_object_event(server, event_name, handler); else module:log("warn", "App %s added handler twice for '%s', ignoring", app_name, event_name); -- cgit v1.2.3 From 7bf2c14e9f702d8bcb0aa0db64fabad272d19d5d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Mar 2015 14:26:34 +0100 Subject: util.encodings: Perform validation of UTF-8 strings before passing to libidn (Based on code from the utf8 library in Lua 5.3) --- util-src/encodings.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/util-src/encodings.c b/util-src/encodings.c index b9b6160a..898add1a 100644 --- a/util-src/encodings.c +++ b/util-src/encodings.c @@ -1,6 +1,7 @@ /* Prosody IM -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain +-- Copyright (C) 1994-2015 Lua.org, PUC-Rio. -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. @@ -116,6 +117,65 @@ static const luaL_Reg Reg_base64[] = { NULL, NULL } }; +/******************* UTF-8 ********************/ + +/* + * Adapted from Lua 5.3 + * Needed because libidn does not validate that input is valid UTF-8 + */ + +#define MAXUNICODE 0x10FFFF + +/* + * Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. + */ +static const char *utf8_decode (const char *o, int *val) { + static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; + const unsigned char *s = (const unsigned char *)o; + unsigned int c = s[0]; + unsigned int res = 0; /* final result */ + if (c < 0x80) /* ascii? */ + res = c; + else { + int count = 0; /* to count number of continuation bytes */ + while (c & 0x40) { /* still have continuation bytes? */ + int cc = s[++count]; /* read next byte */ + if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + return NULL; /* invalid byte sequence */ + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ + c <<= 1; /* to test next bit */ + } + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ + if (count > 3 || res > MAXUNICODE || res <= limits[count] || (0xd800 <= res && res <= 0xdfff) ) + return NULL; /* invalid byte sequence */ + s += count; /* skip continuation bytes read */ + } + if (val) *val = res; + return (const char *)s + 1; /* +1 to include first byte */ +} + +/* + * Check that a string is valid UTF-8 + * Returns NULL if not + */ +const char* check_utf8 (lua_State *L, int idx, size_t *l) { + size_t pos, len; + const char *s = luaL_checklstring(L, 1, &len); + pos = 0; + while (pos <= len) { + const char *s1 = utf8_decode(s + pos, NULL); + if (s1 == NULL) { /* conversion error? */ + return NULL; + } + pos = s1 - s; + } + if(l != NULL) { + *l = len; + } + return s; +} + + /***************** STRINGPREP *****************/ #ifdef USE_STRINGPREP_ICU @@ -212,8 +272,8 @@ static int stringprep_prep(lua_State *L, const Stringprep_profile *profile) lua_pushnil(L); return 1; } - s = lua_tolstring(L, 1, &len); - if (len >= 1024) { + s = check_utf8(L, 1, &len); + if (s == NULL || len >= 1024 || len != strlen(s)) { lua_pushnil(L); return 1; /* TODO return error message */ } @@ -320,7 +380,11 @@ static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */ static int Lidna_to_ascii(lua_State *L) /** idna.to_ascii(s) */ { size_t len; - const char *s = luaL_checklstring(L, 1, &len); + const char *s = check_utf8(L, 1, &len); + if (s == NULL || len != strlen(s)) { + lua_pushnil(L); + return 1; /* TODO return error message */ + } char* output = NULL; int ret = idna_to_ascii_8z(s, &output, IDNA_USE_STD3_ASCII_RULES); if (ret == IDNA_SUCCESS) { -- cgit v1.2.3 From b9f798f83a4dd10e44ccb2e6fa680f3911e67764 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Mar 2015 14:27:30 +0100 Subject: util.encodings: Expose UTF-8 validation and length checking functions --- util-src/encodings.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/util-src/encodings.c b/util-src/encodings.c index 898add1a..91826ca4 100644 --- a/util-src/encodings.c +++ b/util-src/encodings.c @@ -175,6 +175,29 @@ const char* check_utf8 (lua_State *L, int idx, size_t *l) { return s; } +static int Lutf8_valid(lua_State *L) { + lua_pushboolean(L, check_utf8(L, 1, NULL) != NULL); + return 1; +} + +static int Lutf8_length(lua_State *L) { + size_t len; + if(!check_utf8(L, 1, &len)) { + lua_pushnil(L); + lua_pushliteral(L, "invalid utf8"); + return 2; + } + lua_pushinteger(L, len); + return 1; +} + +static const luaL_Reg Reg_utf8[] = +{ + { "valid", Lutf8_valid }, + { "length", Lutf8_length }, + { NULL, NULL } +}; + /***************** STRINGPREP *****************/ #ifdef USE_STRINGPREP_ICU @@ -452,6 +475,11 @@ LUALIB_API int luaopen_util_encodings(lua_State *L) luaL_register(L, NULL, Reg_idna); lua_settable(L,-3); + lua_pushliteral(L, "utf8"); + lua_newtable(L); + luaL_register(L, NULL, Reg_utf8); + lua_settable(L, -3); + lua_pushliteral(L, "version"); /** version */ lua_pushliteral(L, "-3.14"); lua_settable(L,-3); -- cgit v1.2.3 From fa4ef8d7ff12a38a5f1d07e2a0b64d7f92bd1142 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Mar 2015 17:16:54 +0000 Subject: tests: Add UTF-8 validity tests --- tests/test.lua | 1 + tests/test_utf8.lua | 19 ++++++++++++++++++ tests/utf8_sequences.txt | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 tests/test_utf8.lua create mode 100644 tests/utf8_sequences.txt diff --git a/tests/test.lua b/tests/test.lua index db727ce1..de1e40fd 100644 --- a/tests/test.lua +++ b/tests/test.lua @@ -22,6 +22,7 @@ function run_all_tests() dotest "util.sasl.scram" dosingletest("test_sasl.lua", "latin1toutf8"); + dosingletest("test_utf8.lua", "valid"); end local verbosity = tonumber(arg[1]) or 2; diff --git a/tests/test_utf8.lua b/tests/test_utf8.lua new file mode 100644 index 00000000..481eff5d --- /dev/null +++ b/tests/test_utf8.lua @@ -0,0 +1,19 @@ +package.cpath = "../?.so" +package.path = "../?.lua"; + +function valid() + local encodings = require "util.encodings"; + local utf8 = assert(encodings.utf8, "no encodings.utf8 module"); + + for line in io.lines("utf8_sequences.txt") do + local data = line:match(":%s*([^#]+)"):gsub("%s+", ""):gsub("..", function (c) return string.char(tonumber(c, 16)); end) + local expect = line:match("(%S+):"); + if expect ~= "pass" and expect ~= "fail" then + error("unknown expectation: "..line:match("^[^:]+")); + end + local prefix, style = " ", valid_style; + local valid = utf8.valid(data); + assert_equal(valid, utf8.valid(data.." ")); + assert_equal(valid, expect == "pass", line); + end +end diff --git a/tests/utf8_sequences.txt b/tests/utf8_sequences.txt new file mode 100644 index 00000000..408b8f08 --- /dev/null +++ b/tests/utf8_sequences.txt @@ -0,0 +1,52 @@ +Should pass: 41 42 43 # Simple ASCII - abc +Should pass: 41 42 c3 87 # "ABÇ" +Should pass: 41 42 e1 b8 88 # "ABḈ" +Should pass: 41 42 f0 9d 9c 8d # "AB𝜍" +Should pass: F4 8F BF BF # Last valid sequence (U+10FFFF) +Should fail: F4 90 80 80 # First invalid sequence (U+110000) +Should fail: 80 81 82 83 # Invalid sequence (invalid start byte) +Should fail: C2 C3 # Invalid sequence (invalid continuation byte) +Should fail: C0 43 # Overlong sequence +Should fail: F5 80 80 80 # U+140000 (out of range) +Should fail: ED A0 80 # U+D800 (forbidden by RFC 3629) +Should fail: ED BF BF # U+DFFF (forbidden by RFC 3629) +Should pass: ED 9F BF # U+D7FF (U+D800 minus 1: allowed) +Should pass: EE 80 80 # U+E000 (U+D7FF plus 1: allowed) +Should fail: C0 # Invalid start byte +Should fail: C1 # Invalid start byte +Should fail: C2 # Incomplete sequence +Should fail: F8 88 80 80 80 # 6-byte sequence +Should pass: 7F # Last valid 1-byte sequence (U+00007F) +Should pass: DF BF # Last valid 2-byte sequence (U+0007FF) +Should pass: EF BF BF # Last valid 3-byte sequence (U+00FFFF) +Should pass: 00 # First valid 1-byte sequence (U+000000) +Should pass: C2 80 # First valid 2-byte sequence (U+000080) +Should pass: E0 A0 80 # First valid 3-byte sequence (U+000800) +Should pass: F0 90 80 80 # First valid 4-byte sequence (U+000800) +Should fail: F8 88 80 80 80 # First 5-byte sequence - invalid per RFC 3629 +Should fail: FC 84 80 80 80 80 # First 6-byte sequence - invalid per RFC 3629 +Should pass: EF BF BD # U+00FFFD (replacement character) +Should fail: 80 # First continuation byte +Should fail: BF # Last continuation byte +Should fail: 80 BF # 2 continuation bytes +Should fail: 80 BF 80 # 3 continuation bytes +Should fail: 80 BF 80 BF # 4 continuation bytes +Should fail: 80 BF 80 BF 80 # 5 continuation bytes +Should fail: 80 BF 80 BF 80 BF # 6 continuation bytes +Should fail: 80 BF 80 BF 80 BF 80 # 7 continuation bytes +Should fail: FE # Impossible byte +Should fail: FF # Impossible byte +Should fail: FE FE FF FF # Impossible bytes +Should fail: C0 AF # Overlong "/" +Should fail: E0 80 AF # Overlong "/" +Should fail: F0 80 80 AF # Overlong "/" +Should fail: F8 80 80 80 AF # Overlong "/" +Should fail: FC 80 80 80 80 AF # Overlong "/" +Should fail: C0 80 AF # Overlong "/" (invalid) +Should fail: C1 BF # Overlong +Should fail: E0 9F BF # Overlong +Should fail: F0 8F BF BF # Overlong +Should fail: F8 87 BF BF BF # Overlong +Should fail: FC 83 BF BF BF BF # Overlong +Should pass: EF BF BE # U+FFFE (invalid unicode, valid UTF-8) +Should fail: EF BF BF # U+FFFF (invalid unicode, valid UTF-8) -- cgit v1.2.3 From 29f9bdc56e50ac647ab23ee05d190d0dd1078941 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Mar 2015 17:23:11 +0000 Subject: utf8_sequences.txt: Oops --- tests/utf8_sequences.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utf8_sequences.txt b/tests/utf8_sequences.txt index 408b8f08..1b967b2e 100644 --- a/tests/utf8_sequences.txt +++ b/tests/utf8_sequences.txt @@ -49,4 +49,4 @@ Should fail: F0 8F BF BF # Overlong Should fail: F8 87 BF BF BF # Overlong Should fail: FC 83 BF BF BF BF # Overlong Should pass: EF BF BE # U+FFFE (invalid unicode, valid UTF-8) -Should fail: EF BF BF # U+FFFF (invalid unicode, valid UTF-8) +Should pass: EF BF BF # U+FFFF (invalid unicode, valid UTF-8) -- cgit v1.2.3 From 272f0cf5e541c228f61bfef63d327722b9c6e482 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Mar 2015 18:40:12 +0100 Subject: Backout 7726b627c3ea --- plugins/mod_http.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index 610ae0ae..86689aff 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -102,7 +102,6 @@ function module.add_host(module) end if not app_handlers[event_name] then app_handlers[event_name] = handler; - module:log("debug", "Adding app '%s' to handle %s", app_name, event_name); module:hook_object_event(server, event_name, handler); else module:log("warn", "App %s added handler twice for '%s', ignoring", app_name, event_name); -- cgit v1.2.3 From 3550cf7e8e56e8d331596916006cdb8e57221e1c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Mar 2015 18:44:12 +0100 Subject: mod_http: Log a debug message when adding new http apps and warn if no http ports are enabled --- plugins/mod_http.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index 86689aff..9ff3af74 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -110,6 +110,12 @@ function module.add_host(module) module:log("error", "Invalid route in %s, %q. See http://prosody.im/doc/developers/http#routes", app_name, key); end end + local services = portmanager.get_active_services(); + if services:get("https") or services:get("http") then + module:log("debug", "Serving '%s' at %s", app_name, module:http_url(app_name, app_path)); + else + module:log("warn", "Not listening on any ports, '%s' will be unreachable", app_name); + end end local function http_app_removed(event) -- cgit v1.2.3 From 5efd433b8a988f866962f01e674ad7ef5a187668 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Mar 2015 18:45:02 +0100 Subject: mod_http: Return a static string from module:http_url() when no ports are enabled and log a warning --- plugins/mod_http.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua index 9ff3af74..9b574bc8 100644 --- a/plugins/mod_http.lua +++ b/plugins/mod_http.lua @@ -69,6 +69,8 @@ function moduleapi.http_url(module, app_name, default_path) return url_build(url); end end + module:log("warn", "No http ports enabled, can't generate an external URL"); + return "http://disabled.invalid/"; end function module.add_host(module) -- cgit v1.2.3 From 63789fc738797696e93eab90e78468f9f7670411 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 24 Mar 2015 15:57:46 +0000 Subject: sessionmanager: Return 'not-allowed' error instead of the non-existent 'already-bound' error when client tries to bind a resource twice on the same stream (thanks Flow) fixes issue #484. --- core/sessionmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 98ead07f..4b014d18 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -113,7 +113,7 @@ end -- returns nil, err_type, err, err_message on failure function bind_resource(session, resource) if not session.username then return nil, "auth", "not-authorized", "Cannot bind resource before authentication"; end - if session.resource then return nil, "cancel", "already-bound", "Cannot bind multiple resources on a single connection"; end + if session.resource then return nil, "cancel", "not-allowed", "Cannot bind multiple resources on a single connection"; end -- We don't support binding multiple resources resource = resourceprep(resource); -- cgit v1.2.3 From bfbcd081de5ec6fcd65abfefc769d76a5264e82b Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 24 Mar 2015 16:03:37 +0000 Subject: mod_s2s: to/from attributes are required on s2s stream headers. Set them to '' when not available. Fixes #468. --- plugins/mod_s2s/mod_s2s.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index d8846a6f..f5297efe 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -512,7 +512,7 @@ function session_open_stream(session, from, to) version = session.version and (session.version > 0 and "1.0" or nil), ["xml:lang"] = 'en', id = session.streamid, - from = from, to = to, + from = from or "", to = to or "", } if not from or (hosts[from] and hosts[from].modules.dialback) then attr["xmlns:db"] = 'jabber:server:dialback'; -- cgit v1.2.3 -- cgit v1.2.3