%PDF- %PDF-
Direktori : /backups/router/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ |
Current File : //backups/router/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ClientController.php |
<?php /* * Copyright (C) 2023 Deciso B.V. * Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com> * 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\Wireguard\Api; use OPNsense\Base\ApiMutableModelControllerBase; use OPNsense\Core\Config; use OPNsense\Wireguard\Server; use OPNsense\Core\Backend; use OPNsense\Firewall\Util; class ClientController extends ApiMutableModelControllerBase { protected static $internalModelName = 'client'; protected static $internalModelClass = '\OPNsense\Wireguard\Client'; public function pskAction() { return ['psk' => trim((new Backend())->configdRun('wireguard gen_psk')), 'status' => 'ok' ]; } public function listServersAction() { if ($this->request->isGet()) { $results = ['rows' => [], 'status' => 'ok']; foreach ((new Server())->servers->server->iterateItems() as $key => $node) { $results['rows'][] = [ 'uuid' => $key, 'name' => (string)$node->name ]; } return $results; } return ['status' => 'failed']; } public function searchClientAction() { $servers = $this->request->get('servers'); $filter_funct = function ($record) use ($servers) { return empty($servers) || array_intersect(explode(',', $record->servers), $servers); }; return $this->searchBase( 'clients.client', ["enabled", "name", "pubkey", "tunneladdress", "serveraddress", "serverport", "servers"], null, $filter_funct ); } public function getClientAction($uuid = null) { return $this->getBase('client', 'clients.client', $uuid); } public function addClientAction() { return $this->setClientAction(null); } public function delClientAction($uuid) { if ($this->request->isPost()) { Config::getInstance()->lock(); $mdl = new Server(); foreach ($mdl->servers->server->iterateItems() as $key => $node) { $peers = array_filter(explode(',', (string)$node->peers)); if (in_array($uuid, $peers)) { $node->peers = implode(',', array_diff($peers, [$uuid])); } } $mdl->serializeToConfig(false, true); } return $this->delBase('clients.client', $uuid); } public function setClientAction($uuid) { $add_uuid = null; if (!empty($this->request->getPost(static::$internalModelName)) && $this->request->isPost()) { $servers = []; if (!empty($this->request->getPost(static::$internalModelName)['servers'])) { $servers = explode(',', $this->request->getPost(static::$internalModelName)['servers']); } Config::getInstance()->lock(); $mdl = new Server(); if (empty($uuid)) { // add new client, generate uuid $uuid = $mdl->servers->generateUUID(); $add_uuid = $uuid; } foreach ($mdl->servers->server->iterateItems() as $key => $node) { $peers = array_filter(explode(',', (string)$node->peers)); if (in_array($uuid, $peers) && !in_array($key, $servers)) { $node->peers = implode(',', array_diff($peers, [$uuid])); } elseif (!in_array($uuid, $peers) && in_array($key, $servers)) { $node->peers = implode(',', array_merge($peers, [$uuid])); } } /** * Save to in memory model. * Ignore validations as $uuid might be new or trigger an existing validation issue. * Persisting the data is handled by setBase() */ $mdl->serializeToConfig(false, true); } $result = $this->setBase('client', 'clients.client', $uuid); if (!empty($add_uuid) && $result['result'] == 'saved') { $result['uuid'] = $add_uuid; } return $result; } public function toggleClientAction($uuid) { return $this->toggleBase('clients.client', $uuid); } public function getClientBuilderAction() { return $this->getBase('configbuilder', 'clients.client', null); } public function addClientBuilderAction() { $uuid = null; if ($this->request->isPost() && !empty($this->request->getPost('configbuilder'))) { Config::getInstance()->lock(); $mdl = new Server(); $uuid = $this->getModel()->clients->generateUUID(); $server = $this->request->getPost('configbuilder')['server']; foreach ($mdl->servers->server->iterateItems() as $key => $node) { if ($key == $server) { $peers = array_filter(explode(',', (string)$node->peers)); $node->peers = implode(',', array_merge($peers, [$uuid])); break; } } /** * Save to in memory model. * Ignore validations as $uuid might be new or trigger an existing validation issue. * Persisting the data is handled by setBase() */ $mdl->serializeToConfig(false, true); } return $this->setBase('configbuilder', 'clients.client', $uuid); } public function getServerInfoAction($uuid = null) { $result = ['status' => 'failed']; if ($this->request->isGet()) { $peers = []; $subnets = []; $used_addresses = []; /* We cleanse addresses before storing here, to allow string matching */ foreach ((new Server())->servers->server->iterateItems() as $key => $node) { if ($key == $uuid) { $peers = array_filter(explode(',', (string)$node->peers)); $result['endpoint'] = (string)$node->endpoint; $result['peer_dns'] = (string)$node->peer_dns; $result['mtu'] = (string)$node->mtu; $result['pubkey'] = (string)$node->pubkey; foreach (array_filter(explode(',', (string)$node->tunneladdress)) as $addr) { $proto = str_contains($addr, ':') ? 'inet6' : 'inet'; if (!isset($subnets[$proto])) { $subnets[$proto] = $addr; } $used_addresses[] = inet_ntop(inet_pton(explode('/', $addr)[0])); } foreach ($peers as $peer) { $this_peer = $this->getModel()->getNodeByReference('clients.client.' . $peer); if ($this_peer != null) { foreach (array_filter(explode(',', (string)$this_peer->tunneladdress)) as $addr) { $used_addresses[] = inet_ntop(inet_pton(explode('/', $addr)[0])); } } } $tunneladdress = []; foreach ($subnets as $cidr) { foreach (Util::cidrRangeIterator($cidr) as $addr) { if (!in_array($addr, $used_addresses)) { $netmask = str_contains($addr, ':') ? '128' : '32'; $tunneladdress[] = $addr . '/' . $netmask; break; } } } $result['address'] = implode(',', $tunneladdress); $result['status'] = 'ok'; break; } } } return $result; } }