mirror of
https://github.com/brunoos/luasec.git
synced 2024-11-08 06:28:26 +01:00
Add ssl.checkhostname and conn:checkhostname
Convenient (and important!) methods that allow checking for hostnames against a (peer) certificate. Deals with wildcards and alternative names (via the dnsnames extension).
This commit is contained in:
parent
88fa9b8bc2
commit
cde151739e
@ -47,3 +47,13 @@ Alias for `cert.load`.
|
||||
|
||||
`ssl.wrap` wraps an existing luasocket socket into a luasec connection object.
|
||||
`cfg` is defined as for `ssl.newcontext`.
|
||||
|
||||
### ssl.checkhostname ###
|
||||
|
||||
valid = ssl.checkhostname(cert, hostname)
|
||||
|
||||
Check if the certificate is valid for the given hostname. Deals with wildcards
|
||||
and alternative names.
|
||||
|
||||
**NOTE**: It is crucial the hostname is checked to verify the certificate is
|
||||
not only valid, but belonging to the host connected to.
|
||||
|
@ -119,3 +119,10 @@ context associated with this `conn` object.
|
||||
|
||||
Returns luasec's current `want`, if the connection is dirty (see `conn:dirty`).
|
||||
This can either be `nothing`, `read`, `write` or `x509lookup`.
|
||||
|
||||
### conn:checkhostname ###
|
||||
|
||||
valid = conn:checkhostname(hostname)
|
||||
|
||||
Checks whether the certificate is valid for the given hostname. Helper for
|
||||
`ssl.checkhostname`, see `ssl.checkhostname` for more information.
|
||||
|
48
src/ssl.lua
48
src/ssl.lua
@ -159,10 +159,57 @@ local function info(ssl, field)
|
||||
return ( (next(info)) and info )
|
||||
end
|
||||
|
||||
--
|
||||
-- Verify host name against a common name
|
||||
--
|
||||
local function checkhostname_single(hostname, cn)
|
||||
if cn:match("^%*%.") then
|
||||
-- If it's a wildcard domain name, strip the first element of the hostname
|
||||
-- and the cn, then check neither are empty.
|
||||
hostname = hostname:match("%.(.+)$")
|
||||
cn = cn:match("%.(.+)$")
|
||||
if cn == "" or hostname == "" then return false end
|
||||
end
|
||||
return cn == hostname
|
||||
end
|
||||
|
||||
--
|
||||
-- Verify host name against certificate
|
||||
--
|
||||
local function checkhostname(cert, hostname)
|
||||
local subject, ext
|
||||
subject = cert:subject()
|
||||
for i, v in ipairs(subject) do
|
||||
if v.name == "commonName" then
|
||||
if checkhostname_single(hostname, v.value) then
|
||||
return true
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
-- If we got here, the cn doesn't match, check for the dNSName extension
|
||||
ext = (cert:extensions() or {})["2.5.29.17"]
|
||||
if not ext or not ext.dNSName then return false end
|
||||
for i, v in ipairs(ext.dNSName) do
|
||||
if checkhostname_single(hostname, v) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--
|
||||
-- Verify host name against peer certificate
|
||||
--
|
||||
local function checkhostname_ssl(ssl, hostname)
|
||||
return checkhostname(ssl:getpeercertificate(), hostname)
|
||||
end
|
||||
|
||||
--
|
||||
-- Set method for SSL connections.
|
||||
--
|
||||
core.setmethod("info", info)
|
||||
core.setmethod("checkhostname", checkhostname_ssl)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Export module
|
||||
@ -174,6 +221,7 @@ local _M = {
|
||||
loadcertificate = x509.load,
|
||||
newcontext = newcontext,
|
||||
wrap = wrap,
|
||||
checkhostname = checkhostname,
|
||||
}
|
||||
|
||||
return _M
|
||||
|
Loading…
Reference in New Issue
Block a user