Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
hostrestriction.php
1<?php
9namespace Bitrix\Security;
10
19
27{
28 const ACTION_REDIRECT = 'redirect';
29 const ACTION_STOP = 'stop';
30
31 private $optionPrefix = 'restriction_hosts_';
32 private $cacheInitPath = 'security';
33 private $cacheId = 'restriction_hosts';
34 private $cacheTtl = 31536000; //one year
35 private $action = 'stop';
36 private $actionOptions = array();
37 private $isLogNeeded = true;
38 private $hosts = null;
39 private $validActions = array(
40 self::ACTION_REDIRECT,
41 self::ACTION_STOP
42 );
43 private $validationRegExp = null;
44 private $isActive = null;
45
51 public static function onPageStart()
52 {
53 if (\CSecuritySystemInformation::isCliMode())
54 return;
55
57 $instance = new static;
58 $instance->process();
59 }
60
61 public function __construct()
62 {
63 $this->hosts = Config\Option::get('security', $this->optionPrefix.'hosts', '');
64 $this->action = Config\Option::get('security', $this->optionPrefix.'action', '');
65 $this->actionOptions = unserialize(Config\Option::get('security', $this->optionPrefix.'action_options', '{}'), ['allowed_classes' => false]);
66 $this->isLogNeeded = Config\Option::get('security', $this->optionPrefix.'logging', false);
67 }
68
75 public function process($host = null)
76 {
77 if (is_null($host))
78 $host = $this->getTargetHost();
79
80 if ($this->isValidHost($host))
81 return $this;
82
83 if ($this->isLogNeeded)
84 $this->log($host);
85
86 $this->doActions();
87
88 return $this;
89 }
90
98 public function isValidHost($host)
99 {
100 if (is_string($host) && $host !== '')
101 {
102 $count = 0;
103 preg_replace($this->getValidationRegExp(), '', $host, 1, $count);
104 //var_dump($count);
105 if ($count)
106 {
107 return true;
108 }
109 }
110 return false;
111 }
112
116 public function getProperties()
117 {
118 return array(
119 'hosts' => $this->hosts,
120 'current_host' => $this->getTargetHost(),
121 'action' => $this->action,
122 'action_options' => $this->actionOptions,
123 'logging' => $this->isLogNeeded,
124 'active' => is_null($this->isActive)? $this->getActive(): $this->isActive
125 );
126 }
127
143 public function setProperties(array $properties)
144 {
145 if (isset($properties['hosts']))
146 {
147 $this->setHosts($properties['hosts']);
148 }
149
150 if (isset($properties['action']))
151 {
152 if (isset($properties['action_options']))
153 {
154 $this->setAction($properties['action'], $properties['action_options']);
155 }
156 else
157 {
158 $this->setAction($properties['action']);
159 }
160 }
161
162 if (isset($properties['logging']))
163 {
164 $this->setLogging($properties['logging']);
165 }
166
167 if (isset($properties['active']))
168 {
169 $this->setActive($properties['active']);
170 }
171
172 return $this;
173 }
174
178 public function getAction()
179 {
180 return $this->action;
181 }
182
186 public function getActionOptions()
187 {
188 return $this->actionOptions;
189 }
190
202 public function setAction($action, array $options = array())
203 {
204 if (!$action)
205 throw new ArgumentNullException('action');
206
207 if (!is_string($action))
208 throw new ArgumentTypeException('action', 'string');
209
210 if (!in_array($action, $this->validActions))
211 throw new ArgumentOutOfRangeException('action', $this->validActions);
212
213 if ($action === self::ACTION_REDIRECT)
214 {
215 if (!isset($options['host']) || !$options['host'])
216 throw new LogicException('options[host] not present', 'SECURITY_HOSTS_EMPTY_HOST_ACTION');
217
218 if (!preg_match('#^https?://#', $options['host']))
219 throw new LogicException('invalid redirecting host present in options[host]', 'SECURITY_HOSTS_INVALID_HOST_ACTION');
220 }
221
222
223 $this->action = $action;
224 $this->actionOptions = $options;
225
226 return $this;
227 }
228
232 public function getLogging()
233 {
234 return $this->isLogNeeded;
235 }
236
244 public function setLogging($isLogNeeded = true)
245 {
246 if (!is_bool($isLogNeeded))
247 throw new ArgumentTypeException('isLogNeeded', 'bool');
248
249 $this->isLogNeeded = $isLogNeeded;
250
251 return $this;
252 }
253
257 public function getActive()
258 {
259 if (is_null($this->isActive))
260 $this->isActive = $this->isBound();
261
262 return $this->isActive;
263 }
264
272 public function setActive($isActive = false)
273 {
274 if (!is_bool($isActive))
275 throw new ArgumentTypeException('isActive', 'bool');
276
277 $this->isActive = $isActive;
278
279 return $this;
280 }
281
285 public function getHosts()
286 {
287 return $this->hosts;
288 }
289
299 public function setHosts($hosts, $ignoreChecking = false)
300 {
301 if (!is_string($hosts))
302 throw new ArgumentTypeException('host', 'string');
303
304 if (!$ignoreChecking)
305 $this->checkNewHosts($hosts);
306
307 $this->hosts = $hosts;
308
309 return $this;
310 }
311
318 public function getValidationRegExp()
319 {
320 if ($this->validationRegExp === null)
321 {
322 $cache = Data\Cache::createInstance();
323 if($cache->initCache($this->cacheTtl, $this->cacheId, $this->cacheInitPath) )
324 {
325 $this->validationRegExp = $cache->getVars();
326 }
327 else
328 {
329 $this->validationRegExp = $this->genValidationRegExp($this->hosts);
330 $cache->startDataCache();
331 $cache->endDataCache($this->validationRegExp);
332 }
333 }
334
335 return $this->validationRegExp;
336 }
337
343 public function save()
344 {
345 Config\Option::set('security', $this->optionPrefix.'hosts', $this->hosts, '');
346 Config\Option::set('security', $this->optionPrefix.'action', $this->action, '');
347 Config\Option::set('security', $this->optionPrefix.'action_options', serialize($this->actionOptions), '');
348 Config\Option::set('security', $this->optionPrefix.'logging', $this->isLogNeeded, '');
349 if (!is_null($this->isActive))
350 {
351
352 if ($this->isActive)
353 {
354 EventManager::getInstance()
355 ->registerEventHandler('main', 'OnPageStart', 'security', get_class($this), 'onPageStart');
356 }
357 else
358 {
359 EventManager::getInstance()
360 ->unRegisterEventHandler('main', 'OnPageStart', 'security', get_class($this), 'onPageStart');
361 }
362 }
363 Data\Cache::createInstance()->clean($this->cacheId, $this->cacheInitPath);
364
365 return $this;
366 }
367
373 protected function isBound()
374 {
375 $handlers = EventManager::getInstance()->findEventHandlers('main', 'OnPageStart', array('security'));
376
377 foreach($handlers as $handler)
378 {
379 if ($handler['TO_CLASS'] === get_class($this))
380 return true;
381 }
382
383 return false;
384 }
385
391 protected function getTargetHost()
392 {
393 static $host = null;
394 if (is_null($host))
395 $host = Context::getCurrent()->getServer()->getHttpHost();
396
397 return $host;
398 }
399
406 protected function log($host)
407 {
408 return \CSecurityEvent::getInstance()->doLog('SECURITY', 'SECURITY_HOST_RESTRICTION', 'HTTP_HOST', $host);
409 }
410
416 protected function doActions()
417 {
418 switch($this->action)
419 {
422 include Loader::getLocal('/admin/security_403.php');
423 die();
424 break;
426 localRedirect($this->actionOptions['host'], true);
427 break;
428 default:
429 trigger_error('Unknown action', E_USER_WARNING);
430 }
431
432 return $this;
433 }
434
441 protected function genValidationRegExp($hosts)
442 {
443 $hosts = preg_replace('/#.*/', '', $hosts);
444 $hosts = trim($hosts, " \t\n\r");
445 $hosts = preg_quote($hosts);
446 $hosts = preg_replace('~\\\\\*~', '.*', $hosts);
447 $hosts = preg_split('~\s+~s', $hosts);
448
449 foreach ($hosts as $i => $host)
450 {
451 $hosts[$i] = "#^\s*($host)(:\d+)?\s*$#iD";
452 }
453 return $hosts;
454 }
455
463 protected function checkNewHosts($hosts)
464 {
465 $this->validationRegExp = $this->genValidationRegExp($hosts);
466
467 $count = 0;
468 preg_replace($this->validationRegExp, '', $this->getTargetHost(), 1, $count);
469 if (!$count)
470 throw new LogicException('Current host blocked', 'SECURITY_HOSTS_SELF_BLOCK');
471
472 $count = 0;
473 preg_replace($this->validationRegExp, '', 'some-invalid-host.com', 1, $count);
474 if ($count)
475 throw new LogicException('Any host passed restrictions', 'SECURITY_HOSTS_ANY_HOST');
476
477 return $this;
478 }
479}
static getCurrent()
Definition context.php:241
setHosts($hosts, $ignoreChecking=false)
setAction($action, array $options=array())