%PDF- %PDF-
| Direktori : /proc/self/root/backups/router/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/ |
| Current File : //proc/self/root/backups/router/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/Alias.php |
<?php
/**
* Copyright (C) 2018 Deciso B.V.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Firewall;
use OPNsense\Base\BaseModel;
use OPNsense\Core\Config;
use OPNsense\Firewall\Util;
use OPNsense\Base\Messages\Message;
/**
* Class Alias
* @package OPNsense\Firewall
*/
class Alias extends BaseModel
{
/**
* cache iteration items
*/
private $aliasIteratorCache = [];
private $skip_dynamic_info = false;
/**
* return if we're lazy loaded
*/
public function skipDynamicInfo()
{
return $this->skip_dynamic_info;
}
/**
* alias name cache
*/
private $aliasReferenceCache = [];
public function __construct($skip_dynamic_info = false)
{
$this->skip_dynamic_info = $skip_dynamic_info;
parent::__construct();
}
public function performValidation($validateFullModel = false)
{
$messages = parent::performValidation($validateFullModel);
foreach ($this->aliases->alias->iterateItems() as $alias) {
if (!$validateFullModel && !$alias->isFieldChanged()) {
continue;
}
$ref = $alias->__reference;
$username = (string)$alias->username;
$password = (string)$alias->password;
switch ((string)$alias->authtype) {
case 'Basic':
if (empty($username) || empty($password)) {
$messages->appendMessage(new Message(gettext('Please provide a username and password when Basic auth is selected'), $ref . '.authtype'));
}
break;
case 'Bearer':
if (empty($password)) {
$messages->appendMessage(new Message(gettext('Please provide an API token when Bearer auth is selected'), $ref . '.authtype'));
} elseif (strlen($password) > 512) {
$messages->appendMessage(new Message(gettext('Invalid token length'), $ref . '.authtype'));
} elseif (!preg_match('/^[A-Za-z0-9-_.]+$/', $password)) {
$messages->appendMessage(new Message(gettext('Illegal characters in token'), $ref . '.authtype'));
}
break;
}
}
return $messages;
}
/**
* return locations where aliases can be used inside the configuration
* @return array alias source map
*/
private function getAliasSource()
{
$sources = [];
$sources[] = [['filter', 'rule'], ['source', 'address']];
$sources[] = [['filter', 'rule'], ['destination', 'address']];
$sources[] = [['filter', 'rule'], ['source', 'port']];
$sources[] = [['filter', 'rule'], ['destination', 'port']];
$sources[] = [['filter', 'scrub', 'rule'], ['dst']];
$sources[] = [['filter', 'scrub', 'rule'], ['src']];
$sources[] = [['filter', 'scrub', 'rule'], ['dstport']];
$sources[] = [['filter', 'scrub', 'rule'], ['srcport']];
$sources[] = [['nat', 'rule'], ['source', 'address']];
$sources[] = [['nat', 'rule'], ['source', 'port']];
$sources[] = [['nat', 'rule'], ['destination', 'address']];
$sources[] = [['nat', 'rule'], ['destination', 'port']];
$sources[] = [['nat', 'rule'], ['target']];
$sources[] = [['nat', 'rule'], ['local-port']];
$sources[] = [['nat', 'onetoone'], ['destination', 'address']];
$sources[] = [['nat', 'outbound', 'rule'], ['source', 'network']];
$sources[] = [['nat', 'outbound', 'rule'], ['sourceport']];
$sources[] = [['nat', 'outbound', 'rule'], ['destination', 'network']];
$sources[] = [['nat', 'outbound', 'rule'], ['dstport']];
$sources[] = [['nat', 'outbound', 'rule'], ['target']];
$sources[] = [['staticroutes', 'route'], ['network']];
// os-firewall plugin paths
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'rules', 'rule'], ['source_net']];
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'rules', 'rule'], ['source_port']];
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'rules', 'rule'], ['destination_net']];
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'rules', 'rule'], ['destination_port']];
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'snatrules', 'rule'], ['source_net']];
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'snatrules', 'rule'], ['source_port']];
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'snatrules', 'rule'], ['destination_net']];
$sources[] = [['OPNsense', 'Firewall', 'Filter', 'snatrules', 'rule'], ['destination_port']];
return $sources;
}
/**
* search configuration items where the requested alias is used
* @param $name alias name
* @return \Generator [reference, confignode, matched item]
*/
private function searchConfig($name)
{
$cfgObj = Config::getInstance()->object();
foreach ($this->getAliasSource() as $aliasref) {
$cfgsection = $cfgObj;
foreach ($aliasref[0] as $cfgName) {
if ($cfgsection != null) {
$cfgsection = $cfgsection->$cfgName;
}
}
if ($cfgsection != null) {
$nodeidx = 0;
foreach ($cfgsection as $inode) {
$node = $inode;
foreach ($aliasref[1] as $cfgName) {
$node = $node->$cfgName;
}
if ((string)$node == $name) {
$ref = implode('.', $aliasref[0]) . "." . $nodeidx . "/" . implode('.', $aliasref[1]);
yield array($ref, &$inode, &$node);
}
$nodeidx++;
}
}
}
}
/**
* flush cached objects and references
*/
public function flushCache()
{
$this->aliasIteratorCache = [];
$this->aliasReferenceCache = [];
}
/**
* Return all places an alias seems to be used
* @param string $name alias name
* @return array hashmap with references where this alias is used
*/
public function whereUsed($name)
{
$result = array();
// search legacy locations
foreach ($this->searchConfig($name) as $item) {
$result[$item[0]] = (string)$item[1]->descr;
}
// find all used in this model
foreach ($this->aliases->alias->iterateItems() as $alias) {
if (!in_array($alias->type, array('geoip', 'urltable'))) {
$nodeData = $alias->content->getNodeData();
if (isset($nodeData[$name])) {
if (!empty($alias->description)) {
$result[(string)$alias->__reference] = (string)$alias->description;
} else {
$result[(string)$alias->__reference] = (string)$alias->name;
}
}
}
}
return $result;
}
/**
* replace alias usage
* @param $oldname
* @param $newname
*/
public function refactor($oldname, $newname)
{
Util::attachAliasObject($this);
// replace in legacy config
foreach ($this->searchConfig($oldname) as $item) {
$item[2][0] = $newname;
}
// find all used in this model (alias nesting)
foreach ($this->aliases->alias->iterateItems() as $alias) {
if (!in_array($alias->type, array('geoip', 'urltable'))) {
$sepchar = $alias->content->getSeparatorChar();
$aliases = explode($sepchar, (string)$alias->content);
if (in_array($oldname, $aliases)) {
$aliases = array_unique($aliases);
$aliases[array_search($oldname, $aliases)] = $newname;
$alias->content->setValue(implode($sepchar, $aliases));
}
}
}
}
/**
* return aliases as array
* @param $flush flush cached objects from previous call
* @return Generator with aliases
*/
public function aliasIterator($flush = false)
{
if ($flush) {
// flush cache
$this->aliasIteratorCache = [];
}
foreach ($this->aliases->alias->iterateItems() as $uuid => $alias) {
if (empty($this->aliasIteratorCache[$uuid])) {
$this->aliasIteratorCache[$uuid] = [];
foreach ($alias->iterateItems() as $key => $value) {
$this->aliasIteratorCache[$uuid][$key] = (string)$value;
}
// parse content into separate items for easier reading. items are separated by \n
if ((string)$alias->content == "") {
$this->aliasIteratorCache[$uuid]['content'] = [];
} else {
$this->aliasIteratorCache[$uuid]['content'] = explode("\n", (string)$alias->content);
}
}
yield $this->aliasIteratorCache[$uuid];
}
}
public function getByName($name, $flush = false)
{
if ($flush) {
// Flush cache in case model data has been changed.
$this->aliasReferenceCache = [];
}
if (empty($this->aliasReferenceCache)) {
// cache alias uuid references, but always validate existence before return.
foreach ($this->aliases->alias->iterateItems() as $uuid => $alias) {
$this->aliasReferenceCache[(string)$alias->name] = $alias;
}
}
if (isset($this->aliasReferenceCache[$name])) {
return $this->aliasReferenceCache[$name];
} else {
return null;
}
}
}