Last active
June 28, 2023 16:51
-
-
Save donpdonp/75716e63d6fe5bab92c07c2fd77fecdd to your computer and use it in GitHub Desktop.
gluon tls ssl checks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
setup() | |
return {name:"tls"} | |
}) | |
var alert_channel = "#pdxbots" | |
var watchlist = {} | |
var key = "tls:watchlist" | |
function setup() { | |
scan("*", function(result){ | |
result = result.filter(function(i,idx){return idx % 2 == 0}) | |
bot.say(bot.admin_channel, "tls watchlist: "+JSON.stringify(result)) | |
}) | |
} | |
function go(msg) { | |
if (msg.method == "clocktower") { | |
var now = new Date(Date.parse(msg.params.time)) | |
if (now.getMinutes() == 0 && now.getHours() == 6) { | |
//bot.say(bot.admin_channel, "!tls check "+now) | |
scan("*", function(result){ | |
result.forEach(function(str, idx){ | |
if(idx % 2 == 0) { | |
var parts = str.split(':') | |
var nick = parts[0] | |
var domain = parts[1] | |
var hostinfo = tls_check(domain, bot.admin_channel) | |
var remaining_days = (hostinfo.expires_at - (new Date()))/1000/60/60/24 | |
if (remaining_days < 3) { | |
bot.say(alert_channel, nick+": "+domain+" cert expires in "+remaining_days.toFixed(1)+" days. (!tls)") | |
} | |
if (hostinfo.expired) { | |
bot.say(alert_channel, nick+": EXPIRED "+hostinfo.expired+" "+domain+" (!tls help)") | |
} | |
} | |
}) | |
}) | |
} | |
} | |
if (msg.method == "irc.privmsg") { | |
var cmd = /^!tls(\s+(\S+))?(\s+(.*))?/.exec(msg.params.message) | |
if(cmd) { | |
if(cmd[2]) { | |
if (cmd[2] == "add") { | |
bot.say(msg.params.channel, "watching: "+cmd[4]) | |
add_host(msg.params.nick, cmd[4]) | |
} else | |
if (cmd[2] == "del") { | |
bot.say(msg.params.channel, "unwatching: "+cmd[4]) | |
del_host(msg.params.nick, cmd[4]) | |
} else | |
if (cmd[2] == "check") { | |
nickscan(msg.params.nick, function(result){ | |
Object.keys(result).forEach(function(hostname){ | |
var hostinfo = tls_check(hostname, msg.params.channel) | |
bot.say(msg.params.channel, hostname+": "+hostwords(hostinfo)) | |
}) | |
}) | |
} else | |
if (cmd[2] == "list") { | |
nickscan(msg.params.nick, function(result){ | |
bot.say(msg.params.channel, msg.params.nick+": "+Object.keys(result).join(", ")) | |
}) | |
} else | |
if (cmd[2] == "help") { | |
say_help(msg.params.channel) | |
} else { | |
var hostinfo = tls_check(cmd[2], msg.params.channel) | |
bot.say(msg.params.channel, cmd[2]+": "+hostwords(hostinfo)) | |
} | |
} else { | |
say_help(msg.params.channel) | |
} | |
} | |
} | |
} | |
function say_help(channel) { | |
bot.say(channel, "!tls [<domainname> | check | list | add <domainname> | del <domainname> ]") | |
} | |
function hostwords(hostinfo) { | |
var msg | |
if (hostinfo.expired) { | |
msg = "EXPIRED "+hostinfo.expired | |
} else if (hostinfo.error) { | |
msg = hostinfo.error.message | |
} else { | |
msg = hostinfo.tls_version+" "+ certFormat(hostinfo) | |
} | |
return msg | |
} | |
function tls_check(host, channel) { | |
var data = http.get({url:"https://"+host}) | |
delete data.body // todo: http.head | |
var response = {} | |
if(data.error) { | |
if (data.error.message.indexOf('expired') >= 0) { | |
response.expired = data.error.message.slice(-20) | |
} else { | |
response.error = data.error | |
} | |
} | |
// {"tls":{"peer_certs":[{"dns_names":["*.donp.org","donp.org"],"not_after":"2023-07-30T09:00:30Z","not_before":"2023-05-01T09:00:31Z"}, | |
if (data.tls) { | |
if(data.tls.version == 0x0304) { response.tls_version = "tls1.3" } | |
if(data.tls.version == 0x0303) { response.tls_version = "tls1.2" } | |
if(data.tls.version == 0x0302) { response.tls_version = "tls1.1" } | |
if (data.tls.peer_certs) { | |
if (data.tls.peer_certs.length > 0) { | |
var cert = data.tls.peer_certs[0] | |
response.expires_at = new Date(cert.not_after) | |
response.dns_names = cert.dns_names | |
} | |
} else { | |
bot.say(bot.admin_channel, "warning: no tls.peer_certs for "+host) | |
bot.say(bot.admin_channel, JSON.stringify(data)) | |
} | |
} | |
return response | |
} | |
function certFormat(cert) { | |
var dns_names = JSON.stringify(cert.dns_names) | |
var now = new Date() | |
var expired = now > cert.expires_at | |
var remaining_days = (cert.expires_at - now)/1000/60/60/24 | |
var exp_date_str = [cert.expires_at.getFullYear(), cert.expires_at.getMonth()+1, cert.expires_at.getDate() ].join('-') | |
return [(expired ? "EXPIRED " : "expires ")+exp_date_str, | |
remaining_days.toFixed(1)+" days", "dns_names "+dns_names ].join(' ') | |
} | |
function add_host(nick, hostname) { | |
var dbkey = [key, nick, hostname].join(':') | |
db.set(dbkey, "{}", function(){ | |
}) | |
} | |
function del_host(nick, hostname) { | |
var dbkey = [key, nick, hostname].join(':') | |
db.del(dbkey) | |
} | |
function load_host(nick, hostname, cb) { | |
var dbkey = [key, nick, hostname].join(':') | |
db.get(dbkey, cb) | |
} | |
function nickscan(nick, cb) { | |
scan(nick+":*", function(result){ | |
var hosts = {} | |
result.forEach(function(r,idx){ | |
if (idx % 2 == 0) { | |
hosts[r.substr(nick.length+1)] = result[idx+1] | |
} | |
}) | |
cb(hosts) | |
}) | |
} | |
function scan(match, cb, cursor, answers, loop) { | |
if(cursor == null) { cursor = 0; answers = []; loop = 1 } | |
loop = loop + 1 | |
db.scan(cursor, key+':'+match, 100, function(result){ | |
cursor = result[0] | |
answers = answers.concat(result[1]) | |
var count = answers.length/2 | |
if(cursor == 0) { | |
var short_answers = answers.map(function(a, idx){ | |
if(idx % 2 == 0) { | |
return a.substr(key.length+1) | |
} else { | |
return JSON.parse(a) | |
} | |
}) | |
cb(short_answers) | |
} else { | |
if(loop < 1500) { | |
scan(match, cb, cursor, answers, loop) | |
} else { | |
cb({error: "tls scan overload. stopping."}) | |
} | |
} | |
}) | |
} | |
function inspect(x) { | |
return (typeof x)+" "+JSON.stringify(x) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment