1 : <?php
2 :
3 : /**
4 : * PHPIDS
5 : *
6 : * Requirements: PHP5, SimpleXML
7 : *
8 : * Copyright (c) 2007 PHPIDS group (http://php-ids.org)
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; version 2 of the license.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * PHP version 5.1.6+
20 : *
21 : * @category Security
22 : * @package PHPIDS
23 : * @author Mario Heiderich <mario.heiderich@gmail.com>
24 : * @author Christian Matthies <ch0012@gmail.com>
25 : * @author Lars Strojny <lars@strojny.net>
26 : * @license http://www.gnu.org/licenses/lgpl.html LGPL
27 : * @link http://php-ids.org/
28 : */
29 :
30 : /**
31 : * Filter Storage
32 : *
33 : * This class provides various default functions for gathering filter patterns
34 : * to be used later on by the detection mechanism. You might extend this class
35 : * to your requirements.
36 : *
37 : * @category Security
38 : * @package PHPIDS
39 : * @author Christian Matthies <ch0012@gmail.com>
40 : * @author Mario Heiderich <mario.heiderich@gmail.com>
41 : * @author Lars Strojny <lars@strojny.net>
42 : * @copyright 2007 The PHPIDS Group
43 : * @license http://www.gnu.org/licenses/lgpl.html LGPL
44 : * @version Release: $Id:Storage.php 517 2007-09-15 15:04:13Z mario $
45 : * @link http://php-ids.org/
46 : */
47 : class IDS_Filter_Storage
48 : {
49 :
50 : /**
51 : * Filter source file
52 : *
53 : * @var string
54 : */
55 : protected $source = null;
56 :
57 : /**
58 : * Holds caching settings
59 : *
60 : * @var array
61 : */
62 : protected $cacheSettings = null;
63 :
64 : /**
65 : * Cache container
66 : *
67 : * @var object IDS_Caching wrapper
68 : */
69 : protected $cache = null;
70 :
71 : /**
72 : * Filter container
73 : *
74 : * @var array
75 : */
76 : protected $filterSet = array();
77 :
78 : /**
79 : * Constructor
80 : *
81 : * Loads filters based on provided IDS_Init settings.
82 : *
83 : * @param object $init IDS_Init instance
84 : *
85 : * @throws Exception if unsupported filter type is given
86 : * @return void
87 : */
88 : public final function __construct(IDS_Init $init)
89 : {
90 40 : if ($init->config) {
91 :
92 40 : $caching = isset($init->config['Caching']['caching']) ?
93 40 : $init->config['Caching']['caching'] : 'none';
94 :
95 40 : $type = $init->config['General']['filter_type'];
96 40 : $this->source = $init->getBasePath()
97 40 : . $init->config['General']['filter_path'];
98 :
99 40 : if ($caching && $caching != 'none') {
100 40 : $this->cacheSettings = $init->config['Caching'];
101 40 : include_once 'IDS/Caching/Factory.php';
102 40 : $this->cache = IDS_Caching::factory($init, 'storage');
103 40 : }
104 :
105 : switch ($type) {
106 40 : case 'xml' :
107 39 : $this->getFilterFromXML();
108 39 : break;
109 1 : case 'json' :
110 1 : $this->getFilterFromJson();
111 1 : break;
112 : default :
113 : throw new Exception('Unsupported filter type.');
114 : }
115 40 : }
116 40 : }
117 :
118 : /**
119 : * Sets the filter array
120 : *
121 : * @param array $filterSet array containing multiple IDS_Filter instances
122 : *
123 : * @return object $this
124 : */
125 : public final function setFilterSet($filterSet)
126 : {
127 1 : foreach ($filterSet as $filter) {
128 1 : $this->addFilter($filter);
129 1 : }
130 :
131 1 : return $this;
132 : }
133 :
134 : /**
135 : * Returns registered filters
136 : *
137 : * @return array
138 : */
139 : public final function getFilterSet()
140 : {
141 34 : return $this->filterSet;
142 : }
143 :
144 : /**
145 : * Adds a filter
146 : *
147 : * @param object $filter IDS_Filter instance
148 : *
149 : * @return object $this
150 : */
151 : public final function addFilter(IDS_Filter $filter)
152 : {
153 40 : $this->filterSet[] = $filter;
154 40 : return $this;
155 : }
156 :
157 : /**
158 : * Checks if any filters are cached
159 : *
160 : * @return mixed $filters cached filters or false
161 : */
162 : private function _isCached()
163 : {
164 40 : $filters = false;
165 :
166 40 : if ($this->cacheSettings) {
167 :
168 40 : if ($this->cache) {
169 40 : $filters = $this->cache->getCache();
170 40 : }
171 40 : }
172 :
173 40 : return $filters;
174 : }
175 :
176 : /**
177 : * Loads filters from XML using SimpleXML
178 : *
179 : * This function parses the provided source file and stores the result.
180 : * If caching mode is enabled the result will be cached to increase
181 : * the performance.
182 : *
183 : * @throws Exception if problems with fetching the XML data occur
184 : * @return object $this
185 : */
186 : public function getFilterFromXML()
187 : {
188 :
189 39 : if (extension_loaded('SimpleXML')) {
190 :
191 : /*
192 : * See if filters are already available in the cache
193 : */
194 39 : $filters = $this->_isCached();
195 :
196 : /*
197 : * If they aren't, parse the source file
198 : */
199 39 : if (!$filters) {
200 0 : if (file_exists($this->source)) {
201 0 : if (LIBXML_VERSION >= 20621) {
202 0 : $filters = simplexml_load_file($this->source,
203 0 : null,
204 0 : LIBXML_COMPACT);
205 0 : } else {
206 0 : $filters = simplexml_load_file($this->source);
207 : }
208 0 : }
209 0 : }
210 :
211 : /*
212 : * In case we still don't have any filters loaded and exception
213 : * will be thrown
214 : */
215 39 : if (empty($filters)) {
216 0 : throw new Exception(
217 : 'XML data could not be loaded.' .
218 : ' Make sure you specified the correct path.'
219 0 : );
220 : }
221 :
222 : /*
223 : * Now the storage will be filled with IDS_Filter objects
224 : */
225 39 : $data = array();
226 39 : $nocache = $filters instanceof SimpleXMLElement;
227 39 : $filters = $nocache ? $filters->filter : $filters;
228 :
229 39 : include_once 'IDS/Filter.php';
230 :
231 39 : foreach ($filters as $filter) {
232 :
233 39 : $id = $nocache ? (string) $filter->id :
234 39 : $filter['id'];
235 39 : $rule = $nocache ? (string) $filter->rule :
236 39 : $filter['rule'];
237 39 : $impact = $nocache ? (string) $filter->impact :
238 39 : $filter['impact'];
239 39 : $tags = $nocache ? array_values((array) $filter->tags) :
240 39 : $filter['tags'];
241 39 : $description = $nocache ? (string) $filter->description :
242 39 : $filter['description'];
243 :
244 39 : $this->addFilter(new IDS_Filter($id,
245 39 : $rule,
246 39 : $description,
247 39 : (array) $tags[0],
248 39 : (int) $impact));
249 :
250 39 : $data[] = array(
251 39 : 'id' => $id,
252 39 : 'rule' => $rule,
253 39 : 'impact' => $impact,
254 39 : 'tags' => $tags,
255 : 'description' => $description
256 39 : );
257 39 : }
258 :
259 : /*
260 : * If caching is enabled, the fetched data will be cached
261 : */
262 39 : if ($this->cacheSettings) {
263 :
264 39 : $this->cache->setCache($data);
265 39 : }
266 :
267 39 : } else {
268 0 : throw new Exception(
269 : 'SimpleXML not loaded.'
270 0 : );
271 : }
272 :
273 39 : return $this;
274 : }
275 :
276 : /**
277 : * Loads filters from Json file using ext/Json
278 : *
279 : * This function parses the provided source file and stores the result.
280 : * If caching mode is enabled the result will be cached to increase
281 : * the performance.
282 : *
283 : * @throws Exception if problems with fetching the JSON data occur
284 : * @return object $this
285 : */
286 : public function getFilterFromJson()
287 : {
288 :
289 1 : if (extension_loaded('Json')) {
290 :
291 : /*
292 : * See if filters are already available in the cache
293 : */
294 1 : $filters = $this->_isCached();
295 :
296 : /*
297 : * If they aren't, parse the source file
298 : */
299 1 : if (!$filters) {
300 0 : if (file_exists($this->source)) {
301 0 : $filters = json_decode(file_get_contents($this->source));
302 0 : } else {
303 0 : throw new Exception(
304 : 'JSON data could not be loaded.' .
305 : ' Make sure you specified the correct path.'
306 0 : );
307 : }
308 0 : }
309 :
310 1 : if (!$filters) {
311 0 : throw new Exception(
312 : 'JSON data could not be loaded.' .
313 : ' Make sure you specified the correct path.'
314 0 : );
315 : }
316 :
317 : /*
318 : * Now the storage will be filled with IDS_Filter objects
319 : */
320 1 : $data = array();
321 1 : $nocache = !is_array($filters);
322 1 : $filters = $nocache ? $filters->filters->filter : $filters;
323 :
324 1 : include_once 'IDS/Filter.php';
325 :
326 1 : foreach ($filters as $filter) {
327 :
328 1 : $id = $nocache ? (string) $filter->id :
329 1 : $filter['id'];
330 1 : $rule = $nocache ? (string) $filter->rule :
331 1 : $filter['rule'];
332 1 : $impact = $nocache ? (string) $filter->impact :
333 1 : $filter['impact'];
334 1 : $tags = $nocache ? array_values((array) $filter->tags) :
335 1 : $filter['tags'];
336 1 : $description = $nocache ? (string) $filter->description :
337 1 : $filter['description'];
338 :
339 1 : $this->addFilter(new IDS_Filter($id,
340 1 : $rule,
341 1 : $description,
342 1 : (array) $tags[0],
343 1 : (int) $impact));
344 :
345 1 : $data[] = array(
346 1 : 'id' => $id,
347 1 : 'rule' => $rule,
348 1 : 'impact' => $impact,
349 1 : 'tags' => $tags,
350 : 'description' => $description
351 1 : );
352 1 : }
353 :
354 : /*
355 : * If caching is enabled, the fetched data will be cached
356 : */
357 1 : if ($this->cacheSettings) {
358 1 : $this->cache->setCache($data);
359 1 : }
360 :
361 1 : } else {
362 0 : throw new Exception(
363 : 'ext/json not loaded.'
364 0 : );
365 : }
366 :
367 1 : return $this;
368 : }
369 : }
370 :
371 : /*
372 : * Local variables:
373 : * tab-width: 4
374 : * c-basic-offset: 4
375 : * End:
376 : */
|