diff util/jid.lua @ 13949:863dd118f8e8 13.0

util.jid: Validate domainparts using IDNA or as IP literals (fixes #1903) RFC 7622 defines the domainpart as: > domainpart = IP-literal / IPv4address / ifqdn Nameprep allows a number of characters that are not legal in DNS names, such as U+20 " ", colon, slash, brackets, parenthesis. Notably an IPv6 literal domainpart has the form "[db8::abc:123]", but the brackets are not valid in IDNA, hence the separate checks for this. Also see #1967
author Kim Alvefur <zash@zash.se>
date Sat, 20 Sep 2025 17:46:46 +0200
parents d10957394a3c
children 27e97e5b2c16
line wrap: on
line diff
--- a/util/jid.lua	Tue Sep 09 00:39:41 2025 +0100
+++ b/util/jid.lua	Sat Sep 20 17:46:46 2025 +0200
@@ -13,6 +13,8 @@
 local nodeprep = require "prosody.util.encodings".stringprep.nodeprep;
 local nameprep = require "prosody.util.encodings".stringprep.nameprep;
 local resourceprep = require "prosody.util.encodings".stringprep.resourceprep;
+local idna_to_ascii = require "prosody.util.encodings".idna.to_ascii;
+local net = require "prosody.util.net";
 
 local escapes = {
 	[" "] = "\\20"; ['"'] = "\\22";
@@ -48,6 +50,11 @@
 	return host;
 end
 
+local function valid_ip(ip)
+	local v6 = match(ip, "^%[([%x:.]+)%]$");
+	return net.pton(v6 or ip);
+end
+
 local function prepped_split(jid, strict)
 	local node, host, resource = split(jid);
 	if host ~= nil and host ~= "." then
@@ -56,6 +63,7 @@
 		end
 		host = nameprep(host, strict);
 		if host == nil then return; end
+		if not (valid_ip(host) or idna_to_ascii(host)) then return; end
 		if node ~= nil then
 			node = nodeprep(node, strict);
 			if node == nil then return; end