domotz-remote-pawn
Version:
Domotz Agent
339 lines (301 loc) • 11.2 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz UK LLP
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
**/
/**
*
* Created by Iacopo Papalini <iacopo@domotz.com> on 11/04/16.
*/
const DEFAULT_READ_COMMUNITY = 'public';
var extractOids = function (oidsMapping) {
'use strict';
var oids = [];
for (var oid in oidsMapping) {
if (oidsMapping.hasOwnProperty(oid)) {
oids.push(oid);
}
}
return oids;
};
var isEmpty = function (obj) {
if (obj === undefined || obj === null || obj === '') {
return true;
}
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
return false;
}
}
return JSON.stringify(obj) === JSON.stringify({});
};
var factory = function (snmp, settingsManager, domotzLog) {
var snmpConsole = domotzLog ? domotzLog.decorateLogs() : console;
var transformerString = function (o, type) {
// https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
try {
if (isCounter64(type)) {
return transformerCounter64(o, type);
}
var s = '' + o;
if (s.indexOf('\uFFFD') === -1) {
return s;
} else {
return o
.toString('hex')
.match(/.{1,2}/g)
.join(' ')
.toUpperCase();
}
} catch (e) {
return '' + o;
}
};
var transformerMac = function (o) {
var byteList = [];
for (var i = 0; i < o.length; i++) {
var tmpByte = o.readUInt8(i);
var tmpStr = tmpByte.toString(16);
if (tmpStr.length < 2) {
tmpStr = '0' + tmpStr;
}
byteList.push(tmpStr);
}
return byteList.join(':').toUpperCase();
};
var isCounter64 = function (type) {
return type !== undefined && type === snmp.ObjectType.Counter64;
};
var transformerCounter64 = function (value, type) {
if (isCounter64(type)) {
var decimalValue = 0;
var length = value.length;
for (var j = 0; j < length; j++) {
var currentValue = value[j] * Math.pow(256, length - j - 1);
decimalValue += currentValue;
}
return decimalValue;
}
return value;
};
var transformerInt = function (value, type) {
if (isCounter64(type)) {
return transformerCounter64(value, type);
}
return value;
};
var transformerIntTypeInvariant = function (value, type) {
if (isCounter64(type)) {
return transformerCounter64(value, type);
}
if (typeof value === 'number') {
return value;
}
return value + '';
};
var transformer = function (valueType) {
'use strict';
var transformingFunctions = {
string: transformerString,
mac: transformerMac,
int: transformerInt,
};
if (transformingFunctions.hasOwnProperty(valueType)) {
return transformingFunctions[valueType];
} else {
return transformingFunctions.string;
}
};
var transformerTypeInvariant = function (valueType) {
'use strict';
var transformingFunctions = {
string: transformerString,
mac: transformerMac,
int: transformerIntTypeInvariant,
};
if (transformingFunctions.hasOwnProperty(valueType)) {
return transformingFunctions[valueType];
} else {
return transformingFunctions.string;
}
};
var SecurityLevelMap = {};
var AuthProtocolsMap = {};
var PrivProtocolsMap = {};
var VersionsMap = {
V1: snmp.Version1,
V2: snmp.Version2c,
V3_NO_AUTH: snmp.Version3,
V3_AUTH_NO_PRIV: snmp.Version3,
V3_AUTH_PRIV: snmp.Version3,
};
var V2VersionMap = {
0: snmp.Version1,
1: snmp.Version2c,
3: snmp.Version3,
};
if (snmp.SecurityLevel) {
SecurityLevelMap = {
V3_NO_AUTH: snmp.SecurityLevel.noAuthNoPriv,
V3_AUTH_NO_PRIV: snmp.SecurityLevel.authNoPriv,
V3_AUTH_PRIV: snmp.SecurityLevel.authPriv,
};
}
function mapLevel(options, authProvider) {
if (authProvider) {
return SecurityLevelMap[authProvider.version];
}
if (options) {
return SecurityLevelMap[options.extendedVersion];
}
throw new Error('Unspecified or unmappable security level');
}
if (snmp.AuthProtocols) {
AuthProtocolsMap = {
MD5: snmp.AuthProtocols.md5,
SHA: snmp.AuthProtocols.sha,
'SHA-224': snmp.AuthProtocols.sha224,
'SHA-256': snmp.AuthProtocols.sha256,
'SHA-384': snmp.AuthProtocols.sha384,
'SHA-512': snmp.AuthProtocols.sha512,
};
}
function mapAuthProtocol(options, authProvider) {
if (authProvider) {
return AuthProtocolsMap[
authProvider.authenticationProtocol && authProvider.authenticationProtocol !== null ? authProvider.authenticationProtocol : 'none'
];
}
if (options) {
return AuthProtocolsMap[
options.authenticationProtocol && options.authenticationProtocol !== null ? options.authenticationProtocol : 'none'
];
}
}
if (snmp.PrivProtocols) {
PrivProtocolsMap = {
DES: snmp.PrivProtocols.des,
AES: snmp.PrivProtocols.aes,
'AES-256B': snmp.PrivProtocols.aes256b,
'AES-256R': snmp.PrivProtocols.aes256r,
};
}
function mapPrivProtocol(options, authProvider) {
if (authProvider) {
return PrivProtocolsMap[
authProvider.encryptionProtocol && authProvider.encryptionProtocol !== null ? authProvider.encryptionProtocol : 'none'
];
}
if (options) {
return PrivProtocolsMap[options.encryptionProtocol && options.encryptionProtocol !== null ? options.encryptionProtocol : 'none'];
}
}
function mapVersion(options, authProvider) {
if (options && options.extendedVersion) {
return VersionsMap[options.extendedVersion];
}
if (options && options.version !== undefined && options.version !== null) {
return V2VersionMap[options.version];
} else if (authProvider && authProvider.version) {
return VersionsMap[authProvider.version];
} else if (options.version === null || options.version === undefined) {
return snmp.Version2c;
}
snmpConsole.error('Cannot understand required snmp version');
snmpConsole.error('Options are ' + JSON.stringify(options));
snmpConsole.error('Auth Provider is ' + JSON.stringify(authProvider));
throw new Error('Cannot understand required snmp version');
}
function mapCommunity(options, authProvider) {
var community = options.community;
// TODO: maybe check that community is not empty string too
if (authProvider && authProvider.community) {
community = authProvider.community;
}
return community || DEFAULT_READ_COMMUNITY;
}
function mapResource(options, authProvider, resource) {
if (authProvider) {
return authProvider[resource];
}
if (options) {
return options[resource];
}
}
function mapUser(options, authProvider) {
return {
name: mapResource(options, authProvider, 'username'),
level: mapLevel(options, authProvider),
authProtocol: mapAuthProtocol(options, authProvider),
authKey: mapResource(options, authProvider, 'authenticationKey'),
privProtocol: mapPrivProtocol(options, authProvider),
privKey: mapResource(options, authProvider, 'encryptionKey'),
};
}
function checkBindings(interfacesBinding) {
var freshBindings = interfacesBinding.listFresh(1);
if (freshBindings.length === 0) {
snmpConsole.warn('No fresh bindings found');
throw new Error('No fresh bindings found');
}
}
function getInterfaceBindings(options, resourceLocator) {
if (
options.disableFreshBindingsCheck === true ||
(resourceLocator.settingsManager && resourceLocator.settingsManager.isFreshBindingsCheckDisabled() === true)
) {
return null;
}
return resourceLocator.interfacesBindingStorage;
}
function getSession(interfacesBindingStorage, host, options, authProvider) {
if (interfacesBindingStorage) {
checkBindings(interfacesBindingStorage);
}
var version = mapVersion(options, authProvider);
if (version === snmp.Version1 || version === snmp.Version2c) {
options.version = version;
var community = mapCommunity(options, authProvider);
return snmp.createSession(host, community, options);
}
if (snmp.Version3) {
if (version === snmp.Version3) {
var user = mapUser(options, authProvider);
return snmp.createV3Session(host, user, options);
}
}
throw new Error('Unable to create Snmp Session');
}
function getAuthProviderOptions(deviceOptions) {
return {
community: deviceOptions && deviceOptions.snmp_read_community,
version: deviceOptions && deviceOptions.version,
username: deviceOptions && deviceOptions.username,
authenticationProtocol: deviceOptions && deviceOptions.authentication_protocol,
authenticationKey: deviceOptions && deviceOptions.authentication_key,
encryptionProtocol: deviceOptions && deviceOptions.encryption_protocol,
encryptionKey: deviceOptions && deviceOptions.encryption_key,
};
}
return {
transformer: transformer,
transformerTypeInvariant: transformerTypeInvariant,
extractOids: extractOids,
isEmpty: isEmpty,
getInterfaceBindings: getInterfaceBindings,
getSession: getSession,
getAuthProviderOptions: getAuthProviderOptions,
};
};
module.exports.factory = factory;