mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Escape SNMP & IPMI shell commands (#9537)
hopefully doesn't break anything Mostly issues with snmp oids and options containing spaces. Try to remove all of those. DO NOT DELETE THIS TEXT #### Please note > Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting. - [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/) #### Testers If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926` After you are done testing, you can remove the changes with `./scripts/github-remove`. If there are schema changes, you can ask on discord how to revert.
This commit is contained in:
committed by
Neil Lathwood
parent
e0e3e08bf6
commit
fad0bffc43
@@ -101,23 +101,23 @@ function mibdir($mibdir = null, $device = [])
|
||||
return rtrim($dir, '/');
|
||||
}, $dirs)));
|
||||
|
||||
return " -M " . implode(':', $dirs);
|
||||
return implode(':', $dirs);
|
||||
}//end mibdir()
|
||||
|
||||
/**
|
||||
* Generate an snmpget command
|
||||
*
|
||||
* @param array $device the we will be connecting to
|
||||
* @param string $oids the oids to fetch, separated by spaces
|
||||
* @param string $options extra snmp command options, usually this is output options
|
||||
* @param array|string $oids the oids to fetch, separated by spaces
|
||||
* @param array|string $options extra snmp command options, usually this is output options
|
||||
* @param string $mib an additional mib to add to this command
|
||||
* @param string $mibdir a mib directory to search for mibs, usually prepended with +
|
||||
* @return string the fully assembled command, ready to run
|
||||
* @return array the fully assembled command, ready to run
|
||||
*/
|
||||
function gen_snmpget_cmd($device, $oids, $options = null, $mib = null, $mibdir = null)
|
||||
{
|
||||
global $config;
|
||||
$snmpcmd = $config['snmpget'];
|
||||
$snmpcmd = [$config['snmpget']];
|
||||
return gen_snmp_cmd($snmpcmd, $device, $oids, $options, $mib, $mibdir);
|
||||
} // end gen_snmpget_cmd()
|
||||
|
||||
@@ -125,22 +125,22 @@ function gen_snmpget_cmd($device, $oids, $options = null, $mib = null, $mibdir =
|
||||
* Generate an snmpwalk command
|
||||
*
|
||||
* @param array $device the we will be connecting to
|
||||
* @param string $oids the oids to fetch, separated by spaces
|
||||
* @param string $options extra snmp command options, usually this is output options
|
||||
* @param array|string $oids the oids to fetch, separated by spaces
|
||||
* @param array|string $options extra snmp command options, usually this is output options
|
||||
* @param string $mib an additional mib to add to this command
|
||||
* @param string $mibdir a mib directory to search for mibs, usually prepended with +
|
||||
* @return string the fully assembled command, ready to run
|
||||
* @return array the fully assembled command, ready to run
|
||||
*/
|
||||
function gen_snmpwalk_cmd($device, $oids, $options = null, $mib = null, $mibdir = null)
|
||||
{
|
||||
global $config;
|
||||
if ($device['snmpver'] == 'v1' || (isset($device['os'], $config['os'][$device['os']]['nobulk']) && $config['os'][$device['os']]['nobulk'])) {
|
||||
$snmpcmd = $config['snmpwalk'];
|
||||
$snmpcmd = [$config['snmpwalk']];
|
||||
} else {
|
||||
$snmpcmd = $config['snmpbulkwalk'];
|
||||
$snmpcmd = [$config['snmpbulkwalk']];
|
||||
$max_repeaters = get_device_max_repeaters($device);
|
||||
if ($max_repeaters > 0) {
|
||||
$snmpcmd .= " -Cr$max_repeaters ";
|
||||
$snmpcmd[] = "-Cr$max_repeaters";
|
||||
}
|
||||
}
|
||||
return gen_snmp_cmd($snmpcmd, $device, $oids, $options, $mib, $mibdir);
|
||||
@@ -149,38 +149,35 @@ function gen_snmpwalk_cmd($device, $oids, $options = null, $mib = null, $mibdir
|
||||
/**
|
||||
* Generate an snmp command
|
||||
*
|
||||
* @param string $cmd the snmp command to run, like snmpget
|
||||
* @param array $cmd the snmp command to run, like snmpget plus any additional arguments in an array
|
||||
* @param array $device the we will be connecting to
|
||||
* @param string $oids the oids to fetch, separated by spaces
|
||||
* @param string $options extra snmp command options, usually this is output options
|
||||
* @param array|string $oids the oids to fetch, separated by spaces
|
||||
* @param array|string $options extra snmp command options, usually this is output options
|
||||
* @param string $mib an additional mib to add to this command
|
||||
* @param string $mibdir a mib directory to search for mibs, usually prepended with +
|
||||
* @return string the fully assembled command, ready to run
|
||||
* @return array the fully assembled command, ready to run
|
||||
*/
|
||||
function gen_snmp_cmd($cmd, $device, $oids, $options = null, $mib = null, $mibdir = null)
|
||||
{
|
||||
global $debug;
|
||||
|
||||
// populate timeout & retries values from configuration
|
||||
$timeout = prep_snmp_setting($device, 'timeout');
|
||||
$retries = prep_snmp_setting($device, 'retries');
|
||||
|
||||
if (!isset($device['transport'])) {
|
||||
$device['transport'] = 'udp';
|
||||
}
|
||||
|
||||
$cmd .= snmp_gen_auth($device);
|
||||
$cmd .= " $options";
|
||||
$cmd .= $mib ? " -m $mib" : '';
|
||||
$cmd .= mibdir($mibdir, $device);
|
||||
$cmd .= isset($timeout) ? " -t $timeout" : '';
|
||||
$cmd .= isset($retries) ? " -r $retries" : '';
|
||||
$cmd .= ' '.$device['transport'].':'.$device['hostname'].':'.$device['port'];
|
||||
$cmd .= " $oids";
|
||||
|
||||
if (!$debug) {
|
||||
$cmd .= ' 2>/dev/null';
|
||||
$cmd = snmp_gen_auth($device, $cmd);
|
||||
$cmd = $options ? array_merge($cmd, (array)$options) : $cmd;
|
||||
if ($mib) {
|
||||
array_push($cmd, '-m', $mib);
|
||||
}
|
||||
array_push($cmd, '-M', mibdir($mibdir, $device));
|
||||
if ($timeout = prep_snmp_setting($device, 'timeout')) {
|
||||
array_push($cmd, '-t', $timeout);
|
||||
}
|
||||
if ($retries = prep_snmp_setting($device, 'retries')) {
|
||||
array_push($cmd, '-r', $retries);
|
||||
}
|
||||
|
||||
$cmd[] = $device['transport'].':'.$device['hostname'].':'.$device['port'];
|
||||
$cmd = array_merge($cmd, (array)$oids);
|
||||
|
||||
return $cmd;
|
||||
} // end gen_snmp_cmd()
|
||||
@@ -189,8 +186,8 @@ function snmp_get_multi($device, $oids, $options = '-OQUs', $mib = null, $mibdir
|
||||
{
|
||||
$time_start = microtime(true);
|
||||
|
||||
if (is_array($oids)) {
|
||||
$oids = implode(' ', $oids);
|
||||
if (!is_array($oids)) {
|
||||
$oids = explode(' ', $oids);
|
||||
}
|
||||
|
||||
$cmd = gen_snmpget_cmd($device, $oids, $options, $mib, $mibdir);
|
||||
@@ -229,8 +226,7 @@ function snmp_get_multi_oid($device, $oids, $options = '-OUQn', $mib = null, $mi
|
||||
|
||||
$data = [];
|
||||
foreach (array_chunk($oids, $oid_limit) as $chunk) {
|
||||
$partial_oids = implode(' ', $chunk);
|
||||
$cmd = gen_snmpget_cmd($device, $partial_oids, $options, $mib, $mibdir);
|
||||
$cmd = gen_snmpget_cmd($device, $chunk, $options, $mib, $mibdir);
|
||||
$result = trim(external_exec($cmd));
|
||||
if ($result) {
|
||||
$data = array_merge($data, explode("\n", $result));
|
||||
@@ -261,6 +257,16 @@ function snmp_get_multi_oid($device, $oids, $options = '-OUQn', $mib = null, $mi
|
||||
return $array;
|
||||
}//end snmp_get_multi_oid()
|
||||
|
||||
/**
|
||||
* Simple snmpget, returns the output of the get or false if the get failed.
|
||||
*
|
||||
* @param array $device
|
||||
* @param array|string $oid
|
||||
* @param array|string $options
|
||||
* @param string $mib
|
||||
* @param string $mibdir
|
||||
* @return bool|string
|
||||
*/
|
||||
function snmp_get($device, $oid, $options = null, $mib = null, $mibdir = null)
|
||||
{
|
||||
$time_start = microtime(true);
|
||||
@@ -287,8 +293,8 @@ function snmp_get($device, $oid, $options = null, $mib = null, $mibdir = null)
|
||||
* For example instead of get sysName.0, you can getnext sysName to get the .0 value.
|
||||
*
|
||||
* @param array $device Target device
|
||||
* @param string $oid The oid to getnext
|
||||
* @param string $options Options to pass to snmpgetnext (-Oqv for example)
|
||||
* @param array|string $oid The oid to getnext
|
||||
* @param array|string $options Options to pass to snmpgetnext (-Oqv for example)
|
||||
* @param string $mib The MIB to use
|
||||
* @param string $mibdir Optional mib directory to search
|
||||
* @return string|false the output or false if the data could not be fetched
|
||||
@@ -297,7 +303,7 @@ function snmp_getnext($device, $oid, $options = null, $mib = null, $mibdir = nul
|
||||
{
|
||||
$time_start = microtime(true);
|
||||
|
||||
$snmpcmd = Config::get('snmpgetnext', 'snmpgetnext');
|
||||
$snmpcmd = [Config::get('snmpgetnext', 'snmpgetnext')];
|
||||
$cmd = gen_snmp_cmd($snmpcmd, $device, $oid, $options, $mib, $mibdir);
|
||||
$data = trim(external_exec($cmd), "\" \n\r");
|
||||
|
||||
@@ -326,10 +332,10 @@ function snmp_getnext($device, $oid, $options = null, $mib = null, $mibdir = nul
|
||||
function snmp_getnext_multi($device, $oids, $options = '-OQUs', $mib = null, $mibdir = null, $array = array())
|
||||
{
|
||||
$time_start = microtime(true);
|
||||
if (is_array($oids)) {
|
||||
$oids = implode(' ', $oids);
|
||||
if (!is_array($oids)) {
|
||||
$oids = explode(' ', $oids);
|
||||
}
|
||||
$snmpcmd = Config::get('snmpgetnext', 'snmpgetnext');
|
||||
$snmpcmd = [Config::get('snmpgetnext', 'snmpgetnext')];
|
||||
$cmd = gen_snmp_cmd($snmpcmd, $device, $oids, $options, $mib, $mibdir);
|
||||
$data = trim(external_exec($cmd), "\" \n\r");
|
||||
|
||||
@@ -359,9 +365,10 @@ function snmp_check($device)
|
||||
$time_start = microtime(true);
|
||||
|
||||
$oid = '.1.3.6.1.2.1.1.2.0';
|
||||
$options = '-Oqvn';
|
||||
$cmd = gen_snmpget_cmd($device, $oid, $options);
|
||||
exec($cmd, $data, $code);
|
||||
$cmd = gen_snmpget_cmd($device, $oid, '-Oqvn');
|
||||
$proc = new \Symfony\Component\Process\Process($cmd);
|
||||
$proc->run();
|
||||
$code = $proc->getExitCode();
|
||||
d_echo("SNMP Check response code: $code".PHP_EOL);
|
||||
|
||||
recordSnmpStatistic('snmpget', $time_start);
|
||||
@@ -398,7 +405,7 @@ function snmp_walk($device, $oid, $options = null, $mib = null, $mibdir = null)
|
||||
|
||||
function snmpwalk_cache_cip($device, $oid, $array = array(), $mib = 0)
|
||||
{
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, ' -OsnQ', $mib);
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, '-OsnQ', $mib);
|
||||
$data = trim(external_exec($cmd));
|
||||
|
||||
// echo("Caching: $oid\n");
|
||||
@@ -434,7 +441,7 @@ function snmpwalk_cache_cip($device, $oid, $array = array(), $mib = 0)
|
||||
function snmp_cache_ifIndex($device)
|
||||
{
|
||||
// FIXME: this is not yet using our own snmp_*
|
||||
$cmd = gen_snmpwalk_cmd($device, 'ifIndex', ' -OQs', 'IF-MIB');
|
||||
$cmd = gen_snmpwalk_cmd($device, 'ifIndex', '-OQs', 'IF-MIB');
|
||||
$data = trim(external_exec($cmd));
|
||||
|
||||
$array = array();
|
||||
@@ -668,7 +675,7 @@ function snmpwalk_group($device, $oid, $mib = '', $depth = 1, $array = array(),
|
||||
|
||||
function snmpwalk_cache_twopart_oid($device, $oid, $array, $mib = 0)
|
||||
{
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, ' -OQUs', $mib);
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, '-OQUs', $mib);
|
||||
$data = trim(external_exec($cmd));
|
||||
|
||||
foreach (explode("\n", $data) as $entry) {
|
||||
@@ -690,7 +697,7 @@ function snmpwalk_cache_threepart_oid($device, $oid, $array, $mib = 0)
|
||||
{
|
||||
global $debug;
|
||||
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, ' -OQUs', $mib);
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, '-OQUs', $mib);
|
||||
$data = trim(external_exec($cmd));
|
||||
|
||||
foreach (explode("\n", $data) as $entry) {
|
||||
@@ -715,7 +722,7 @@ function snmpwalk_cache_threepart_oid($device, $oid, $array, $mib = 0)
|
||||
|
||||
function snmp_cache_slotport_oid($oid, $device, $array, $mib = 0)
|
||||
{
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, ' -OQUs', $mib);
|
||||
$cmd = gen_snmpwalk_cmd($device, $oid, '-OQUs', $mib);
|
||||
$data = trim(external_exec($cmd));
|
||||
|
||||
foreach (explode("\n", $data) as $entry) {
|
||||
@@ -747,7 +754,7 @@ function snmp_cache_port_oids($oids, $port, $device, $array, $mib = 0)
|
||||
$string .= " $oid.$port";
|
||||
}
|
||||
|
||||
$cmd = gen_snmpget_cmd($device, $string, ' -Ovq', $mib);
|
||||
$cmd = gen_snmpget_cmd($device, $string, '-Ovq', $mib);
|
||||
$data = trim(external_exec($cmd));
|
||||
|
||||
$x = 0;
|
||||
@@ -765,47 +772,40 @@ function snmp_cache_port_oids($oids, $port, $device, $array, $mib = 0)
|
||||
}//end snmp_cache_port_oids()
|
||||
|
||||
|
||||
function snmp_gen_auth(&$device)
|
||||
/**
|
||||
* generate snmp auth arguments
|
||||
* @param array $device
|
||||
* @param array $cmd
|
||||
* @return array
|
||||
*/
|
||||
function snmp_gen_auth(&$device, $cmd = [])
|
||||
{
|
||||
global $debug, $vdebug;
|
||||
|
||||
$cmd = '';
|
||||
|
||||
if ($device['snmpver'] === 'v3') {
|
||||
$cmd = " -v3 -n '' -l '".$device['authlevel']."'";
|
||||
array_push($cmd, '-v3', '-l', $device['authlevel']);
|
||||
array_push($cmd, '-n', isset($device['context_name']) ? $device['context_name'] : '');
|
||||
|
||||
//add context if exist context
|
||||
if (key_exists('context_name', $device)) {
|
||||
$cmd = " -v3 -n '".$device['context_name']."' -l '".$device['authlevel']."'";
|
||||
}
|
||||
|
||||
if (strtolower($device['authlevel']) === 'noauthnopriv') {
|
||||
$authlevel = strtolower($device['authlevel']);
|
||||
if ($authlevel === 'noauthnopriv') {
|
||||
// We have to provide a username anyway (see Net-SNMP doc)
|
||||
$username = !empty($device['authname']) ? $device['authname'] : 'root';
|
||||
$cmd .= " -u '".$username."'";
|
||||
} elseif (strtolower($device['authlevel']) === 'authnopriv') {
|
||||
$cmd .= " -a '".$device['authalgo']."'";
|
||||
$cmd .= " -A '".$device['authpass']."'";
|
||||
$cmd .= " -u '".$device['authname']."'";
|
||||
} elseif (strtolower($device['authlevel']) === 'authpriv') {
|
||||
$cmd .= " -a '".$device['authalgo']."'";
|
||||
$cmd .= " -A '".$device['authpass']."'";
|
||||
$cmd .= " -u '".$device['authname']."'";
|
||||
$cmd .= " -x '".$device['cryptoalgo']."'";
|
||||
$cmd .= " -X '".$device['cryptopass']."'";
|
||||
array_push($cmd, '-u', !empty($device['authname']) ? $device['authname'] : 'root');
|
||||
} elseif ($authlevel === 'authnopriv') {
|
||||
array_push($cmd, '-a', $device['authalgo']);
|
||||
array_push($cmd, '-A', $device['authpass']);
|
||||
array_push($cmd, '-u', $device['authname']);
|
||||
} elseif ($authlevel === 'authpriv') {
|
||||
array_push($cmd, '-a', $device['authalgo']);
|
||||
array_push($cmd, '-A', $device['authpass']);
|
||||
array_push($cmd, '-u', $device['authname']);
|
||||
array_push($cmd, '-x', $device['cryptoalgo']);
|
||||
array_push($cmd, '-X', $device['cryptopass']);
|
||||
} else {
|
||||
if ($debug) {
|
||||
print 'DEBUG: '.$device['snmpver']." : Unsupported SNMPv3 AuthLevel (wtf have you done ?)\n";
|
||||
}
|
||||
d_echo('DEBUG: '.$device['snmpver']." : Unsupported SNMPv3 AuthLevel (wtf have you done ?)\n");
|
||||
}
|
||||
} elseif ($device['snmpver'] === 'v2c' or $device['snmpver'] === 'v1') {
|
||||
$cmd = " -".$device['snmpver'];
|
||||
$cmd .= " -c '".$device['community']."'";
|
||||
} elseif ($device['snmpver'] === 'v2c' || $device['snmpver'] === 'v1') {
|
||||
array_push($cmd, '-' . $device['snmpver'], '-c', $device['community']);
|
||||
} else {
|
||||
if ($debug) {
|
||||
print 'DEBUG: '.$device['snmpver']." : Unsupported SNMP Version (shouldn't be possible to get here)\n";
|
||||
}
|
||||
}//end if
|
||||
d_echo('DEBUG: '.$device['snmpver']." : Unsupported SNMP Version (shouldn't be possible to get here)\n");
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}//end snmp_gen_auth()
|
||||
@@ -832,7 +832,7 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null, $device = array())
|
||||
$lastpart = end($fulloid);
|
||||
|
||||
$cmd = 'snmptranslate -Td -On';
|
||||
$cmd .= mibdir($mibdir, $device);
|
||||
$cmd .= ' -M ' . mibdir($mibdir, $device);
|
||||
$cmd .= ' -m '.$module.' '.$module.'::';
|
||||
$cmd .= $lastpart;
|
||||
|
||||
@@ -912,7 +912,7 @@ function snmp_mib_parse($oid, $mib, $module, $mibdir = null, $device = array())
|
||||
function snmp_mib_walk($mib, $module, $mibdir = null, $device = array())
|
||||
{
|
||||
$cmd = 'snmptranslate -Ts';
|
||||
$cmd .= mibdir($mibdir, $device);
|
||||
$cmd .= ' -M ' . mibdir($mibdir, $device);
|
||||
$cmd .= ' -m '.$module;
|
||||
$result = array();
|
||||
$data = preg_split('/\n+/', shell_exec($cmd));
|
||||
@@ -1008,10 +1008,8 @@ function snmp_mib_translate($oid, $module, $mibdir = null, $device = array())
|
||||
$oid = "$module::$oid";
|
||||
}
|
||||
|
||||
$cmd = 'snmptranslate'.mibdir($mibdir, $device);
|
||||
$cmd .= " -IR -m $module $oid";
|
||||
// load all the MIBs looking for our object
|
||||
$cmd .= ' 2>/dev/null';
|
||||
// load all the MIBs looking for our object (-IR)
|
||||
$cmd = [Config::get('snmptranslate', 'snmptranslate'), '-M', mibdir($mibdir, $device), '-IR', '-m', $module, $oid];
|
||||
// ignore invalid MIBs
|
||||
$lines = preg_split('/\n+/', external_exec($cmd));
|
||||
if (empty($lines)) {
|
||||
@@ -1042,15 +1040,13 @@ function snmp_mib_translate($oid, $module, $mibdir = null, $device = array())
|
||||
* @param string $oid
|
||||
* @param string $mib
|
||||
* @param string $mibdir the mib directory (relative to the LibreNMS mibs directory)
|
||||
* @param string $options Options to pass to snmptranslate
|
||||
* @param array|string $options Options to pass to snmptranslate
|
||||
* @param array $device
|
||||
* @return string
|
||||
*/
|
||||
function snmp_translate($oid, $mib = 'ALL', $mibdir = null, $options = null, $device = array())
|
||||
{
|
||||
$cmd = Config::get('snmptranslate', 'snmptranslate');
|
||||
$cmd .= mibdir($mibdir, $device);
|
||||
$cmd .= " -m $mib";
|
||||
$cmd = [Config::get('snmptranslate', 'snmptranslate'), '-M', mibdir($mibdir, $device), '-m', $mib];
|
||||
|
||||
if (oid_is_numeric($oid)) {
|
||||
$default_options = '-Os';
|
||||
@@ -1061,8 +1057,10 @@ function snmp_translate($oid, $mib = 'ALL', $mibdir = null, $options = null, $de
|
||||
$default_options = '-On';
|
||||
}
|
||||
$options = is_null($options) ? $default_options : $options;
|
||||
$cmd = array_merge($cmd, (array)$options);
|
||||
$cmd[] = $oid;
|
||||
|
||||
return trim(external_exec("$cmd $options $oid 2>/dev/null"));
|
||||
return trim(external_exec($cmd));
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user