aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/mod_console.lua103
1 files changed, 103 insertions, 0 deletions
diff --git a/plugins/mod_console.lua b/plugins/mod_console.lua
index 6c1c8fd9..1b106888 100644
--- a/plugins/mod_console.lua
+++ b/plugins/mod_console.lua
@@ -561,6 +561,109 @@ function def_env.s2s:show(match_jid)
return true, "Total: "..count_out.." outgoing, "..count_in.." incoming connections";
end
+local function print_subject(print, subject)
+ for _, entry in ipairs(subject) do
+ print(
+ (" %s: %q"):format(
+ entry.name or entry.oid,
+ entry.value:gsub("[\r\n%z%c]", " ")
+ )
+ );
+ end
+end
+
+function def_env.s2s:showcert(domain)
+ local ser = require "util.serialization".serialize;
+ local print = self.session.print;
+ local domain_sessions = set.new(array.collect(keys(incoming_s2s)))
+ /function(session) return session.from_host == domain; end;
+ for local_host in values(prosody.hosts) do
+ local s2sout = local_host.s2sout;
+ if s2sout and s2sout[domain] then
+ domain_sessions:add(s2sout[domain]);
+ end
+ end
+ local cert_set = {};
+ for session in domain_sessions do
+ local conn = session.conn;
+ conn = conn and conn:socket();
+ if not conn.getpeercertificate then
+ if conn.dohandshake then
+ error("This version of LuaSec does not support certificate viewing");
+ end
+ else
+ local cert = conn:getpeercertificate();
+ if cert then
+ local digest = cert:digest("sha1");
+ if not cert_set[digest] then
+ local chain_valid, chain_err = conn:getpeerchainvalid();
+ cert_set[digest] = {
+ {
+ from = session.from_host,
+ to = session.to_host,
+ direction = session.direction
+ };
+ chain_valid = chain_valid;
+ chain_err = chain_err;
+ cert = cert;
+ };
+ else
+ table.insert(cert_set[digest], {
+ from = session.from_host,
+ to = session.to_host,
+ direction = session.direction
+ });
+ end
+ end
+ end
+ end
+ local domain_certs = array.collect(values(cert_set));
+ -- Phew. We now have a array of unique certificates presented by domain.
+ local print = self.session.print;
+ local n_certs = #domain_certs;
+
+ if n_certs == 0 then
+ return "No certificates found for "..domain;
+ end
+
+ local function _capitalize_and_colon(byte)
+ return string.upper(byte)..":";
+ end
+ local function pretty_fingerprint(hash)
+ return hash:gsub("..", _capitalize_and_colon):sub(1, -2);
+ end
+
+ for cert_info in values(domain_certs) do
+ local cert = cert_info.cert;
+ print("---")
+ print("Fingerprint (SHA1): "..pretty_fingerprint(cert:digest("sha1")));
+ print("");
+ local n_streams = #cert_info;
+ print("Currently used on "..n_streams.." stream"..(n_streams==1 and "" or "s")..":");
+ for _, stream in ipairs(cert_info) do
+ if stream.direction == "incoming" then
+ print(" "..stream.to.." <- "..stream.from);
+ else
+ print(" "..stream.from.." -> "..stream.to);
+ end
+ end
+ print("");
+ local chain_valid, err = cert_info.chain_valid, cert_info.chain_err;
+ local valid_identity = cert_verify_identity(domain, "xmpp-server", cert);
+ print("Trusted certificate: "..(chain_valid and "Yes" or ("No ("..err..")")));
+ print("Issuer: ");
+ print_subject(print, cert:issuer());
+ print("");
+ print("Valid for "..domain..": "..(valid_identity and "Yes" or "No"));
+ print("Subject:");
+ print_subject(print, cert:subject());
+ end
+ print("---");
+ return ("Showing "..n_certs.." certificate"
+ ..(n_certs==1 and "" or "s")
+ .." presented by "..domain..".");
+end
+
function def_env.s2s:close(from, to)
local print, count = self.session.print, 0;