From 9997aafec7f710e950463e2f6234217483142673 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sat, 17 Dec 2016 11:51:33 +0200 Subject: [PATCH] Rewrite identd server, combine with oidentd --- src/clientManager.js | 18 +++-- src/identd.js | 55 -------------- src/identification.js | 108 +++++++++++++++++++++++++++ src/oidentd.js | 49 ------------ src/plugins/irc-events/connection.js | 24 +++--- src/server.js | 48 +++++------- 6 files changed, 150 insertions(+), 152 deletions(-) delete mode 100644 src/identd.js create mode 100644 src/identification.js delete mode 100644 src/oidentd.js diff --git a/src/clientManager.js b/src/clientManager.js index fc681cd9..578972c3 100644 --- a/src/clientManager.js +++ b/src/clientManager.js @@ -5,18 +5,26 @@ var colors = require("colors/safe"); var fs = require("fs"); var Client = require("./client"); var Helper = require("./helper"); -var Oidentd = require("./oidentd"); module.exports = ClientManager; function ClientManager() { this.clients = []; - - if (typeof Helper.config.oidentd === "string") { - this.identHandler = new Oidentd(Helper.config.oidentd); - } } +ClientManager.prototype.init = function(identHandler, sockets) { + this.sockets = sockets; + this.identHandler = identHandler; + + if (!Helper.config.public) { + if ("autoload" in Helper.config) { + log.warn(`Autoloading users is now always enabled. Please remove the ${colors.yellow("autoload")} option from your configuration file.`); + } + + this.autoloadUsers(); + } +}; + ClientManager.prototype.findClient = function(name, token) { for (var i in this.clients) { var client = this.clients[i]; diff --git a/src/identd.js b/src/identd.js deleted file mode 100644 index e8928074..00000000 --- a/src/identd.js +++ /dev/null @@ -1,55 +0,0 @@ -"use strict"; - -var _ = require("lodash"); -var net = require("net"); - -var users = {}; -var enabled = false; - -module.exports.start = function(port) { - port = port || 113; - log.info("Starting identd server on port", port); - net.createServer(init).listen(port); - enabled = true; -}; - -module.exports.hook = function(stream, user) { - var socket = stream.socket || stream; - var ports = _.pick(socket, "localPort", "remotePort"); - var id = _.values(ports).join(", "); - - users[id] = user; - - socket.on("close", function() { - delete users[id]; - }); -}; - -module.exports.isEnabled = function() { - return enabled; -}; - -function init(socket) { - socket.on("data", function(data) { - respond(socket, data); - }); -} - -function respond(socket, data) { - var id = parse(data); - var response = id + " : "; - if (users[id]) { - response += "USERID : UNIX : " + users[id]; - } else { - response += "ERROR : NO-USER"; - } - response += "\r\n"; - socket.write(response); - socket.end(); -} - -function parse(data) { - data = data.toString(); - data = data.split(","); - return parseInt(data[0]) + ", " + parseInt(data[1]); -} diff --git a/src/identification.js b/src/identification.js new file mode 100644 index 00000000..a3386cb1 --- /dev/null +++ b/src/identification.js @@ -0,0 +1,108 @@ +"use strict"; + +const fs = require("fs"); +const net = require("net"); +const colors = require("colors/safe"); +const Helper = require("./helper"); + +class Identification { + constructor(startedCallback) { + this.connectionId = 0; + this.connections = new Map(); + + if (typeof Helper.config.oidentd === "string") { + this.oidentdFile = Helper.expandHome(Helper.config.oidentd); + log.info(`Oidentd file: ${colors.green(this.oidentdFile)}`); + + this.refresh(); + } + + if (Helper.config.identd.enable) { + if (this.oidentdFile) { + log.warn("Using both identd and oidentd at the same time, this is most likely not intended."); + } + + var server = net.createServer(this.serverConnection.bind(this)); + server.listen({ + port: Helper.config.identd.port || 113, + host: Helper.config.bind || Helper.config.host, + }, () => { + var address = server.address(); + log.info(`Identd server available on ${colors.green(address.address + ":" + address.port)}`); + + startedCallback(); + }); + } else { + startedCallback(); + } + } + + serverConnection(socket) { + socket.on("data", data => { + this.respondToIdent(socket, data); + socket.end(); + }); + } + + respondToIdent(socket, data) { + data = data.toString().split(","); + + const lport = parseInt(data[0]); + const fport = parseInt(data[1]); + + if (lport < 1 || fport < 1 || lport > 65535 || fport > 65535) { + return; + } + + for (var connection of this.connections.values()) { + if (connection.socket.remoteAddress === socket.remoteAddress + && connection.socket.remotePort === fport + && connection.socket.localPort === lport + && connection.socket.localAddress === socket.localAddress) { + return socket.write(`${lport}, ${fport} : USERID : UNIX : ${connection.user}\r\n`); + } + } + + socket.write(`${lport}, ${fport} : ERROR : NO-USER\r\n`); + } + + addSocket(socket, user) { + const id = ++this.connectionId; + + this.connections.set(id, {socket: socket, user: user}); + + if (this.oidentdFile) { + this.refresh(); + } + + return id; + } + + removeSocket(id) { + this.connections.delete(id); + + if (this.oidentdFile) { + this.refresh(); + } + } + + refresh() { + let file = "# Warning: file generated by The Lounge: changes will be overwritten!\n"; + + this.connections.forEach((connection) => { + file += "to " + connection.socket.remoteAddress + + " lport " + connection.socket.localPort + + " from " + connection.socket.localAddress + + " fport " + connection.socket.remotePort + + " { reply \"" + connection.user + "\" }\n"; + }); + + fs.writeFile(this.oidentdFile, file, {flag: "w+"}, function(err) { + if (err) { + log.error("Failed to update oidentd file!", err); + } + }); + } +} + +module.exports = Identification; diff --git a/src/oidentd.js b/src/oidentd.js deleted file mode 100644 index 541b9772..00000000 --- a/src/oidentd.js +++ /dev/null @@ -1,49 +0,0 @@ -"use strict"; - -const fs = require("fs"); -const Helper = require("./helper"); - -function OidentdFile(file) { - this.file = Helper.expandHome(file); - this.connectionId = 0; - this.connections = new Map(); - - this.refresh(); -} - -OidentdFile.prototype = { - addSocket: function(socket, user) { - const id = this.connectionId++; - - this.connections.set(id, {socket: socket, user: user}); - this.refresh(); - - return id; - }, - - removeSocket: function(id) { - this.connections.delete(id); - - this.refresh(); - }, - - refresh: function() { - let file = "# Warning: file generated by The Lounge: changes will be overwritten!\n"; - - this.connections.forEach((connection) => { - file += "to " + connection.socket.remoteAddress - + " lport " + connection.socket.localPort - + " from " + connection.socket.localAddress - + " fport " + connection.socket.remotePort - + " { reply \"" + connection.user + "\" }\n"; - }); - - fs.writeFile(this.file, file, {flag: "w+"}, function(err) { - if (err) { - log.error("Failed to update oidentd file!", err); - } - }); - }, -}; - -module.exports = OidentdFile; diff --git a/src/plugins/irc-events/connection.js b/src/plugins/irc-events/connection.js index 9da7d6e0..fb2fdb74 100644 --- a/src/plugins/irc-events/connection.js +++ b/src/plugins/irc-events/connection.js @@ -1,6 +1,5 @@ "use strict"; -var identd = require("../../identd"); var Msg = require("../../models/msg"); var Chan = require("../../models/chan"); var Helper = require("../../helper"); @@ -63,23 +62,18 @@ module.exports = function(irc, network) { }), true); }); - if (identd.isEnabled()) { - irc.on("raw socket connected", function(socket) { - identd.hook(socket, client.name || network.username); - }); - } + let identSocketId; - if (identHandler) { - let identSocketId; + irc.on("raw socket connected", function(socket) { + identSocketId = identHandler.addSocket(socket, client.name || network.username); + }); - irc.on("raw socket connected", function(socket) { - identSocketId = identHandler.addSocket(socket, client.name || network.username); - }); - - irc.on("socket close", function() { + irc.on("socket close", function() { + if (identSocketId > 0) { identHandler.removeSocket(identSocketId); - }); - } + identSocketId = 0; + } + }); if (Helper.config.debug.ircFramework) { irc.on("debug", function(message) { diff --git a/src/server.js b/src/server.js index 34217944..347214c4 100644 --- a/src/server.js +++ b/src/server.js @@ -11,12 +11,16 @@ var dns = require("dns"); var Helper = require("./helper"); var ldap = require("ldapjs"); var colors = require("colors/safe"); +const Identification = require("./identification"); +let identHandler = null; var manager = null; var authFunction = localAuth; module.exports = function() { - manager = new ClientManager(); + log.info(`The Lounge ${colors.green(Helper.getVersion())} \ +(node ${colors.green(process.versions.node)} on ${colors.green(process.platform)} ${process.arch})`); + log.info(`Configuration file: ${colors.green(Helper.CONFIG_PATH)}`); if (!fs.existsSync("client/js/bundle.js")) { log.error(`The client application was not built. Run ${colors.bold("NODE_ENV=production npm run build")} to resolve this.`); @@ -37,7 +41,7 @@ module.exports = function() { if (!config.https.enable) { server = require("http"); - server = server.createServer(app).listen(config.port, config.host); + server = server.createServer(app); } else { server = require("spdy"); const keyPath = Helper.expandHome(config.https.key); @@ -53,16 +57,18 @@ module.exports = function() { server = server.createServer({ key: fs.readFileSync(keyPath), cert: fs.readFileSync(certPath) - }, app).listen(config.port, config.host); + }, app); } - if (config.identd.enable) { - if (manager.identHandler) { - log.warn("Using both identd and oidentd at the same time!"); - } - - require("./identd").start(config.identd.port); - } + server.listen({ + port: config.port, + host: config.host, + }, () => { + const protocol = config.https.enable ? "https" : "http"; + var address = server.address(); + log.info(`Available on ${colors.green(protocol + "://" + address.address + ":" + address.port + "/")} \ +in ${config.public ? "public" : "private"} mode`); + }); if (!config.public && (config.ldap || {}).enable) { authFunction = ldapAuth; @@ -81,25 +87,11 @@ module.exports = function() { } }); - manager.sockets = sockets; + manager = new ClientManager(); - const protocol = config.https.enable ? "https" : "http"; - const host = config.host || "*"; - - log.info(`The Lounge ${colors.green(Helper.getVersion())} is now running \ -using node ${colors.green(process.versions.node)} on ${colors.green(process.platform)} (${process.arch})`); - log.info(`Configuration file: ${colors.green(Helper.CONFIG_PATH)}`); - log.info(`Available on ${colors.green(protocol + "://" + host + ":" + config.port + "/")} \ -in ${config.public ? "public" : "private"} mode`); - log.info("Press Ctrl-C to stop\n"); - - if (!config.public) { - if ("autoload" in config) { - log.warn(`Autoloading users is now always enabled. Please remove the ${colors.yellow("autoload")} option from your configuration file.`); - } - - manager.autoloadUsers(); - } + identHandler = new Identification(() => { + manager.init(identHandler, sockets); + }); }; function getClientIp(req) {