diff options
| author | Peter Wu | 2014-07-20 23:30:49 +0200 |
|---|---|---|
| committer | Peter Wu | 2014-07-20 23:30:49 +0200 |
| commit | 4a737bc1abdbef7e0698b006704a26583a4c61df (patch) | |
| tree | 7d5f51f76acd43d1aeda601dd7201e2c158bdae4 /type/Base.class.php | |
| parent | security: Add missing input validation for plugin (diff) | |
| download | apt-panopticon_cgp-4a737bc1abdbef7e0698b006704a26583a4c61df.zip apt-panopticon_cgp-4a737bc1abdbef7e0698b006704a26583a4c61df.tar.gz apt-panopticon_cgp-4a737bc1abdbef7e0698b006704a26583a4c61df.tar.bz2 apt-panopticon_cgp-4a737bc1abdbef7e0698b006704a26583a4c61df.tar.xz | |
Use a more secure command line building method
Previously, a command is built by string concatenation. Here, the
distinction between a value and multiple params got lost. Solve this
by using an array for shell arguments. As the escaping is now removed
from the `rrd_gen_graph` function, the canvas style needs to manually
add those quotes to make the JS code still work. That only supports
double-quotes, so hopefully nobody creates a name with a double quote
as that would break the fragile JS command line parser.
Separate the rrdtool options from the rrdtool graph command to make the
`$graph_type == 'canvas'` option work (it would otherwise not understand
the `rrdtool graph - -a PNG` option).
Merge the SVG and PNG cases as they are the same except for the
Content-Type header.
Fix a missing html escape in a debug style.
Diffstat (limited to 'type/Base.class.php')
| -rw-r--r-- | type/Base.class.php | 104 |
1 files changed, 61 insertions, 43 deletions
diff --git a/type/Base.class.php b/type/Base.class.php index 1f42f4f..72ce437 100644 --- a/type/Base.class.php +++ b/type/Base.class.php | |||
| @@ -36,8 +36,14 @@ class Type_Base { | |||
| 36 | function __construct($config, $_get) { | 36 | function __construct($config, $_get) { |
| 37 | $this->datadir = $config['datadir']; | 37 | $this->datadir = $config['datadir']; |
| 38 | $this->rrdtool = $config['rrdtool']; | 38 | $this->rrdtool = $config['rrdtool']; |
| 39 | if (!empty($config['rrdtool_opts'])) | 39 | if (!empty($config['rrdtool_opts'])) { |
| 40 | $this->rrdtool_opts[] = $config['rrdtool_opts']; | 40 | if (is_array($config['rrdtool_opts'])) { |
| 41 | $this->rrdtool_opts = $config['rrdtool_opts']; | ||
| 42 | } else { | ||
| 43 | $this->rrdtool_opts = explode(' ', | ||
| 44 | $config['rrdtool_opts']); | ||
| 45 | } | ||
| 46 | } | ||
| 41 | $this->cache = $config['cache']; | 47 | $this->cache = $config['cache']; |
| 42 | $this->parse_get($_get); | 48 | $this->parse_get($_get); |
| 43 | $this->rrd_title = sprintf( | 49 | $this->rrd_title = sprintf( |
| @@ -200,78 +206,90 @@ class Type_Base { | |||
| 200 | $this->rainbow_colors(); | 206 | $this->rainbow_colors(); |
| 201 | $this->colors = $colors + $this->colors; | 207 | $this->colors = $colors + $this->colors; |
| 202 | 208 | ||
| 203 | $graphdata = $this->rrd_gen_graph(); | 209 | $graphoptions = $this->rrd_gen_graph(); |
| 210 | # $shellcmd contains escaped rrdtool arguments | ||
| 211 | $shellcmd = array(); | ||
| 212 | foreach ($graphoptions as $arg) | ||
| 213 | $shellcmd[] = escapeshellarg($arg); | ||
| 204 | 214 | ||
| 205 | $style = $debug !== false ? $debug : $this->graph_type; | 215 | $style = $debug !== false ? $debug : $this->graph_type; |
| 206 | switch ($style) { | 216 | switch ($style) { |
| 207 | case 'cmd': | 217 | case 'cmd': |
| 208 | print '<pre>'; | 218 | print '<pre>'; |
| 209 | foreach ($graphdata as $d) { | 219 | foreach ($shellcmd as $d) { |
| 210 | printf("%s \\\n", htmlentities($d)); | 220 | printf("%s \\\n", htmlentities($d)); |
| 211 | } | 221 | } |
| 212 | print '</pre>'; | 222 | print '</pre>'; |
| 213 | break; | 223 | break; |
| 214 | case 'canvas': | 224 | case 'canvas': |
| 215 | printf('<canvas id="%s" class="rrd">', sha1(serialize($graphdata))); | 225 | printf('<canvas id="%s" class="rrd">', sha1(serialize($graphoptions))); |
| 216 | foreach ($graphdata as $d) { | 226 | foreach ($graphoptions as $d) { |
| 217 | printf("%s\n", htmlentities($d)); | 227 | printf("\"%s\"\n", htmlentities($d)); |
| 218 | } | 228 | } |
| 219 | print '</canvas>'; | 229 | print '</canvas>'; |
| 220 | break; | 230 | break; |
| 221 | case 'debug': | 231 | case 'debug': |
| 222 | case 1: | 232 | case 1: |
| 223 | print '<pre>'; | 233 | print '<pre>'; |
| 224 | print_r($graphdata); | 234 | htmlentities(print_r($shellcmd, TRUE)); |
| 225 | print '</pre>'; | 235 | print '</pre>'; |
| 226 | break; | 236 | break; |
| 227 | case 'svg': | 237 | case 'svg': |
| 228 | # caching | ||
| 229 | if (is_numeric($this->cache) && $this->cache > 0) | ||
| 230 | header("Expires: " . date(DATE_RFC822,strtotime($this->cache." seconds"))); | ||
| 231 | header("content-type: image/svg+xml"); | ||
| 232 | $graphdata = implode(' ', $graphdata); | ||
| 233 | echo `$graphdata`; | ||
| 234 | break; | ||
| 235 | case 'png': | 238 | case 'png': |
| 236 | default: | 239 | default: |
| 237 | # caching | 240 | # caching |
| 238 | if (is_numeric($this->cache) && $this->cache > 0) | 241 | if (is_numeric($this->cache) && $this->cache > 0) |
| 239 | header("Expires: " . date(DATE_RFC822,strtotime($this->cache." seconds"))); | 242 | header("Expires: " . date(DATE_RFC822,strtotime($this->cache." seconds"))); |
| 240 | header("content-type: image/png"); | 243 | |
| 241 | $graphdata = implode(' ', $graphdata); | 244 | if ($style === 'svg') |
| 242 | echo `$graphdata`; | 245 | header("content-type: image/svg+xml"); |
| 246 | else | ||
| 247 | header("content-type: image/png"); | ||
| 248 | |||
| 249 | $shellcmd = array_merge( | ||
| 250 | $this->rrd_graph_command($style), | ||
| 251 | $shellcmd | ||
| 252 | ); | ||
| 253 | $shellcmd = implode(' ', $shellcmd); | ||
| 254 | passthru($shellcmd); | ||
| 243 | break; | 255 | break; |
| 244 | } | 256 | } |
| 245 | } | 257 | } |
| 246 | 258 | ||
| 259 | function rrd_graph_command($imgformat) { | ||
| 260 | if (!in_array($imgformat, array('png', 'svg'))) | ||
| 261 | $imgformat = 'png'; | ||
| 262 | |||
| 263 | return array( | ||
| 264 | $this->rrdtool, | ||
| 265 | 'graph', | ||
| 266 | '-', | ||
| 267 | '-a', strtoupper($imgformat) | ||
| 268 | ); | ||
| 269 | } | ||
| 270 | |||
| 247 | function rrd_options() { | 271 | function rrd_options() { |
| 248 | switch ($this->graph_type) { | 272 | $rrdgraph = array(); |
| 249 | case 'png': | 273 | foreach($this->rrdtool_opts as $opt) |
| 250 | case 'hybrid': | 274 | $rrdgraph[] = $opt; |
| 251 | $rrdgraph[] = $this->rrdtool; | ||
| 252 | $rrdgraph[] = 'graph - -a PNG'; | ||
| 253 | break; | ||
| 254 | case 'svg': | ||
| 255 | $rrdgraph[] = $this->rrdtool; | ||
| 256 | $rrdgraph[] = 'graph - -a SVG'; | ||
| 257 | break; | ||
| 258 | default: | ||
| 259 | break; | ||
| 260 | } | ||
| 261 | if (!empty($this->rrdtool_opts)) | ||
| 262 | foreach($this->rrdtool_opts as $opt) | ||
| 263 | $rrdgraph[] = $opt; | ||
| 264 | if ($this->graph_smooth) | 275 | if ($this->graph_smooth) |
| 265 | $rrdgraph[] = '-E'; | 276 | $rrdgraph[] = '-E'; |
| 266 | if ($this->base) | 277 | if ($this->base) { |
| 267 | $rrdgraph[] = '--base '.$this->base; | 278 | $rrdgraph[] = '--base'; |
| 268 | $rrdgraph[] = sprintf('-w %d', is_numeric($this->width) ? $this->width : 400); | 279 | $rrdgraph[] = $this->base; |
| 269 | $rrdgraph[] = sprintf('-h %d', is_numeric($this->height) ? $this->height : 175); | 280 | } |
| 270 | $rrdgraph[] = '-l 0'; | 281 | $rrdgraph = array_merge($rrdgraph, array( |
| 271 | $rrdgraph[] = sprintf('-t "%s on %s"', $this->rrd_title, $this->args['host']); | 282 | '-w', is_numeric($this->width) ? $this->width : 400, |
| 272 | if ($this->rrd_vertical) | 283 | '-h', is_numeric($this->height) ? $this->height : 175, |
| 273 | $rrdgraph[] = sprintf('-v "%s"', $this->rrd_vertical); | 284 | '-l', '0', |
| 274 | $rrdgraph[] = sprintf('-s e-%d', is_numeric($this->seconds) ? $this->seconds : 86400); | 285 | '-t', "{$this->rrd_title} on {$this->args['host']}" |
| 286 | )); | ||
| 287 | if ($this->rrd_vertical) { | ||
| 288 | $rrdgraph[] = '-v'; | ||
| 289 | $rrdgraph[] = $this->rrd_vertical; | ||
| 290 | } | ||
| 291 | $rrdgraph[] = '-s'; | ||
| 292 | $rrdgraph[] = sprintf('e-%d', is_numeric($this->seconds) ? $this->seconds : 86400); | ||
| 275 | 293 | ||
| 276 | return $rrdgraph; | 294 | return $rrdgraph; |
| 277 | } | 295 | } |
