From 4b1c467826eeb6d493e714ef0dd0c5716bf51ebe Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 19 Feb 2016 22:04:20 -0600 Subject: [PATCH 1/3] auth: Use ClientManager.findClient to simplify auth logic By adding an optional "token" parameter to the findClient method, we can simplify the logic of the auth function. Signed-off-by: Andy Doan --- src/clientManager.js | 4 +++- src/server.js | 30 +++++++++++------------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/clientManager.js b/src/clientManager.js index 624dd9d7..29358a3a 100644 --- a/src/clientManager.js +++ b/src/clientManager.js @@ -10,11 +10,13 @@ function ClientManager() { this.clients = []; } -ClientManager.prototype.findClient = function(name) { +ClientManager.prototype.findClient = function(name, token) { for (var i in this.clients) { var client = this.clients[i]; if (client.name === name) { return client; + } else if (token && token === client.token ) { + return client; } } return false; diff --git a/src/server.js b/src/server.js index 5beb6707..153d00ea 100644 --- a/src/server.js +++ b/src/server.js @@ -141,27 +141,19 @@ function auth(data) { }); init(socket, client); } else { - var success = false; - _.each(manager.clients, function(client) { - if (data.token) { - if (data.token === client.token) { - success = true; - } - } else if (client.config.user === data.user) { - if (bcrypt.compareSync(data.password || "", client.config.password)) { - success = true; - } - } - if (success) { - var token; - if (data.remember || data.token) { - token = client.token; - } + var client = manager.findClient(data.user, data.token); + var token; + if (data.remember || data.token) { + token = client.token; + } + if (client) { + if (bcrypt.compareSync(data.password || "", client.config.password)) { init(socket, client, token); - return false; + } else { + socket.emit("auth"); } - }); - if (!success) { + } + else { socket.emit("auth"); } } From 102cdc23f98a5980e7d7eeadf6f0a83dae9ccdf9 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 19 Feb 2016 22:14:29 -0600 Subject: [PATCH 2/3] auth: break out local authentication logic into its own function This uses a callback mechanism to fit the needs of the upcoming LDAP authentication function. Signed-off-by: Andy Doan --- src/server.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/server.js b/src/server.js index 153d00ea..e3829313 100644 --- a/src/server.js +++ b/src/server.js @@ -130,6 +130,10 @@ function init(socket, client, token) { } } +function local_auth(client, user, password, callback) { + callback(bcrypt.compareSync(password || "", client.config.password)); +} + function auth(data) { var socket = this; if (config.public) { @@ -147,11 +151,13 @@ function auth(data) { token = client.token; } if (client) { - if (bcrypt.compareSync(data.password || "", client.config.password)) { - init(socket, client, token); - } else { - socket.emit("auth"); - } + local_auth(client, data.user, data.password, function(passed) { + if (passed) { + init(socket, client, token); + } else { + socket.emit("auth"); + } + }); } else { socket.emit("auth"); From ba38049062870a0cf643699e92cd1e9232affbb4 Mon Sep 17 00:00:00 2001 From: Andy Doan Date: Fri, 19 Feb 2016 22:34:14 -0600 Subject: [PATCH 3/3] auth: add LDAP login support This allows logins to authenticate against an LDAP server. If the user doesn't exist before hand they will be created dynamically. Signed-off-by: Andy Doan --- defaults/config.js | 50 +++++++++++++++++++++++++++++++++++++++ src/command-line/start.js | 2 +- src/server.js | 32 +++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/defaults/config.js b/defaults/config.js index 1a342d1a..f97b0b33 100644 --- a/defaults/config.js +++ b/defaults/config.js @@ -86,6 +86,56 @@ module.exports = { // displayNetwork: true, + // + // LDAP authentication settings (only available if public=false) + // @type object + // @default {} + ldap: { + // + // Enable LDAP user authentication + // + // @type boolean + // @default false + // + enabled: false, + + // + // LDAP server URL + // + // @type string + // + //url: "ldaps://example.com", + + // + // LDAP bind user + // + // @type string + // + //adminDn: "cn=user,ou=binders,dc=example,dc=com", + + // + // LDAP bind password + // + // @type string + // + //adminPassword: "superS3cr3t", + + // + // LDAP search base + // + // @type string + // + //searchBase: "ou=accounts,dc=example,dc=com", + + // + // LDAP search filter + // + // @type string + // @default "(uid={{username}})" + // + searchFilter: "(uid={{username}})" + }, + // // Log settings // diff --git a/src/command-line/start.js b/src/command-line/start.js index 676fccb1..b93a6e3b 100644 --- a/src/command-line/start.js +++ b/src/command-line/start.js @@ -20,7 +20,7 @@ program } else if (program.private) { mode = false; } - if (!mode && !users.length) { + if (!mode && !users.length && !config.ldap.enabled) { console.log(""); console.log("No users found!"); console.log("Create a new user with 'shout add '."); diff --git a/src/server.js b/src/server.js index e3829313..d307197c 100644 --- a/src/server.js +++ b/src/server.js @@ -6,6 +6,7 @@ var express = require("express"); var fs = require("fs"); var io = require("socket.io"); var Helper = require("./helper"); +var LdapAuth = require("ldapauth"); var config = {}; var sockets = null; @@ -134,6 +135,20 @@ function local_auth(client, user, password, callback) { callback(bcrypt.compareSync(password || "", client.config.password)); } +function ldap_auth(client, user, password, callback) { + ldap = new LdapAuth(config.ldap); + ldap.authenticate(user, password, function(err, ldap_user){ + if (!err && !client) { + // we've authenticated, but having no client means we + // have a valid LDAP user that doesn't exist locally. + if (!manager.addUser(user, null)) { + console.log("Unable to create new user", user); + } + } + callback(!err); + }); +} + function auth(data) { var socket = this; if (config.public) { @@ -147,12 +162,25 @@ function auth(data) { } else { var client = manager.findClient(data.user, data.token); var token; + var auth_func; if (data.remember || data.token) { token = client.token; } - if (client) { - local_auth(client, data.user, data.password, function(passed) { + + if (client || config.ldap.enabled) { + auth_func = ldap_auth; + } else if (client) { + auth_func = local_auth; + } + + if (auth_func) { + auth_func(client, data.user, data.password, function(passed) { if (passed) { + if (!client) { + //LDAP auth just created a user + manager.loadUser(data.user); + client = manager.findClient(data.user); + } init(socket, client, token); } else { socket.emit("auth");