util/x509.lua
author Jonas Schäfer <jonas@wielicki.name>
Mon, 10 Jan 2022 18:23:54 +0100
branch0.11
changeset 12185 783056b4e448
parent 8558 4f0f5b49bb03
child 9911 54e36a8677bc
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:
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     1
-- Prosody IM
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     2
-- Copyright (C) 2010 Matthew Wild
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     3
-- Copyright (C) 2010 Paul Aurich
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     4
--
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     5
-- This project is MIT/X11 licensed. Please see the
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     6
-- COPYING file in the source package for more information.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     7
--
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     8
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
     9
-- TODO: I feel a fair amount of this logic should be integrated into Luasec,
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    10
-- so that everyone isn't re-inventing the wheel.  Dependencies on
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    11
-- IDN libraries complicate that.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    12
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    13
4330
520fcb333cba util.x509: Update references to published RFCs
Paul Aurich <paul@darkrain42.org>
parents: 3735
diff changeset
    14
-- [TLS-CERTS] - http://tools.ietf.org/html/rfc6125
520fcb333cba util.x509: Update references to published RFCs
Paul Aurich <paul@darkrain42.org>
parents: 3735
diff changeset
    15
-- [XMPP-CORE] - http://tools.ietf.org/html/rfc6120
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    16
-- [SRV-ID]    - http://tools.ietf.org/html/rfc4985
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    17
-- [IDNA]      - http://tools.ietf.org/html/rfc5890
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    18
-- [LDAP]      - http://tools.ietf.org/html/rfc4519
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    19
-- [PKIX]      - http://tools.ietf.org/html/rfc5280
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    20
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    21
local nameprep = require "util.encodings".stringprep.nameprep;
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    22
local idna_to_ascii = require "util.encodings".idna.to_ascii;
6152
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
    23
local base64 = require "util.encodings".base64;
3735
40b54c46a14c util.x509: "certverification" -> "x509".
Waqas Hussain <waqas20@gmail.com>
parents: 3733
diff changeset
    24
local log = require "util.logger".init("x509");
4486
f04db5e7e90d user.x509: Add some utility functions for generating OpenSSL configs
Kim Alvefur <zash@zash.se>
parents: 4330
diff changeset
    25
local s_format = string.format;
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    26
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
    27
local _ENV = nil;
8558
4f0f5b49bb03 vairious: Add annotation when an empty environment is set [luacheck]
Kim Alvefur <zash@zash.se>
parents: 6780
diff changeset
    28
-- luacheck: std none
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    29
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    30
local oid_commonname = "2.5.4.3"; -- [LDAP] 2.3
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    31
local oid_subjectaltname = "2.5.29.17"; -- [PKIX] 4.2.1.6
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    32
local oid_xmppaddr = "1.3.6.1.5.5.7.8.5"; -- [XMPP-CORE]
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    33
local oid_dnssrv   = "1.3.6.1.5.5.7.8.7"; -- [SRV-ID]
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    34
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    35
-- Compare a hostname (possibly international) with asserted names
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    36
-- extracted from a certificate.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    37
-- This function follows the rules laid out in
4330
520fcb333cba util.x509: Update references to published RFCs
Paul Aurich <paul@darkrain42.org>
parents: 3735
diff changeset
    38
-- sections 6.4.1 and 6.4.2 of [TLS-CERTS]
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    39
--
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    40
-- A wildcard ("*") all by itself is allowed only as the left-most label
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    41
local function compare_dnsname(host, asserted_names)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    42
	-- TODO: Sufficient normalization?  Review relevant specs.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    43
	local norm_host = idna_to_ascii(host)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    44
	if norm_host == nil then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    45
		log("info", "Host %s failed IDNA ToASCII operation", host)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    46
		return false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    47
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    48
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    49
	norm_host = norm_host:lower()
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    50
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    51
	local host_chopped = norm_host:gsub("^[^.]+%.", "") -- everything after the first label
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    52
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    53
	for i=1,#asserted_names do
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    54
		local name = asserted_names[i]
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    55
		if norm_host == name:lower() then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    56
			log("debug", "Cert dNSName %s matched hostname", name);
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    57
			return true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    58
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    59
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    60
		-- Allow the left most label to be a "*"
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    61
		if name:match("^%*%.") then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    62
			local rest_name = name:gsub("^[^.]+%.", "")
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    63
			if host_chopped == rest_name:lower() then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    64
				log("debug", "Cert dNSName %s matched hostname", name);
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    65
				return true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    66
			end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    67
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    68
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    69
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    70
	return false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    71
end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    72
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    73
-- Compare an XMPP domain name with the asserted id-on-xmppAddr
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    74
-- identities extracted from a certificate.  Both are UTF8 strings.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    75
--
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    76
-- Per [XMPP-CORE], matches against asserted identities don't include
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    77
-- wildcards, so we just do a normalize on both and then a string comparison
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    78
--
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    79
-- TODO: Support for full JIDs?
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    80
local function compare_xmppaddr(host, asserted_names)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    81
	local norm_host = nameprep(host)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    82
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    83
	for i=1,#asserted_names do
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    84
		local name = asserted_names[i]
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    85
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    86
		-- We only want to match against bare domains right now, not
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    87
		-- those crazy full-er JIDs.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    88
		if name:match("[@/]") then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    89
			log("debug", "Ignoring xmppAddr %s because it's not a bare domain", name)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    90
		else
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    91
			local norm_name = nameprep(name)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    92
			if norm_name == nil then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    93
				log("info", "Ignoring xmppAddr %s, failed nameprep!", name)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    94
			else
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    95
				if norm_host == norm_name then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    96
					log("debug", "Cert xmppAddr %s matched hostname", name)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    97
					return true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    98
				end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
    99
			end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   100
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   101
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   102
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   103
	return false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   104
end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   105
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   106
-- Compare a host + service against the asserted id-on-dnsSRV (SRV-ID)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   107
-- identities extracted from a certificate.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   108
--
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   109
-- Per [SRV-ID], the asserted identities will be encoded in ASCII via ToASCII.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   110
-- Comparison is done case-insensitively, and a wildcard ("*") all by itself
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   111
-- is allowed only as the left-most non-service label.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   112
local function compare_srvname(host, service, asserted_names)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   113
	local norm_host = idna_to_ascii(host)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   114
	if norm_host == nil then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   115
		log("info", "Host %s failed IDNA ToASCII operation", host);
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   116
		return false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   117
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   118
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   119
	-- Service names start with a "_"
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   120
	if service:match("^_") == nil then service = "_"..service end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   121
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   122
	norm_host = norm_host:lower();
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   123
	local host_chopped = norm_host:gsub("^[^.]+%.", "") -- everything after the first label
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   124
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   125
	for i=1,#asserted_names do
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   126
		local asserted_service, name = asserted_names[i]:match("^(_[^.]+)%.(.*)");
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   127
		if service == asserted_service then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   128
			if norm_host == name:lower() then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   129
				log("debug", "Cert SRVName %s matched hostname", name);
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   130
				return true;
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   131
			end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   132
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   133
			-- Allow the left most label to be a "*"
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   134
			if name:match("^%*%.") then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   135
				local rest_name = name:gsub("^[^.]+%.", "")
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   136
				if host_chopped == rest_name:lower() then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   137
					log("debug", "Cert SRVName %s matched hostname", name)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   138
					return true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   139
				end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   140
			end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   141
			if norm_host == name:lower() then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   142
				log("debug", "Cert SRVName %s matched hostname", name);
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   143
				return true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   144
			end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   145
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   146
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   147
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   148
	return false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   149
end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   150
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   151
local function verify_identity(host, service, cert)
6711
d2beb98ece29 util.x509: Tell LuaSec we want UTF-8 data
Kim Alvefur <zash@zash.se>
parents: 6153
diff changeset
   152
	if cert.setencode then
d2beb98ece29 util.x509: Tell LuaSec we want UTF-8 data
Kim Alvefur <zash@zash.se>
parents: 6153
diff changeset
   153
		cert:setencode("utf8");
d2beb98ece29 util.x509: Tell LuaSec we want UTF-8 data
Kim Alvefur <zash@zash.se>
parents: 6153
diff changeset
   154
	end
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   155
	local ext = cert:extensions()
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   156
	if ext[oid_subjectaltname] then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   157
		local sans = ext[oid_subjectaltname];
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   158
4330
520fcb333cba util.x509: Update references to published RFCs
Paul Aurich <paul@darkrain42.org>
parents: 3735
diff changeset
   159
		-- Per [TLS-CERTS] 6.3, 6.4.4, "a client MUST NOT seek a match for a
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   160
		-- reference identifier if the presented identifiers include a DNS-ID
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   161
		-- SRV-ID, URI-ID, or any application-specific identifier types"
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   162
		local had_supported_altnames = false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   163
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   164
		if sans[oid_xmppaddr] then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   165
			had_supported_altnames = true
5845
c48f717c2fd6 util.x509: Only compare identity with oid-on-xmppAddr for XMPP services
Kim Alvefur <zash@zash.se>
parents: 4825
diff changeset
   166
			if service == "_xmpp-client" or service == "_xmpp-server" then
c48f717c2fd6 util.x509: Only compare identity with oid-on-xmppAddr for XMPP services
Kim Alvefur <zash@zash.se>
parents: 4825
diff changeset
   167
				if compare_xmppaddr(host, sans[oid_xmppaddr]) then return true end
c48f717c2fd6 util.x509: Only compare identity with oid-on-xmppAddr for XMPP services
Kim Alvefur <zash@zash.se>
parents: 4825
diff changeset
   168
			end
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   169
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   170
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   171
		if sans[oid_dnssrv] then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   172
			had_supported_altnames = true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   173
			-- Only check srvNames if the caller specified a service
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   174
			if service and compare_srvname(host, service, sans[oid_dnssrv]) then return true end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   175
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   176
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   177
		if sans["dNSName"] then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   178
			had_supported_altnames = true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   179
			if compare_dnsname(host, sans["dNSName"]) then return true end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   180
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   181
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   182
		-- We don't need URIs, but [TLS-CERTS] is clear.
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   183
		if sans["uniformResourceIdentifier"] then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   184
			had_supported_altnames = true
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   185
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   186
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   187
		if had_supported_altnames then return false end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   188
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   189
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   190
	-- Extract a common name from the certificate, and check it as if it were
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   191
	-- a dNSName subjectAltName (wildcards may apply for, and receive,
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   192
	-- cat treats)
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   193
	--
4330
520fcb333cba util.x509: Update references to published RFCs
Paul Aurich <paul@darkrain42.org>
parents: 3735
diff changeset
   194
	-- Per [TLS-CERTS] 1.8, a CN-ID is the Common Name from a cert subject
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   195
	-- which has one and only one Common Name
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   196
	local subject = cert:subject()
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   197
	local cn = nil
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   198
	for i=1,#subject do
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   199
		local dn = subject[i]
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   200
		if dn["oid"] == oid_commonname then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   201
			if cn then
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   202
				log("info", "Certificate has multiple common names")
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   203
				return false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   204
			end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   205
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   206
			cn = dn["value"];
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   207
		end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   208
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   209
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   210
	if cn then
4330
520fcb333cba util.x509: Update references to published RFCs
Paul Aurich <paul@darkrain42.org>
parents: 3735
diff changeset
   211
		-- Per [TLS-CERTS] 6.4.4, follow the comparison rules for dNSName SANs.
3651
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   212
		return compare_dnsname(host, { cn })
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   213
	end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   214
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   215
	-- If all else fails, well, why should we be any different?
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   216
	return false
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   217
end
337391d34b70 s2s: SASL EXTERNAL
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
   218
6152
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   219
local pat = "%-%-%-%-%-BEGIN ([A-Z ]+)%-%-%-%-%-\r?\n"..
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   220
"([0-9A-Za-z+/=\r\n]*)\r?\n%-%-%-%-%-END %1%-%-%-%-%-";
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   221
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   222
local function pem2der(pem)
6152
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   223
	local typ, data = pem:match(pat);
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   224
	if typ and data then
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   225
		return base64.decode(data), typ;
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   226
	end
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   227
end
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   228
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   229
local wrap = ('.'):rep(64);
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   230
local envelope = "-----BEGIN %s-----\n%s\n-----END %s-----\n"
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   231
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   232
local function der2pem(data, typ)
6152
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   233
	typ = typ and typ:upper() or "CERTIFICATE";
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   234
	data = base64.encode(data);
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   235
	return s_format(envelope, typ, data:gsub(wrap, '%0\n', (#data-1)/64), typ);
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   236
end
fbab74c28e31 util.x509: And functions for converting between DER and PEM
Kim Alvefur <zash@zash.se>
parents: 5845
diff changeset
   237
6780
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   238
return {
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   239
	verify_identity = verify_identity;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   240
	pem2der = pem2der;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   241
	der2pem = der2pem;
5de6b93d0190 util.*: Remove use of module() function, make all module functions local and return them in a table at the end
Kim Alvefur <zash@zash.se>
parents: 6711
diff changeset
   242
};