aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/type/Base.class.php
diff options
context:
space:
mode:
authorPeter Wu2014-07-20 23:30:49 +0200
committerPeter Wu2014-07-20 23:30:49 +0200
commit4a737bc1abdbef7e0698b006704a26583a4c61df (patch)
tree7d5f51f76acd43d1aeda601dd7201e2c158bdae4 /type/Base.class.php
parentsecurity: Add missing input validation for plugin (diff)
downloadapt-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.php104
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 }