Ports API: Workaround for ifNames with slashes (#10502)

* Workaround for ifNames with slashes

Basically,

/api/v0/devices/3/ports/0%2f4 -> /api/v0/devices/3/ports/ifName?ifName=0/4
/api/v0/devices/3/ports/0%2f4/port_bits -> /api/v0/devices/3/ports/ifName/port_bits?ifName=0/4

Or you can just use port_id.

* Fix API ports using ifName with slashes
hand parse the path for the ports graph endpoints
this way we can respect the original way of handling slashes (%2F)
This commit is contained in:
Tony Murray
2019-08-12 09:46:36 -05:00
committed by GitHub
parent cec10c1d37
commit f1c67ac5f4
4 changed files with 38 additions and 8 deletions

View File

@@ -74,6 +74,12 @@ function api_get_graph(array $vars)
$auth = '1'; $auth = '1';
$base64_output = ''; $base64_output = '';
// prevent ugly error for undefined graphs from being passed to the user
list($type, $subtype) = extract_graph_type($vars['type']);
if (!is_file(base_path("includes/html/graphs/$type/auth.inc.php"))) {
return api_error(400, 'Invalid graph type');
}
ob_start(); ob_start();
rrdtool_initialize(false); rrdtool_initialize(false);
@@ -117,14 +123,14 @@ function check_port_permission($port_id, $device_id, $callback)
return $callback($port_id); return $callback($port_id);
} }
function get_graph_by_port_hostname(\Illuminate\Http\Request $request) function get_graph_by_port_hostname(\Illuminate\Http\Request $request, $ifname = null, $type = 'port_bits')
{ {
// This will return a graph for a given port by the ifName // This will return a graph for a given port by the ifName
$hostname = $request->route('hostname'); $hostname = $request->route('hostname');
$device_id = ctype_digit($hostname) ? $hostname : getidbyname($hostname); $device_id = ctype_digit($hostname) ? $hostname : getidbyname($hostname);
$vars = [ $vars = [
'port' => $request->route('ifname'), 'port' => $ifname ?: $request->route('ifname'),
'type' => $request->route('type', 'port_bits'), 'type' => $request->route('type', $type),
'output' => $request->get('output', 'display'), 'output' => $request->get('output', 'display'),
'width' => $request->get('width', 1075), 'width' => $request->get('width', 1075),
'height' => $request->get('height', 300), 'height' => $request->get('height', 300),
@@ -149,10 +155,23 @@ function get_graph_by_port_hostname(\Illuminate\Http\Request $request)
function get_port_stats_by_port_hostname(\Illuminate\Http\Request $request) function get_port_stats_by_port_hostname(\Illuminate\Http\Request $request)
{ {
$ifName = $request->route('ifname');
// handle %2f in paths and pass to get_graph_by_port_hostname if needed
if (str_contains($ifName, '/')) {
$parts = explode('/', $request->path());
if (isset($parts[5])) {
$ifName = urldecode($parts[5]);
if (isset($parts[6])) {
return get_graph_by_port_hostname($request, $ifName, $parts[6]);
}
}
}
// This will return port stats based on a devices hostname and ifName // This will return port stats based on a devices hostname and ifName
$hostname = $request->route('hostname'); $hostname = $request->route('hostname');
$device_id = ctype_digit($hostname) ? $hostname : getidbyname($hostname); $device_id = ctype_digit($hostname) ? $hostname : getidbyname($hostname);
$ifName = $request->route('ifname');
$port = dbFetchRow('SELECT * FROM `ports` WHERE `device_id`=? AND `ifName`=? AND `deleted` = 0', [$device_id, $ifName]); $port = dbFetchRow('SELECT * FROM `ports` WHERE `device_id`=? AND `ifName`=? AND `deleted` = 0', [$device_id, $ifName]);
return check_port_permission($port['port_id'], $device_id, function () use ($request, $port) { return check_port_permission($port['port_id'], $device_id, function () use ($request, $port) {

View File

@@ -455,6 +455,18 @@ function generate_entity_link($type, $entity, $text = null, $graph_type = null)
return ($link); return ($link);
}//end generate_entity_link() }//end generate_entity_link()
/**
* Extract type and subtype from a complex graph type, also makes sure variables are file name safe.
* @param string $type
* @return array [type, subtype]
*/
function extract_graph_type($type): array
{
preg_match('/^(?P<type>[A-Za-z0-9]+)_(?P<subtype>.+)/', $type, $graphtype);
$type = basename($graphtype['type']);
$subtype = basename($graphtype['subtype']);
return [$type, $subtype];
}
function generate_port_link($port, $text = null, $type = null, $overlib = 1, $single_graph = 0) function generate_port_link($port, $text = null, $type = null, $overlib = 1, $single_graph = 0)
{ {

View File

@@ -7,9 +7,7 @@ foreach ($_GET as $name => $value) {
$vars[$name] = $value; $vars[$name] = $value;
} }
preg_match('/^(?P<type>[A-Za-z0-9]+)_(?P<subtype>.+)/', $vars['type'], $graphtype); list($type, $subtype) = extract_graph_type($vars['type']);
$type = basename($graphtype['type']);
$subtype = basename($graphtype['subtype']);
if (is_numeric($vars['device'])) { if (is_numeric($vars['device'])) {
$device = device_by_id_cache($vars['device']); $device = device_by_id_cache($vars['device']);

View File

@@ -91,7 +91,8 @@ Route::group(['prefix' => 'v0', 'namespace' => '\App\Api\Controllers'], function
Route::get('{hostname}/port_stack', 'LegacyApiController@get_port_stack')->name('get_port_stack'); Route::get('{hostname}/port_stack', 'LegacyApiController@get_port_stack')->name('get_port_stack');
Route::get('{hostname}/components', 'LegacyApiController@get_components')->name('get_components'); Route::get('{hostname}/components', 'LegacyApiController@get_components')->name('get_components');
Route::get('{hostname}/groups', 'LegacyApiController@get_device_groups')->name('get_device_groups'); Route::get('{hostname}/groups', 'LegacyApiController@get_device_groups')->name('get_device_groups');
Route::get('{hostname}/ports/{ifname}', 'LegacyApiController@get_port_stats_by_port_hostname')->name('get_port_stats_by_port_hostname'); // consumes the route below, but passes to it when detected
Route::get('{hostname}/ports/{ifname}', 'LegacyApiController@get_port_stats_by_port_hostname')->name('get_port_stats_by_port_hostname')->where('ifname', '.*');
Route::get('{hostname}/ports/{ifname}/{type}', 'LegacyApiController@get_graph_by_port_hostname')->name('get_graph_by_port_hostname'); Route::get('{hostname}/ports/{ifname}/{type}', 'LegacyApiController@get_graph_by_port_hostname')->name('get_graph_by_port_hostname');
Route::get('{hostname}/{type}', 'LegacyApiController@get_graph_generic_by_hostname')->name('get_graph_generic_by_hostname'); Route::get('{hostname}/{type}', 'LegacyApiController@get_graph_generic_by_hostname')->name('get_graph_generic_by_hostname');