diff --git a/lib/agent/actions/alert/index.js b/lib/agent/actions/alert/index.js index 994d70116..e4b9a1dee 100644 --- a/lib/agent/actions/alert/index.js +++ b/lib/agent/actions/alert/index.js @@ -1,89 +1,90 @@ -/* eslint-disable linebreak-style */ // Prey Alert // Written by Tomas Pollak -const { join } = require('path'); -const common = require('../../common'); - -const { system } = common; -const flash = join(__dirname, process.platform, 'flash'); -const preyApp = join(__dirname, '..', '..', 'utils', 'Prey.app'); -const actionsApp = join(__dirname, '..', '..', 'utils', 'prey-actions.app'); -// eslint-disable-next-line import/order -const Emitter = require('events').EventEmitter; - -const isWin = process.platform === 'win32'; -const isMac = process.platform === 'darwin'; - -let child; -let emitter; -let app; -let binary; -const userInputStr = 'User input: '; - -// eslint-disable-next-line consistent-return -exports.start = (id, opts, cb) => { - let message = opts.message || opts.alert_message; - const { title } = opts; - const level = opts.level || 'info'; - let reply = opts.reply || opts.entry || opts.response; - - if (!message || message.toString().trim() === '') return cb(new Error('Message required')); +var join = require('path').join, + common = require('./../../common'), + system = common.system, + flash = join(__dirname, process.platform, 'flash'), + prey_app = join(__dirname, '..', '..', 'utils', 'Prey.app'), + actions_app = join(__dirname, '..', '..', 'utils', 'prey-actions.app'), + Emitter = require('events').EventEmitter, + is_win = process.platform == 'win32', + is_mac = process.platform == 'darwin'; + +var child, + emitter, + app, + binary, + user_input_str = 'User input: '; + +exports.start = function(id, opts, cb) { + var opts = opts || {}, + message = opts.message || opts.alert_message, + title = opts.title, + level = opts.level || 'info', + reply = opts.reply || opts.entry || opts.response; + + if (!message || message.toString().trim() == '') + return cb(new Error('Message required')); // remove newlines so the message can be completely displayed - message = message.toString().replace(/(\r\n|\n|\r)/gm, ' '); + message = message.toString().replace(/(\r\n|\n|\r)/gm," "); - let returned = 0; - let bin = flash; - let args = ['-l', level]; + var reply, + returned = 0, + bin = flash, + args = ['-l', level]; - if (reply) args = args.concat(['-e', 'Type here:']); + if (reply) + args = args.concat(['-e', 'Type here:']); - if (title && title.toString().trim() !== '') args = args.concat(['-t', title]); + if (title && title.toString().trim() != '') + args = args.concat(['-t', title]); - if (isWin) { + if (is_win) { args.push('-m', message); // in windows, the bin expects a -m message argument bin += '.exe'; - } else if (isMac) { + } else if (is_mac) { args.push(message); bin += '.py'; } else { args.push(message); - bin += ((system.python_version && system.python_version >= '3.0.0') ? '3.py' : '.py'); + bin += ((system.python_version && system.python_version >= "3.0.0") ? '3.py' : '.py'); } - if (isMac && common.os_release >= '10.14') { - app = preyApp; + if (is_mac && common.os_release >= '10.14') { + app = prey_app; binary = 'Prey'; if (common.os_release >= '11.0') { - app = actionsApp; + app = actions_app; binary = 'prey-actions'; } - - bin = join(app, 'Contents', 'MacOS', binary); + + bin = join(app, 'Contents', 'MacOS', binary); args = ['-alert', message]; } - const done = (err) => { - // eslint-disable-next-line no-plusplus + function done(err) { if (returned++) return; - if (emitter) emitter.emit('end', id, err, reply); + if (emitter) + emitter.emit('end', id, err, reply); emitter = null; - }; + } - // eslint-disable-next-line consistent-return - system.spawn_as_logged_user(bin, args, (err, alert) => { + system.spawn_as_logged_user(bin, args, function(err, alert) { if (err) return done(err); - alert.stdout.on('data', (chunk) => { - if (chunk.toString().match(userInputStr)) reply = chunk.toString().replace(userInputStr, '').trim(); + alert.stdout.on('data', function(chunk) { + if (chunk.toString().match(user_input_str)) { + reply = chunk.toString().replace(user_input_str, '').trim(); + } }); alert.on('error', done); - alert.once('exit', () => { + alert.once('exit', function() { child = null; done(); }); @@ -92,13 +93,14 @@ exports.start = (id, opts, cb) => { emitter = new Emitter(); cb(null, emitter); }); -}; -exports.stop = () => { +} + +exports.stop = function() { // if child is killed, the 'exit' event is triggered // and it will fire the emitter's end' event, marking // the action as stopped. if (child && !child.exitCode) { child.kill(); } -}; +} \ No newline at end of file diff --git a/lib/agent/actions/lock/index.js b/lib/agent/actions/lock/index.js index ff4f056d6..e3ecdc481 100644 --- a/lib/agent/actions/lock/index.js +++ b/lib/agent/actions/lock/index.js @@ -1,227 +1,232 @@ -/* eslint-disable linebreak-style */ -/// /////////////////////////////////////// +"use strict"; + +////////////////////////////////////////// // Prey JS Lock Module // (c) 2011 - Fork Ltd. // by Tomas Pollak - http://forkhq.com // GPLv3 Licensed -/// /////////////////////////////////////// - -const path = require('path'); - -const { join } = path; -const Emitter = require('events').EventEmitter; -const crypto = require('crypto'); -const { exec } = require('child_process'); -const os = require('os'); -const common = require('../../common'); - -const logger = common.logger.prefix('actions'); -const { system } = common; -const runAsUser = system.run_as_logged_user; -const osName = os.platform().replace('darwin', 'mac').replace('win32', 'windows'); -// eslint-disable-next-line no-undef -const osPath = join(__dirname, osName); // used for cwd when spawning child -const isWin = osName === 'windows'; -const isMac = osName === 'mac'; -const isLinux = osName === 'linux'; -const nodeBin = join(system.paths.current, 'bin', 'node'); -const release = parseFloat(os.release()); - -const defaultPass = 'e75f0173be748b6f68b3feb61255693c'; // "preyrocks", because it does. :) - -let child; -let timer; -let emitter; -let stopped; -let killApps; - -// eslint-disable-next-line consistent-return -const killRunningApps = (cb) => { - if (osName !== 'mac') return cb(); - // eslint-disable-next-line quotes - const cmd = `ps aux |awk '{for(i=11;i<=NF;i++){printf "%s ", $i}; print $2}' | grep "^/Applications" | awk '{print $NF}`; +////////////////////////////////////////// + +var util = require('util'), + path = require('path'), + join = path.join, + Emitter = require('events').EventEmitter, + exec = require('child_process').exec, + common = require('./../../common'), + logger = common.logger.prefix('actions'), + system = common.system, + run_as_user = system.run_as_logged_user, + os = require('os'), + os_name = os.platform().replace('darwin', 'mac').replace('win32', 'windows'), + os_path = join(__dirname, os_name), // used for cwd when spawning child + is_win = os_name == 'windows', + is_mac = os_name == 'mac', + is_linux = os_name == 'linux', + node_bin = join(system.paths.current, 'bin', 'node'), + release = parseFloat(os.release()); + +var lock_binary = lock_binary_path(), + default_pass = 'e75f0173be748b6f68b3feb61255693c'; // "preyrocks", because it does. :) + +var child, + timer, + emitter, + stopped, + kill_apps; + +function kill_running_apps(cb) { + if (os_name != 'mac') return cb(); + var cmd = `ps aux |awk '{for(i=11;i<=NF;i++){printf "%s ", $i}; print $2}' | grep "^/Applications" | awk '{print $NF}'` exec(cmd, (err, out) => { - let apps = out.split('\n').slice(0, -1); - apps = apps.join(' '); - - const killCmd = `kill -9 ${apps};killall Finder`; - runAsUser(killCmd, [], () => cb()); - }); -}; - -const lockBinaryPath = () => { - let binaryName = 'prey-lock'; - - if (isWin) { - binaryName = (release >= '6.1') ? 'new-prey-lock' : 'prey-lock'; - } else if (isLinux && system.python_version && system.python_version >= '3.0.0') { - // eslint-disable-next-line no-unused-vars - binaryName += '3'; - } else if (isMac && common.os_release >= '11.0') { - // New lock script for macOS Big Sur + var apps = out.split('\n').slice(0,-1); + apps = apps.join(" ") + + var kill_cmd = 'kill -9 ' + apps + ';killall Finder'; + run_as_user(kill_cmd, [], (err) =>{ + return cb(); + }) + }) +} + +function lock_binary_path() { + var binary_name = 'prey-lock'; + + if (is_win) { + binary_name = (release >= '6.1') ? 'new-prey-lock' : 'prey-lock'; + } else if (is_linux && system.python_version && system.python_version >= "3.0.0") { + binary_name += "3"; + } else if (is_mac && common.os_release >= '11.0') { + // New lock script for macOS Big Sur return (join(__dirname, '..', '..', 'utils', 'prey-actions.app', 'Contents', 'MacOS', 'prey-actions')); } - return (join(__dirname, osName, binaryName)); -}; -const lockBinary = lockBinaryPath(); + return (join(__dirname, os_name, binary_name)); +} -const md5Digest = (str) => crypto.createHash('md5').update(str).digest('hex'); +var md5_digest = function(str){ + return require('crypto').createHash('md5').update(str).digest('hex'); +}; -// eslint-disable-next-line consistent-return -const before = (cb) => { +function before(cb) { // as priviledged user, lock all escape mechanisms // we cannot do this as logged user because we lose privileges. - if (isWin) return exec(`${lockBinary} --block`, cb); - if (isLinux || (isMac && !killApps)) return cb(); - killRunningApps(cb); -}; + if (is_win) return exec(lock_binary + ' --block', cb); + + if (is_linux || (is_mac && !kill_apps)) return cb(); + + kill_running_apps(cb); +} -// eslint-disable-next-line consistent-return -const after = (cb) => { - if (!isWin) return cb(); +function after(cb) { + if (!is_win) return cb(); // ok, good. now restore access to escape routes. - // eslint-disable-next-line consistent-return - exec(`${lockBinary} --unblock`, () => { - // eslint-disable-next-line no-undef - if (isWin) runAsUser(join(__dirname, osName, 'tb-enable'), [], cb); + exec(lock_binary + ' --unblock', function() { + if (is_win) run_as_user(join(__dirname, os_name, 'tb-enable'), [], cb); else return cb(); }); -}; +} -const setTouchPadState = (state) => { - const data = { - action: 'set-enabled-touchPad', - key: 'device-key', - token: 'token', - logged: false, - dirs: [state], - optsKeep: [], - }; +function start(id, opts, cb) { + var opts = opts || {}, + password = opts.password || opts.unlock_pass || default_pass, + message = opts.lock_message || ""; - const action = 'set-enabled-touchPad'; + kill_apps = false; + kill_apps = opts.close_apps; - // eslint-disable-next-line consistent-return - system.spawn_as_admin_user(nodeBin, data, (err, touchpad) => { - if (err) return logger.info(`Error Enabling Touchpad: ${JSON.stringify(err)}`); - if (typeof touchpad === 'function') touchpad(action, data); - }); -}; + if (!password || password.toString().trim() === '') + return cb(new Error('No unlock password given!')) -const finished = (id, cb) => { - after(() => { - if (isWin) setTouchPadState('Enable'); + if (os_name == 'windows' && path.basename(lock_binary) == 'prey-lock') // old prey-lock binary for windows + password = password; + else + password = Buffer.from(typeof password !== 'number' ? password : password.toString()).toString('base64'); + password = md5_digest(password.toString().trim()); - if (emitter) { - emitter.emit('end', id); - emitter = null; - } - // eslint-disable-next-line no-unused-expressions - cb && cb(); - }); -}; + stopped = false; // ensure the flag is off + before(function() { + open(id, password, message, cb) + }) +} -const open = (id, password, message, cb) => { - // eslint-disable-next-line no-param-reassign - if (!message) message = ''; +function open(id, password, message, cb) { + if (!message) message = ""; - // eslint-disable-next-line prefer-const - let args = [password, message]; - if (isMac && common.os_release >= '11.0') args.unshift('-lock'); + var args = [password, message]; + if (is_mac && common.os_release >= '11.0') + args.unshift('-lock') timer = null; - system.spawn_as_logged_user(lockBinary, args, { cwd: osPath }, (err, lock) => { + + system.spawn_as_logged_user(lock_binary, args, { cwd: os_path }, function(err, lock) { if (err || stopped) { + // if no logged user is found, retry in a sec or two. - if (err && err.code === 'NO_LOGGED_USER') { - timer = setTimeout(() => { open(id, password, message, cb); }, 5000); + if (err && err.code == 'NO_LOGGED_USER') { + timer = setTimeout(function() { open(id, password, message, cb) }, 5000); return; + } else { + return finished(id, function() { cb && cb(err) }); } - // eslint-disable-next-line consistent-return - return finished(id, () => cb && cb(err)); } child = lock; - child.stdout.on('data', (data) => { - // eslint-disable-next-line prefer-destructuring - if (child && child.impersonating && data.toString().match(/PID:? (\d+)/)) child.impersonated_pid = data.toString().match(/PID:? (\d+)/)[1]; - else if (emitter && data.toString().match(/invalid password/i)) emitter.emit('failed_unlock_attempt'); + child.stdout.on('data', function(data) { + if (child && child.impersonating && data.toString().match(/PID:? (\d+)/)) { + child.impersonated_pid = data.toString().match(/PID:? (\d+)/)[1]; + + } else if (emitter && data.toString().match(/invalid password/i)) { + emitter.emit('failed_unlock_attempt'); + } }); - // eslint-disable-next-line consistent-return - child.once('exit', (code) => { + child.once('exit', function(code, signal) { child = null; - if (stopped || code === 66 || code === 67) return finished(id); + + + if (stopped || code === 66 || code === 67) + return finished(id); + // trying to kill me are you? ha-ha-ha. + open(id, password, message); }); if (!emitter) { - emitter = new Emitter(); - // eslint-disable-next-line no-unused-expressions + emitter = new Emitter; cb && cb(null, emitter); } }); -}; - -// eslint-disable-next-line consistent-return -const start = (id, opts, cb) => { - // eslint-disable-next-line no-param-reassign - opts = opts || {}; - let password = opts.password || opts.unlock_pass || defaultPass; - const message = opts.lock_message || ''; - - killApps = false; - killApps = opts.close_apps; - - if (!password || password.toString().trim() === '') return cb(new Error('No unlock password given!')); - if (!(osName === 'windows' && path.basename(lockBinary) === 'prey-lock')) { - // eslint-disable-next-line no-undef - password = Buffer.from(typeof password !== 'number' ? password : password.toString()).toString('base64'); - } - password = md5Digest(password.toString().trim()); +} - stopped = false; // ensure the flag is off - before(() => open(id, password, message, cb)); -}; - -const stop = () => { - if (timer) clearTimeout(timer); +function stop() { + if (timer) + clearTimeout(timer); if (child) { stopped = true; - if (isWin || !child.impersonated_pid) { - setTouchPadState('Enable'); + if (is_win || !child.impersonated_pid) { + setTouchPadState("Enable"); child.kill(); } else { system.kill_as_logged_user(child.impersonated_pid); } } -}; +} -const isRunning = () => { - // eslint-disable-next-line no-undef - try { process.kill(child.pid, 0); return true; } catch (e) { return false; } -}; +const setTouchPadState = (state) => { + let data = { + action: "set-enabled-touchPad", + key: "device-key", + token: "token", + logged: false, + dirs : [state], + optsKeep: [] + } + + let action = 'set-enabled-touchPad'; + + system.spawn_as_admin_user(node_bin, data, function(err, touchpad) { + if(err) return logger.info('Error Enabling Touchpad:' + JSON.stringify(err)); + if (typeof touchpad == 'function') touchpad(action, data); + }); +} + +function finished(id, cb) { + after(function() { + if(is_win) + setTouchPadState("Enable"); + + if (emitter) { + emitter.emit('end', id); + emitter = null; + } + cb && cb(); + }) +} + +function is_running() { + try { process.kill(child.pid, 0); return true; } + catch(e) { return false; } +} exports.events = ['failed_unlock_attempt']; -// eslint-disable-next-line consistent-return -exports.start = (id, options, cb) => { - if (child && isRunning()) { - if (typeof options === 'function') return cb(new Error('Lock already running!')); - // eslint-disable-next-line consistent-return - return; - } - if (isWin) setTouchPadState('Disable'); +exports.start = function(id, options, cb){ + if (child && is_running()) + return callback(new Error('Lock already running!')); + if(is_win) + setTouchPadState("Disable"); start(id, options, cb); }; -exports.stop = () => { - if (!child || !isRunning()) return; +exports.stop = function(){ + if (!child || !is_running()) + return; + stop(); -}; +}; \ No newline at end of file diff --git a/lib/agent/providers/hardware/index.js b/lib/agent/providers/hardware/index.js index 95f8c54ff..d2efa1ddd 100644 --- a/lib/agent/providers/hardware/index.js +++ b/lib/agent/providers/hardware/index.js @@ -1,137 +1,132 @@ -/* eslint-disable linebreak-style */ -/// /////////////////////////////////////// +////////////////////////////////////////// // Prey JS Hardware Module // (c) 2011 - Fork Ltd. // By Tomas Pollak - http://forkhq.com // GPLv3 Licensed -/// /////////////////////////////////////// - -const os = require('os'); -const async = require('async'); -const network = require('network'); -const hooks = require('../../hooks'); -const common = require('../../common'); - -const logger = common.logger.prefix('hardware'); -const osName = process.platform.replace('darwin', 'mac').replace('win32', 'windows'); -const storage = require('../../utils/storage'); - -// eslint-disable-next-line import/no-dynamic-require -const osFunctions = require(`./${osName}`); -const exp = module.exports; - -exp.get_processor_info = (callback) => { - const cpus = os.cpus(); - const cpuInfo = { +////////////////////////////////////////// + +"use strict"; + +var _ = require('underscore'), + os = require('os'), + async = require('async'), + network = require('network'), + hooks = require('./../../hooks'), + common = require('./../../common'), + logger = common.logger.prefix('hardware'), + os_name = process.platform.replace('darwin', 'mac').replace('win32', 'windows'), + common = require('./../../../common'), + logger = common.logger.prefix('hardware'), + storage = require('./../../utils/storage'), + os_functions = require('./' + os_name), + exp = module.exports; + +exp.get_processor_info = function(callback) { + var cpus = os.cpus(); + var cpu_info = { model: cpus[0].model.trim(), speed: cpus[0].speed, - cores: cpus.length, + cores: cpus.length }; - callback(null, cpuInfo); + callback(null, cpu_info); }; /** * There are no parameters to create a memoized hash key on so supply "key" as default in * optional hasher function. - * */ -exp.get_firmware_info = async.memoize((callback) => { - // eslint-disable-next-line consistent-return - osFunctions.get_firmware_info((err, data) => { + **/ +exp.get_firmware_info = async.memoize(function(callback){ + os_functions.get_firmware_info(function(err, data) { if (err) return callback(err); - // eslint-disable-next-line prefer-const - let dataFirmwareInfo = data; - if (data.device_type) dataFirmwareInfo.device_type = data.device_type.replace('Notebook', 'Laptop'); - callback(null, dataFirmwareInfo); + if (data.device_type) + data.device_type = data.device_type.replace('Notebook', 'Laptop'); + + callback(null, data); }); }); -exp.get_storage_devices_list = (callback) => callback(new Error('TODO!')); +exp.get_storage_devices_list = function(callback){ + callback(new Error('TODO!')) +}; + + /** * Returns full list of network interfaces, including MAC and broadcast address - * */ + **/ exp.get_network_interfaces_list = network.get_interfaces_list; -exp.get_tpm_module = osFunctions.get_tpm_module; -exp.get_os_edition = osFunctions.get_os_edition; -exp.get_winsvc_version = osFunctions.get_winsvc_version; -exp.get_rp_module = osFunctions.get_recovery_partition_status; +exp.get_tpm_module = os_functions.get_tpm_module; +exp.get_os_edition = os_functions.get_os_edition; +exp.get_winsvc_version = os_functions.get_winsvc_version; +exp.get_rp_module = os_functions.get_recovery_partition_status; // even though these functions look like they belong in the network provider, // we put them here because MAC addresses are part of the network interfaces, // and are not subject to change (even though they can be spoofed) -exp.get_first_mac_address = (callback) => { - network.get_interfaces_list((err, list) => { - if (err) callback(err); - else if (list && list[0] && list[0].mac_address) callback(null, list[0].mac_address); - callback(new Error('Couldn\'t find any valid MAC addresses!')); +exp.get_first_mac_address = function(callback) { + + network.get_interfaces_list(function(err, list) { + if (err) + callback(err) + else if (list && list[0] && list[0].mac_address) + callback(null, list[0].mac_address); + else + callback(new Error("Couldn't find any valid MAC addresses!")); }); + }; -exp.get_ram_module_list = osFunctions.get_ram_module_list; +exp.get_ram_module_list = os_functions.get_ram_module_list; exp.track_hardware_changes = (data) => { - // eslint-disable-next-line no-param-reassign if (data.tpm_module) delete data.tpm_module; - // eslint-disable-next-line no-param-reassign if (data.os_edition) delete data.os_edition; - // eslint-disable-next-line no-param-reassign if (data.winsvc_version) delete data.winsvc_version; - // eslint-disable-next-line no-param-reassign if (data.rp_module) delete data.rp_module; - let diffCount = 0; - const saveData = () => { - storage.do('set', { type: 'keys', id: 'hardware', data: { value: JSON.stringify(data) } }, (err) => { + var diff_count = 0; + var save_data = () => { + storage.do('set', {type: 'keys', id: 'hardware', data: {value: JSON.stringify(data)}}, (err) => { if (err) logger.error('Unable to save hardware data'); }); - }; + } - // eslint-disable-next-line consistent-return - const compareField = (current, stored) => { + var compare_field = (current, stored) => { if (stored instanceof Array) { - // eslint-disable-next-line no-plusplus - if (!current || (current.length > stored.length)) return diffCount++; - // eslint-disable-next-line consistent-return + if (!current || (current.length > stored.length)) return diff_count++; stored.forEach((value) => { const foundIndex = current.findIndex((element) => element === value); - if (foundIndex === -1) { - // eslint-disable-next-line no-plusplus - return diffCount++; - } + if (foundIndex === -1) return diffCount++; }); } else if (stored instanceof Object) { - if (!current || (Object.keys(current).length > Object.keys(stored).length)) { - // eslint-disable-next-line no-plusplus - return diffCount++; - } + if (!current || (Object.keys(current).length > Object.keys(stored).length)) return diff_count++; Object.keys(stored).forEach((key) => { - compareField(current[key], stored[key]); + compare_field(current[key], stored[key]) }); - // eslint-disable-next-line no-plusplus - } else if (current !== stored) diffCount++; - }; + } else { + if (current != stored) diff_count++; + } + } - // eslint-disable-next-line consistent-return - storage.do('query', { type: 'keys', column: 'id', data: 'hardware' }, (error, storedData) => { - if (error) logger.error('Unable to read hardware data'); - if (storedData.length === 0) return saveData(); + storage.do('query', {type: 'keys', column: 'id', data: 'hardware'}, (err, stored_data) => { + if (err) logger.error('Unable to read hardware data'); + if (stored_data.length == 0) return save_data(); try { - // eslint-disable-next-line no-param-reassign - storedData = JSON.parse(storedData[0].value); + stored_data = JSON.parse(stored_data[0].value); } catch (e) { - console.log('ERROR!'); // modificar + console.log("ERROR!") // modificar } - compareField(data, storedData); + compare_field(data, stored_data); - if (diffCount > 0) { + if (diff_count > 0) { hooks.trigger('hardware_changed'); - storage.do('del', { type: 'keys', id: 'hardware' }, (err) => { + storage.do('del', {type: 'keys', id: 'hardware'}, (err) => { if (err) logger.error('Unable to delete hardware data'); - saveData(); - }); + save_data(); + }) } - }); -}; + }) +} \ No newline at end of file diff --git a/lib/agent/providers/network/windows.js b/lib/agent/providers/network/windows.js index 8afef366f..041a7c62b 100644 --- a/lib/agent/providers/network/windows.js +++ b/lib/agent/providers/network/windows.js @@ -1,23 +1,23 @@ -/* eslint-disable linebreak-style */ +"use strict"; -/// /////////////////////////////////////// +////////////////////////////////////////// // Prey JS Network Module Windows Functions // (c) 2011 - Fork Ltd. // by Tomas Pollak - http://forkhq.com // GPLv3 Licensed -/// /////////////////////////////////////// +////////////////////////////////////////// -const wmic = require('wmic'); -const { exec } = require('child_process'); -const os = require('os'); -const si = require('systeminformation'); -const common = require('../../common'); - -const release = parseFloat(os.release()); +var wmic = require('wmic'), + exec = require('child_process').exec, + os = require('os'), + common = require('./../../common'), + logger = common.logger.prefix('network-windows'), + si = require('systeminformation'), + release = parseFloat(os.release()); /** * Callsback a list of wireless adapter names. - * */ + **/ exports.get_wireless_interfaces_list = function(callback) { var query = 'nic where "Name like \'%Wireless%\'" get NetConnectionID'; @@ -36,18 +36,17 @@ exports.get_wireless_interfaces_list = function(callback) { /** * Returns the MAC address of the active access point. - * */ -exports.get_active_access_point_mac = (callback) => { + **/ +exports.get_active_access_point_mac = function(callback) { if (release >= 6.0) { - // eslint-disable-next-line consistent-return - exec('netsh wlan show interfaces', (err, stdout) => { + exec('netsh wlan show interfaces', function(err, stdout) { if (err) return callback(err); - const bssid = stdout.toString().match(/BSSID\s+:\s?(.+)/); + var bssid = stdout.toString().match(/BSSID\s+:\s?(.+)/); if (bssid) { callback(null, bssid[1]); } else { - callback(null, ''); + callback(null, '') } }); } else { @@ -55,220 +54,227 @@ exports.get_active_access_point_mac = (callback) => { } }; -exports.get_active_access_point = (callback) => { +exports.get_active_access_point = function(callback) { if (release >= 6.0) { - // eslint-disable-next-line consistent-return - exec('netsh wlan show interfaces', (error, stdout) => { - if (error) return callback(error); - if (!stdout.includes('SSID')) return callback(new Error('Wifi connection unavailable')); + exec('netsh wlan show interfaces', (err, stdout) => { + if (err) return callback(err); + if (!stdout.includes('SSID')) + return callback(new Error('Wifi connection unavailable')); + try { - const info = stdout.split('\n'); - const ssid = escape(stdout.toString().match(/SSID\s+:\s?(.+)/)[1]); - const mac_address = stdout.toString().match(/BSSID\s+:\s?(.+)/)[1]; - const ss = info[18].toString().match(/\s+:\s?(.+)/)[1].trim(); + var info = stdout.split('\n'), + ssid = escape(stdout.toString().match(/SSID\s+:\s?(.+)/)[1]), + mac_address = stdout.toString().match(/BSSID\s+:\s?(.+)/)[1], + ss = info[18].toString().match(/\s+:\s?(.+)/)[1].trim(); // Verify info from command output - if (ss.slice(-1) === '%') { - const signal_strength = parseInt(ss, 10) - 100; - const channel = parseInt(info[15].toString().match(/\s+:\s?(.+)/)[1], 10); - const security = info[12].toString().match(/\s+:\s?(.+)/)[1]; - - const ap = { - ssid, mac_address, signal_strength, channel, security, - }; + if (ss.slice(-1) == '%') { + var signal_strength = parseInt(ss) -100, + channel = parseInt(info[15].toString().match(/\s+:\s?(.+)/)[1]), + security = info[12].toString().match(/\s+:\s?(.+)/)[1]; + + var ap = {ssid: ssid, mac_address: mac_address, signal_strength: signal_strength, channel: channel, security: security} callback(null, ap); // When the data isn't consistent we're using the old method } else { - // eslint-disable-next-line consistent-return exports.get_access_points_list((err, aps) => { if (err) return callback(err); - const paddedMac = mac_address.toString().trim().replace(/(^|:)(?=[0-9a-fA-F](?::|$))/g, '$10'); + var padded_mac = mac_address.toString().trim().replace(/(^|:)(?=[0-9a-fA-F](?::|$))/g, "$10"); + + var aps = aps.filter(function(ap) { + return ap.mac_address === padded_mac; + }); - const apsFiltered = aps.filter((ap) => ap.mac_address === paddedMac); + if (aps.length > 0) { + callback(null, aps[0]); + } else { + callback(new Error('Could not find matching access point for' + padded_mac)); + } + + }) - if (apsFiltered.length > 0) { - callback(null, apsFiltered[0]); - } else callback(new Error(`Could not find matching access point for ${paddedMac}`)); - }); } - } catch (e) { - callback(new Error('Unable to get current ap.')); + } catch(e) { + callback(new Error('Unable to get current ap.')) } - }); + }) } else { callback(new Error('TODO!')); } -}; +} + -/// ////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// // access points list fetcher and parser -/// ////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// /** * Gets access points list * @param {String} wifi_device - should return something like * { ssid:"",security:true,quality:23,signal_strength:54,noise_level:24} * - * autowc actually returns {mac_address,ssid,signal_strength,channel,signal_to_noise} - * this function converts - * */ - -exports.get_access_points_list = (callback) => { - let cmd; - let parser; - let list = []; - - // eslint-disable-next-line consistent-return - const done = (err) => { - if (err || list.length === 0) { - if (typeof err === 'undefined') return callback(new Error('No access points found.')); - if (!err) return callback(new Error('No access points found.')); - if (err.code === 10) return callback('No Wi-Fi adapter found'); - return callback(err); + * autowc actually returns {mac_address,ssid,signal_strength,channel,signal_to_noise} this function converts + **/ + +exports.get_access_points_list = function(callback) { + + var cmd, parser, list = []; + + var done = function(err){ + if (typeof err === 'undefined') return callback(new Error('No access points found.')); + if (err || list.length == 0) { + var e = !err ? new Error("No access points found.") + : err.code == 10 ? 'No Wi-Fi adapter found' : err; + callback(e); + } else { + callback(null, list); } - return callback(null, list); - }; + } if (release <= 5.2) { - cmd = 'autowcxp -list'; + cmd = 'autowcxp -list'; parser = 'autowc'; } else { - cmd = 'netsh wlan show all'; + cmd = 'netsh wlan show all'; parser = 'netsh'; } - exec('chcp 65001', () => { - common.system.scan_networks(() => { - // eslint-disable-next-line consistent-return - exec(cmd, (err, out) => { + exec('chcp 65001', function() { + common.system.scan_networks(function() { + exec(cmd, function(err, out) { if (err) return done(err); - list = exports[`parse_access_points_list_${parser}`](out); + list = exports['parse_access_points_list_' + parser](out); done(); - }); - }); - }); + }) + }) + }) + }; -exports.parse_access_points_list_autowc = (out) => { - let arr = []; - try { - arr = JSON.parse(`[${out}]`); - } catch (e) { - return arr; - } +exports.parse_access_points_list_autowc = function(out) { - if (arr.length === 0) return []; + var arr = []; + try { arr = JSON.parse("[" + out + "]") } + catch(e) { return arr; }; - return arr.map((o) => ({ - ssid: o.ssid.replace(/[^\w :'-]/g, ''), - // security : null, // don't have this data - // quality : null, - signal_strength: o.signal_strength, - noise_level: o.signal_to_noise, - })); -}; + if (arr.length === 0) + return []; + + return arr.map(function(o) { + return { + ssid : o.ssid.replace(/[^\w :'-]/g, ''), + // security : null, // don't have this data + // quality : null, + signal_strength : o.signal_strength, + noise_level : o.signal_to_noise + }; + }) -/* example output: +} + +/* example output: SSID 1 : SomewhereWiFi Network type : Infrastructure Authentication : Open - Encryption : None + Encryption : None BSSID 1 : aa:bb:cc:11:22:33 - Signal : 38% + Signal : 38% Radio type : 802.11n - Channel : 6 + Channel : 6 Basic rates (Mbps) : 1 2 5.5 11 Other rates (Mbps) : 6 9 12 18 24 36 48 54 BSSID 2 : 33:22:11:bb:cc:dd - Signal : 40% + Signal : 40% Radio type : 802.11n - Channel : 4 + Channel : 4 Basic rates (Mbps) : 1 2 5.5 11 Other rates (Mbps) : 6 9 12 18 24 36 48 54 - */ -exports.parse_access_points_list_netsh = (out) => { - // eslint-disable-next-line prefer-const - let list = []; - const blocks = out.split(/\nSSID \d{1,2}\s:/); +exports.parse_access_points_list_netsh = function(out) { - if (!blocks) return []; + var list = [], + blocks = out.split(/\nSSID \d{1,2}\s:/); - const getValues = (str) => { - // eslint-disable-next-line prefer-const - let res = {}; - let idx = 0; - str.split('\n').forEach((line) => { - if (line.toString().trim() === '') return; + if (!blocks) + return []; - const split = line.split(': '); - const key = idx.toString(); - const val = split[1] ? split[1].trim() : null; + var get_values = function(str) { + var res = {}; + var idx = 0; + str.split('\n').forEach(function(line) { + if (line.toString().trim() == '') + return; - if (key) res[key] = val; - idx += 1; - }); + var split = line.split(': '), + key = idx.toString(), + val = split[1] ? split[1].trim() : null; + + if (key) res[key] = val; + idx++; + }) return res; - }; + } - const SSID_KEYS = { - SSID: '0', - AUTH: '2', + var SSID_KEYS = { + SSID : '0', + AUTH : '2' }; - const BSSID_KEYS = { - BSSID: '0', - SIGNAL: '1', - CHANNEL: '3', + var BSSID_KEYS = { + BSSID : '0', + SIGNAL : '1', + CHANNEL : '3' }; - const buildAp = (base, router) => { - const obj = { - ssid: (!base[SSID_KEYS.SSID] || base[SSID_KEYS.SSID].toString().trim() === '') ? '(Unknown)' : base['0'], - security: base[SSID_KEYS.AUTH] !== 'Open' ? base[SSID_KEYS.AUTH] : null, - mac_address: router[BSSID_KEYS.BSSID], - }; + var build_ap = function(base, router) { + var obj = { + ssid : (!base[SSID_KEYS.SSID] || base[SSID_KEYS.SSID].toString().trim() == '') ? '(Unknown)' : base['0'], + security : base[SSID_KEYS.AUTH] != 'Open' ? base[SSID_KEYS.AUTH] : null, + mac_address : router[BSSID_KEYS.BSSID] + } // signal is shown as '94%', so we need to substract 100 to get a consistent behaviour with // OSX and Linux's signal_strength integer - // eslint-disable-next-line max-len - if (router[BSSID_KEYS.SIGNAL]) obj.signal_strength = parseInt(router[BSSID_KEYS.SIGNAL], 10) - 100; + if (router[BSSID_KEYS.SIGNAL]) + obj.signal_strength = parseInt(router[BSSID_KEYS.SIGNAL]) - 100; - if (router[BSSID_KEYS.CHANNEL])obj.channel = parseInt(router[BSSID_KEYS.CHANNEL], 10); + if (router[BSSID_KEYS.CHANNEL]) + obj.channel = parseInt(router[BSSID_KEYS.CHANNEL]); return obj; - }; + } - blocks.forEach((block, i) => { - if (i === 0) return; // first block contains data about the interface and card + blocks.forEach(function(block, i) { + if (i == 0) return; // first block contains data about the interface and card - // netsh groups access points by BSSID, so we need to separate each + // netsh groups access points by BSSID, so we need to separate each // SSID block into the BSSID it contains and select one of them - const routers = block.split(/[BSSID BSSIDD] \d/); + var routers = block.split(/[BSSID BSSIDD] \d/); // the first block will contain shared information: SSID, auth, encryption // so parse those values first. insert the SSID part that was removed from line one - const shared = `SSID : ${routers.shift()}`; - const main = getValues(shared); + var shared = 'SSID : ' + routers.shift(), + main = get_values(shared); - const routersMapped = routers.map((routerData) => { - const values = getValues(`BSSID${routerData}`); + var routers = routers.map(function(router_data) { + var values = get_values('BSSID' + router_data); - if (!values[BSSID_KEYS.BSSID] || values[BSSID_KEYS.BSSID].toString().trim() === '') return; + if (!values[BSSID_KEYS.BSSID] || values[BSSID_KEYS.BSSID].toString().trim() == '') + return; - // eslint-disable-next-line consistent-return return values; - }).filter((el) => el); // remove invalid entries + }).filter(function(el) { return el }) // remove invalid entries // console.log(main['SSID'] + ' has ' + routers.length + ' routers.'); - routersMapped.forEach((router) => { - list.push(buildAp(main, router)); - }); + routers.forEach(function(router) { + list.push(build_ap(main, router)); + }) + }); return list; -}; +} \ No newline at end of file