mod_checkcerts/mod_checkcerts.lua
author Matthew Wild <mwild1@gmail.com>
Thu, 28 Jan 2021 07:04:11 +0000
changeset 4413 44f6537f6427
parent 2949 ec7f9c8f2a5f
child 4611 c8ccaac78f64
permissions -rw-r--r--
mod_invites_adhoc: Fail contact invite if user is not on current host Only the username was being used, and the host of the requester ignored. Luckily this only affects admins of the host. If they want to create an account they can use the other command. If they want to create a contact they should request from their account on this host.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2949
ec7f9c8f2a5f mod_checkcerts: Fixed luacheck warnings
Michel Le Bihan <michel@lebihan.pl>
parents: 1884
diff changeset
     1
local config = require "core.configmanager";
667
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
local ssl = require"ssl";
1098
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
     3
local datetime_parse = require"util.datetime".parse;
1676
d9fcf9d8e787 mod_checkcerts: Fix for removal of globals in LuaSec
Kim Alvefur <zash@zash.se>
parents: 1098
diff changeset
     4
local load_cert = ssl.loadcertificate;
941
a6c2345bcf87 mod_checkcerts: Nag admins about certs that have, or are about to expire. Often.
Kim Alvefur <zash@zash.se>
parents: 855
diff changeset
     5
local st = require"util.stanza"
855
1983d4d51e1a mod_checkcerts: Improve, add comments, add forward compatibility.
Kim Alvefur <zash@zash.se>
parents: 667
diff changeset
     6
1098
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
     7
-- These are in days.
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
     8
local nag_time = module:get_option_number("checkcerts_notify", 7) * 86400;
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
     9
855
1983d4d51e1a mod_checkcerts: Improve, add comments, add forward compatibility.
Kim Alvefur <zash@zash.se>
parents: 667
diff changeset
    10
if not load_cert then
1983d4d51e1a mod_checkcerts: Improve, add comments, add forward compatibility.
Kim Alvefur <zash@zash.se>
parents: 667
diff changeset
    11
	module:log("error", "This version of LuaSec (%s) does not support certificate checking", ssl._VERSION);
667
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    12
	return
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    13
end
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    14
1098
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    15
local pat = "^([JFMAONSD][ceupao][glptbvyncr])  ?(%d%d?) (%d%d):(%d%d):(%d%d) (%d%d%d%d) GMT$";
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    16
local months = {Jan=1,Feb=2,Mar=3,Apr=4,May=5,Jun=6,Jul=7,Aug=8,Sep=9,Oct=10,Nov=11,Dec=12};
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    17
local function parse_x509_datetime(s)
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    18
	local month, day, hour, min, sec, year = s:match(pat); month = months[month];
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    19
	return datetime_parse(("%04d-%02d-%02dT%02d:%02d:%02dZ"):format(year, month, day, hour, min, sec));
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    20
end
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    21
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    22
local timeunits = {"minute",60,"hour",3600,"day",86400,"week",604800,"month",2629746,"year",31556952,};
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    23
local function humantime(timediff)
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    24
	local ret = {};
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    25
	for i=#timeunits,2,-2 do
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    26
		if timeunits[i] < timediff then
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    27
			local n = math.floor(timediff / timeunits[i]);
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    28
			if n > 0 and #ret < 2 then
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    29
				ret[#ret+1] = ("%d %s%s"):format(n, timeunits[i-1], n ~= 1 and "s" or "");
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    30
				timediff = timediff - n*timeunits[i];
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    31
			end
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    32
		end
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    33
	end
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    34
	return table.concat(ret, " and ")
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    35
end
941
a6c2345bcf87 mod_checkcerts: Nag admins about certs that have, or are about to expire. Often.
Kim Alvefur <zash@zash.se>
parents: 855
diff changeset
    36
667
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    37
local function check_certs_validity()
941
a6c2345bcf87 mod_checkcerts: Nag admins about certs that have, or are about to expire. Often.
Kim Alvefur <zash@zash.se>
parents: 855
diff changeset
    38
	local now = os.time();
a6c2345bcf87 mod_checkcerts: Nag admins about certs that have, or are about to expire. Often.
Kim Alvefur <zash@zash.se>
parents: 855
diff changeset
    39
855
1983d4d51e1a mod_checkcerts: Improve, add comments, add forward compatibility.
Kim Alvefur <zash@zash.se>
parents: 667
diff changeset
    40
	-- First, let's find out what certificate this host uses.
1098
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    41
	local ssl_config = config.rawget(module.host, "ssl");
1883
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    42
	if not ssl_config or not ssl_config.certificate then
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    43
		ssl_config = config.get(module.host:match("%.(.*)"), "ssl");
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    44
	end
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    45
	if not ssl_config or not ssl_config.certificate then
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    46
		ssl_config = config.get("*", "ssl");
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    47
	end
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    48
	if not ssl_config or not ssl_config.certificate then
2949
ec7f9c8f2a5f mod_checkcerts: Fixed luacheck warnings
Michel Le Bihan <michel@lebihan.pl>
parents: 1884
diff changeset
    49
		module:log("warn", "Could not find a certificate to check");
1883
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    50
		return;
667
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    51
	end
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    52
1883
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    53
	local certfile = ssl_config.certificate;
1884
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    54
	local fh, ferr = io.open(certfile); -- Load the file.
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    55
	if not fh then
2949
ec7f9c8f2a5f mod_checkcerts: Fixed luacheck warnings
Michel Le Bihan <michel@lebihan.pl>
parents: 1884
diff changeset
    56
		module:log("warn", "Could not open certificate %s", ferr);
1884
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    57
		return;
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    58
	end
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    59
	local cert, lerr = load_cert(fh:read("*a")); -- And parse
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    60
	fh:close();
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    61
	if not cert then
2949
ec7f9c8f2a5f mod_checkcerts: Fixed luacheck warnings
Michel Le Bihan <michel@lebihan.pl>
parents: 1884
diff changeset
    62
		module:log("warn", "Could not parse certificate %s: %s", certfile, lerr or "");
1884
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    63
		return;
a7c1f1b6ef05 mod_checkcerts: Improve error handling when loading certificate
Kim Alvefur <zash@zash.se>
parents: 1883
diff changeset
    64
	end
855
1983d4d51e1a mod_checkcerts: Improve, add comments, add forward compatibility.
Kim Alvefur <zash@zash.se>
parents: 667
diff changeset
    65
1883
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    66
	local expires_at = parse_x509_datetime(cert:notafter());
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    67
	local expires_in = os.difftime(expires_at, now);
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    68
	local fmt =  "Certificate %s expires in %s"
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    69
	local nag_admin = expires_in < nag_time;
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    70
	local log_warn = expires_in < nag_time * 2;
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    71
	local timediff = expires_in;
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    72
	if expires_in < 0 then
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    73
		fmt =  "Certificate %s expired %s ago";
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    74
		timediff = -timediff;
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    75
	end
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    76
	timediff = humantime(timediff);
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    77
	module:log(log_warn and "warn" or "info", fmt, certfile, timediff);
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    78
	if nag_admin then
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    79
		local body = fmt:format("for host ".. module.host, timediff);
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    80
		for _,admin in ipairs(module:get_option_array("admins", {})) do
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    81
			module:send(st.message({ from = module.host, to = admin, type = "chat" }, body));
1098
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    82
		end
667
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    83
	end
1883
18123e0f5d58 mod_checkcerts: Improve logic for finding an ssl section with a certificate
Kim Alvefur <zash@zash.se>
parents: 1676
diff changeset
    84
	return math.max(86400, expires_in / 3);
667
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    85
end
ea9941812721 mod_checkcerts: New module that logs a warning when your cert is about to expire.
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    86
1098
cbbeac61f1ab mod_checkcerts: Add timestamp parsing, format time until expiry more human-readable, adjust check intervals to time left.
Kim Alvefur <zash@zash.se>
parents: 943
diff changeset
    87
module:add_timer(1, check_certs_validity);