From e005643002aac881d157e48ea62d1a40230a54b5 Mon Sep 17 00:00:00 2001 From: "Franc[e]sco" Date: Thu, 4 Jun 2020 18:29:04 +0200 Subject: [PATCH] Add SASL EXTERNAL authentication and example --- example/externalSasl.js | 62 +++++++++++++++++++++++++++++++++++++++++ lib/irc.js | 24 +++++++++++----- 2 files changed, 79 insertions(+), 7 deletions(-) create mode 100755 example/externalSasl.js diff --git a/example/externalSasl.js b/example/externalSasl.js new file mode 100755 index 00000000..8542aaa5 --- /dev/null +++ b/example/externalSasl.js @@ -0,0 +1,62 @@ +#!/usr/bin/env node + +var irc = require('../'); +var fs = require('fs'); + +// example of authenticating through external sasl on freenode +// set up your cert as instructed here https://freenode.net/kb/answer/certfp +// change these to your cert +var options = { + key: fs.readFileSync('/path/to/.weechat/certs/freenode.pem'), + cert: fs.readFileSync('/path/to/.weechat/certs/freenode.pem') +}; + +var bot = new irc.Client('chat.freenode.net', 'nodebot', { + port: 6697, + sasl: true, + saslType: 'EXTERNAL', + debug: true, + secure: options, + channels: ['#botwar'] +}); + +bot.addListener('error', function(message) { + console.error('ERROR: %s: %s', message.command, message.args.join(' ')); +}); + +bot.addListener('message#blah', function(from, message) { + console.log('<%s> %s', from, message); +}); + +bot.addListener('message', function(from, to, message) { + console.log('%s => %s: %s', from, to, message); + + if (to.match(/^[#&]/)) { + // channel message + if (message.match(/hello/i)) { + bot.say(to, 'Hello there ' + from); + } + if (message.match(/dance/)) { + setTimeout(function() { bot.say(to, '\u0001ACTION dances: :D\\-<\u0001'); }, 1000); + setTimeout(function() { bot.say(to, '\u0001ACTION dances: :D|-<\u0001'); }, 2000); + setTimeout(function() { bot.say(to, '\u0001ACTION dances: :D/-<\u0001'); }, 3000); + setTimeout(function() { bot.say(to, '\u0001ACTION dances: :D|-<\u0001'); }, 4000); + } + } + else { + // private message + console.log('private message'); + } +}); +bot.addListener('pm', function(nick, message) { + console.log('Got private message from %s: %s', nick, message); +}); +bot.addListener('join', function(channel, who) { + console.log('%s has joined %s', who, channel); +}); +bot.addListener('part', function(channel, who, reason) { + console.log('%s has left %s: %s', who, channel, reason); +}); +bot.addListener('kick', function(channel, who, by, reason) { + console.log('%s was kicked from %s by %s: %s', who, channel, by, reason); +}); diff --git a/lib/irc.js b/lib/irc.js index 08375ec5..353f18c2 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -64,6 +64,7 @@ function Client(server, nick, opt) { floodProtection: false, floodProtectionDelay: 1000, sasl: false, + saslType: 'PLAIN', stripColors: false, channelPrefixes: '&#', messageSplit: 512, @@ -661,15 +662,24 @@ function Client(server, nick, opt) { if (message.args[0] === '*' && message.args[1] === 'ACK' && message.args[2] === 'sasl ') // there's a space after sasl - self._send('AUTHENTICATE', 'PLAIN'); + self._send('AUTHENTICATE', self.opt.saslType); break; case 'AUTHENTICATE': - if (message.args[0] === '+') self._send('AUTHENTICATE', - Buffer.from( - self.opt.nick + '\0' + - self.opt.userName + '\0' + - self.opt.password - ).toString('base64')); + if (message.args[0] === '+') { + switch (self.opt.saslType) { + case 'PLAIN': + self._send('AUTHENTICATE', + Buffer.from( + self.opt.nick + '\0' + + self.opt.userName + '\0' + + self.opt.password + ).toString('base64')); + break; + case 'EXTERNAL': + self._send('AUTHENTICATE', '+'); + break; + } + } break; case '903': self._send('CAP', 'END');