Rough outline of an irssi znc auto-opt plugin
I wrote a quick irssi plugin that lets me run a few irssi sessions in tmux on various cloud hosts that op each other using the auto-op protocol made popular by the znc bouncer. I can tmux in and start chatting as any of them.
ZNC Auto-op Protocol
The ZNC auto-op protocol is a sequence of IRC notices.
bot: !ZNCAO CHALLENGE uOceZDNtXOv36VJXc5Dt0Ji9NiZxX0Tz
you: !ZNCAO RESPONSE 51f34b12e2f2a5678a173a97f73fc5dc
The bot has two things in common with you: a secret, and an emphemeral 32-char challenge it sends everytime it sees you. The response is an md5sum of the secret, ::, and the challenge.
Demo Code
The following is very rough code pruned for shortness, and does not work. It has a lot of detail that took me a while to figure out.
We need an md5 function, and depend on a function (not provided here) to generate random strings of a certain length (generaterandomstring int).
use strict;
use Digest::MD5 qw(md5_hex);
There are two signal handlers for channel joins and notices.
Issuing a challenge
When a nick joins the channel and can be mapped to a shared secret, issue a challenge:
sub message_join {
my ($server, $channel, $nick, $address) = @_;
my ($challenge) = generate_random_string(32);
$server->command("NOTICE $nick !ZNCAO CHALLENGE $challenge");
}
Handling a response
If the bot gets a notice, it could be a response or a challenge.
sub event_notice {
my ($server, $msg, $nick, $address, $target) = @_;
For a response, calculate the expected response by taking the md5 of the concatenation of shared password, ::, and the challenge sent.
my ($to,$response) = $msg =~ m{^(\S+)\s+:\s*!ZNCAO\s+RESPONSE\s+(.+)$};
my ($expected_response) = md5_hex($password . "::" . $challenge);
if ($response eq $expected_response) {
# op them
}
Oh, ho! We are challenged
For a challenge, respond using the same formula processing a response and send a notice.
my ($to,$challenge) = $msg =~ m{^(\S+)\s+:\s*!ZNCAO\s+CHALLENGE\s+(.+)$};
my ($response) = md5_hex($password . "::" . $challenge);
$server->command("NOTICE $nick !ZNCAO RESPONSE $response");
Signal Registration
Register the two signals for notices and channel joins.
Irssi::signal_add("event notice", "event_notice");
Irssi::signal_add("message join", "message_join");