mod_auth_ccert/mod_auth_ccert.lua
author Kim Alvefur <zash@zash.se>
Fri, 14 Jun 2013 20:28:23 +0200
changeset 1069 d7719bf1aed6
parent 1068 8ad0d234608c
child 1070 dee31eeae7ae
permissions -rw-r--r--
mod_auth_ccert: Add missing OID for email
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1062
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
-- Copyright (C) 2013 Kim Alvefur
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
--
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     3
-- This file is MIT/X11 licensed.
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     5
local jid_compare = require "util.jid".compare;
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     6
local jid_split = require "util.jid".prepped_split;
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     7
local new_sasl = require "util.sasl".new;
1069
d7719bf1aed6 mod_auth_ccert: Add missing OID for email
Kim Alvefur <zash@zash.se>
parents: 1068
diff changeset
     8
local now = os.time;
1062
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
local log = module._log;
1069
d7719bf1aed6 mod_auth_ccert: Add missing OID for email
Kim Alvefur <zash@zash.se>
parents: 1068
diff changeset
    10
1062
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    11
local subject_alternative_name = "2.5.29.17";
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    12
local id_on_xmppAddr = "1.3.6.1.5.5.7.8.5";
1069
d7719bf1aed6 mod_auth_ccert: Add missing OID for email
Kim Alvefur <zash@zash.se>
parents: 1068
diff changeset
    13
local oid_emailAddress = "1.2.840.113549.1.9.1";
1062
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    14
1065
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    15
local cert_match = module:get_option("certificate_match", "xmppaddr");
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    16
1068
8ad0d234608c mod_auth_ccert: Pass the session username-outfigurer function too
Kim Alvefur <zash@zash.se>
parents: 1067
diff changeset
    17
local username_extractor = {};
1065
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    18
1068
8ad0d234608c mod_auth_ccert: Pass the session username-outfigurer function too
Kim Alvefur <zash@zash.se>
parents: 1067
diff changeset
    19
function username_extractor.xmppaddr(cert, authz, session)
1065
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    20
	local extensions = cert:extensions();
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    21
	local SANs = extensions[subject_alternative_name];
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    22
	local xmppAddrs = SANs and SANs[id_on_xmppAddr];
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    23
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    24
	if not xmppAddrs then
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    25
		(session.log or log)("warn", "Client certificate contains no xmppAddrs");
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    26
		return nil, false;
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    27
	end
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    28
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    29
	for i=1,#xmppAddrs do
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    30
		if authz == "" or jid_compare(authz, xmppAddrs[i]) then
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    31
			(session.log or log)("debug", "xmppAddrs[%d] %q matches authz %q", i, xmppAddrs[i], authz)
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    32
			local username, host = jid_split(xmppAddrs[i]);
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    33
			if host == module.host then
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    34
				return username, true
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    35
			end
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    36
		end
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    37
	end
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    38
end
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    39
1066
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    40
function username_extractor.email(cert)
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    41
	local subject = cert:subject();
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    42
	for i=1,#subject do
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    43
		local ava = subject[i];
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    44
		if ava.oid == oid_emailAddress then
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    45
			local username, host = jid_split(ava.value);
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    46
			if host == module.host then
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    47
				return username, true
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    48
			end
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    49
		end
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    50
	end
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    51
end
83175a6af8c5 mod_auth_ccert: Add optional method for certificates which contain an email address
Kim Alvefur <zash@zash.se>
parents: 1065
diff changeset
    52
1065
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    53
local find_username = username_extractor[cert_match];
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    54
if not find_username then
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    55
	module:log("error", "certificate_match = %q is not supported");
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    56
	return
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    57
end
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    58
3d04d9377a67 mod_auth_ccert: Prepare for supporting more ways to figure out the username
Kim Alvefur <zash@zash.se>
parents: 1063
diff changeset
    59
1062
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    60
function get_sasl_handler(session)
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    61
	return new_sasl(module.host, {
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    62
		external = session.secure and function(authz)
1063
b2a4679e7d20 mod_auth_ccert: Accidentally not
Kim Alvefur <zash@zash.se>
parents: 1062
diff changeset
    63
			if not session.secure then
1062
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    64
				-- getpeercertificate() on a TCP connection would be bad, abort!
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    65
				(session.log or log)("error", "How did you manage to select EXTERNAL without TLS?");
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    66
				return nil, false;
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    67
			end
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    68
			local sock = session.conn:socket();
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    69
			local cert = sock:getpeercertificate();
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    70
			if not cert then
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    71
				(session.log or log)("warn", "No certificate provided");
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    72
				return nil, false;
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    73
			end
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    74
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    75
			if not cert:validat(now()) then
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    76
				(session.log or log)("warn", "Client certificate expired")
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    77
				return nil, "expired";
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    78
			end
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    79
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    80
			local chain_valid, chain_errors = sock:getpeerverification();
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    81
			if not chain_valid then
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    82
				(session.log or log)("warn", "Invalid client certificate chain");
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    83
				for i, error in ipairs(chain_errors) do
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    84
					(session.log or log)("warn", "%d: %s", i, table.concat(chain_errors, ", "));
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    85
				end
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    86
				return nil, false;
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    87
			end
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    88
1068
8ad0d234608c mod_auth_ccert: Pass the session username-outfigurer function too
Kim Alvefur <zash@zash.se>
parents: 1067
diff changeset
    89
			return find_username(cert, authz, session);
1062
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    90
		end
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    91
	});
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    92
end
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    93
f853a1a3aa15 mod_auth_ccert: Initial commit of authentication module for using CA-issued client certificates
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    94
module:provides "auth";