From 35a429c4ca1923b3e87531f34ca64133d4a82efc Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Tue, 2 Jul 2019 22:34:59 +0200 Subject: Add Debian packaging and LGPL license. --- debian/changelog | 5 +++++ debian/compat | 1 + debian/control | 23 +++++++++++++++++++++++ debian/copyright | 35 +++++++++++++++++++++++++++++++++++ debian/rules | 28 ++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100755 debian/rules (limited to 'debian') diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..2b24a8f9e --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +vyos-smoketest (1.0.0) unstable; urgency=medium + + * Initial release + + -- Daniil Baturin Tue, 02 Jul 2019 22:29:53 +0200 diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..97f8b27ea --- /dev/null +++ b/debian/control @@ -0,0 +1,23 @@ +Source: vyos-smoketest +Section: contrib/net +Priority: extra +Maintainer: VyOS Package Maintainers +Build-Depends: debhelper (>= 9), + quilt, + python3, + python3-setuptools, + quilt, + python3-lxml, + python3-nose, + python3-coverage +Standards-Version: 3.9.6 + +Package: vyos-smoketest +Architecture: all +Depends: python3, + ${python3:Depends}, + ${shlibs:Depends}, + ${misc:Depends}, + vyos-1x +Description: VyOS build sanity checking toolkit + VyOS build sanity checking toolkit diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..a3260a7a1 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,35 @@ +This package was debianized by Daniil Baturin on +Tue, 02 Jul 2019 22:24:20 +0200 + +It's original content from the GIT repository + +Upstream Author: + + + +Copyright: + + Copyright (C) 2019 VyOS maintainers and contributors + All Rights Reserved. + +License: + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +A copy of the GNU General Public License is available as +`/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution +or on the World Wide Web at `http://www.gnu.org/copyleft/lgpl.html'. +You can also obtain it by writing to the Free Software Foundation, +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. + +The Debian packaging is (C) 2019, Daniil Baturin and +is licensed under the GPL, see above. diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..4ccc23e86 --- /dev/null +++ b/debian/rules @@ -0,0 +1,28 @@ +#!/usr/bin/make -f + +DIR := debian/vyos-smoketest +VYOS_SBIN_DIR := usr/sbin/ +VYOS_BIN_DIR := usr/bin/ +VYOS_LIBEXEC_DIR := usr/libexec/vyos +VYOS_DATA_DIR := /usr/share/vyos +VYOS_CFG_TMPL_DIR := /opt/vyatta/share/vyatta-cfg/templates +VYOS_OP_TMPL_DIR := /opt/vyatta/share/vyatta-op/templates + +MIGRATION_SCRIPTS_DIR := /opt/vyatta/etc/config-migrate/migrate/ + +SBINDIR := $(DIR)/usr/sbin + +%: + dh $@ --with python3, --with quilt + +override_dh_auto_build: + make all + +override_dh_auto_install: + # Install smoke test scripts + mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke/ + cp -r scripts/* $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke + + # Install system programs + mkdir -p $(SBINDIR) + cp -r bin/* $(SBINDIR) -- cgit v1.2.3 From ae2c359c2938466001359823d4b2a97bd360a889 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 28 Dec 2019 09:43:50 +0100 Subject: Debian: install binary to /usr/bin --- debian/rules | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'debian') diff --git a/debian/rules b/debian/rules index 4ccc23e86..526fb8537 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,6 @@ #!/usr/bin/make -f DIR := debian/vyos-smoketest -VYOS_SBIN_DIR := usr/sbin/ VYOS_BIN_DIR := usr/bin/ VYOS_LIBEXEC_DIR := usr/libexec/vyos VYOS_DATA_DIR := /usr/share/vyos @@ -10,8 +9,6 @@ VYOS_OP_TMPL_DIR := /opt/vyatta/share/vyatta-op/templates MIGRATION_SCRIPTS_DIR := /opt/vyatta/etc/config-migrate/migrate/ -SBINDIR := $(DIR)/usr/sbin - %: dh $@ --with python3, --with quilt @@ -24,5 +21,5 @@ override_dh_auto_install: cp -r scripts/* $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke # Install system programs - mkdir -p $(SBINDIR) - cp -r bin/* $(SBINDIR) + mkdir -p $(DIR)/$(VYOS_BIN_DIR) + cp -r bin/* $(DIR)/$(VYOS_BIN_DIR) -- cgit v1.2.3 From a9eb356dd479330d23e598ac76521cc67356b963 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 5 Feb 2020 22:33:05 +0100 Subject: user: add test for adding/deleting system users --- debian/control | 1 + scripts/cli/test_system_login.py | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 scripts/cli/test_system_login.py (limited to 'debian') diff --git a/debian/control b/debian/control index 97f8b27ea..7dde84d3e 100644 --- a/debian/control +++ b/debian/control @@ -9,6 +9,7 @@ Build-Depends: debhelper (>= 9), quilt, python3-lxml, python3-nose, + python3-paramiko, python3-coverage Standards-Version: 3.9.6 diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py new file mode 100755 index 000000000..c804a6117 --- /dev/null +++ b/scripts/cli/test_system_login.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import re +import unittest + +from paramiko import SSHClient, WarningPolicy + +import vyos.config +import vyos.configsession +import vyos.util as util + +base_path = ['system', 'login'] +users = ['vyos1', 'vyos2'] + +class TestSystemLoginServer(unittest.TestCase): + def setUp(self): + self.session = vyos.configsession.ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = vyos.config.Config(session_env=env) + + def tearDown(self): + # Delete SNNP configuration + for user in users: + self.session.delete(base_path + ['user', user]) + + self.session.commit() + + def test_user(self): + """ Check if user can be created and we can SSH to localhost """ + + for user in users: + name = "VyOS Roxx " + user + home_dir = "/tmp/" + user + + self.session.set(base_path + ['user', user, 'authentication', 'plaintext-password', user]) + self.session.set(base_path + ['user', user, 'full-name', 'VyOS Roxx']) + self.session.set(base_path + ['user', user, 'home-directory', home_dir]) + + self.session.commit() + + # check if we can login via SSH + for user in users: + # check if homedir has been created + self.assertTrue(os.path.isdir("/tmp/" + user)) + + ssh = SSHClient() + ssh.set_missing_host_key_policy(WarningPolicy) + + try: + ssh.connect('localhost', username=user, password=user) + stdin, stdout, stderr = ssh.exec_command('who') + print(stdout.read().decode()) + except Exception as e: + print(e) + self.assertTrue(False) + + ssh.close() + + # check if homedir has been created + # this can only be done after we have connected via ssh and + # pam_mkhomedir was executes + self.assertTrue(os.path.isdir("/tmp/" + user)) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 6aea18a15f96c733505fc7587ac35e263c165549 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 7 Feb 2020 19:07:35 +0100 Subject: Debian: move python3-paramiko from Build-Depends to Depends Commit a9eb356 ("user: add test for adding/deleting system users") added python3-paramiko to the list of build dependencies, but its a runtime dependency. --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 7dde84d3e..41a0338db 100644 --- a/debian/control +++ b/debian/control @@ -9,13 +9,13 @@ Build-Depends: debhelper (>= 9), quilt, python3-lxml, python3-nose, - python3-paramiko, python3-coverage Standards-Version: 3.9.6 Package: vyos-smoketest Architecture: all Depends: python3, + python3-paramiko, ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends}, -- cgit v1.2.3 From 189b724dd7e5f4a5be4137809376127298bf9d25 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 13:00:07 +0100 Subject: login: remove ssh test --- debian/control | 1 - scripts/cli/test_system_login.py | 25 ------------------------- 2 files changed, 26 deletions(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 41a0338db..97f8b27ea 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,6 @@ Standards-Version: 3.9.6 Package: vyos-smoketest Architecture: all Depends: python3, - python3-paramiko, ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends}, diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index c804a6117..b14b52603 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -18,8 +18,6 @@ import os import re import unittest -from paramiko import SSHClient, WarningPolicy - import vyos.config import vyos.configsession import vyos.util as util @@ -53,28 +51,5 @@ class TestSystemLoginServer(unittest.TestCase): self.session.commit() - # check if we can login via SSH - for user in users: - # check if homedir has been created - self.assertTrue(os.path.isdir("/tmp/" + user)) - - ssh = SSHClient() - ssh.set_missing_host_key_policy(WarningPolicy) - - try: - ssh.connect('localhost', username=user, password=user) - stdin, stdout, stderr = ssh.exec_command('who') - print(stdout.read().decode()) - except Exception as e: - print(e) - self.assertTrue(False) - - ssh.close() - - # check if homedir has been created - # this can only be done after we have connected via ssh and - # pam_mkhomedir was executes - self.assertTrue(os.path.isdir("/tmp/" + user)) - if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 23257105b68cb26fe16638928ab490fe3ea99164 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 08:13:24 +0200 Subject: Debian: cleanup runtime dependencies Depends field of package vyos-smoketest: substitution variable ${shlibs:Depends} used, but is not defined --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 97f8b27ea..ada46a4c1 100644 --- a/debian/control +++ b/debian/control @@ -16,7 +16,6 @@ Package: vyos-smoketest Architecture: all Depends: python3, ${python3:Depends}, - ${shlibs:Depends}, ${misc:Depends}, vyos-1x Description: VyOS build sanity checking toolkit -- cgit v1.2.3 From 909152a69e0844ad0cdd2b05467cd7fe379a5347 Mon Sep 17 00:00:00 2001 From: jack9603301 Date: Mon, 10 Aug 2020 21:40:57 +0800 Subject: tcptraceroute: T2723: Fix the problem that tcptraceroute6 cannot be executed --- debian/control | 3 ++- op-mode-definitions/traceroute.xml | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 3a441b47b..34ba4be8e 100644 --- a/debian/control +++ b/debian/control @@ -106,7 +106,8 @@ Depends: python3, conntrack, libatomic1, fastnetmon, - libndp-tools + libndp-tools, + tcptraceroute Description: VyOS configuration scripts and data VyOS configuration scripts, interface definitions, and everything diff --git a/op-mode-definitions/traceroute.xml b/op-mode-definitions/traceroute.xml index efbaaeb2f..b562eb2e6 100644 --- a/op-mode-definitions/traceroute.xml +++ b/op-mode-definitions/traceroute.xml @@ -26,7 +26,7 @@ /usr/bin/traceroute -4 "$3" - + Route tracing and port detection using TCP @@ -38,10 +38,10 @@ 0-65535 - sudo /usr/sbin/tcptraceroute "$3" $6 + sudo /usr/bin/tcptraceroute "$3" $6 - + @@ -53,7 +53,7 @@ /usr/bin/traceroute -6 "$3" - + Use TCP/IPv6 packets to perform a traceroute @@ -65,10 +65,10 @@ 0-65535 - sudo /usr/sbin/tcptraceroute6 "$3" $6 + sudo /usr/bin/tcptraceroute6 "$3" $6 - + -- cgit v1.2.3 From 865cba395223afaa263ff7581fb53ee509f36266 Mon Sep 17 00:00:00 2001 From: Eshenko Dmitriy Date: Wed, 19 Aug 2020 00:37:00 +0300 Subject: anyconnect: T2036: add anyconnect VPN support --- data/templates/ocserv/ocserv_config.tmpl | 82 +++++++ data/templates/ocserv/ocserv_passwd.tmpl | 6 + data/templates/ocserv/radius_conf.tmpl | 22 ++ data/templates/ocserv/radius_servers.tmpl | 7 + debian/control | 1 + interface-definitions/vpn_anyconnect.xml.in | 258 +++++++++++++++++++++ op-mode-definitions/anyconnect.xml | 20 ++ src/conf_mode/vpn_anyconnect.py | 132 +++++++++++ .../systemd/system/ocserv.service.d/override.conf | 14 ++ src/op_mode/anyconnect-control.py | 67 ++++++ 10 files changed, 609 insertions(+) create mode 100644 data/templates/ocserv/ocserv_config.tmpl create mode 100644 data/templates/ocserv/ocserv_passwd.tmpl create mode 100644 data/templates/ocserv/radius_conf.tmpl create mode 100644 data/templates/ocserv/radius_servers.tmpl create mode 100644 interface-definitions/vpn_anyconnect.xml.in create mode 100644 op-mode-definitions/anyconnect.xml create mode 100755 src/conf_mode/vpn_anyconnect.py create mode 100644 src/etc/systemd/system/ocserv.service.d/override.conf create mode 100755 src/op_mode/anyconnect-control.py (limited to 'debian') diff --git a/data/templates/ocserv/ocserv_config.tmpl b/data/templates/ocserv/ocserv_config.tmpl new file mode 100644 index 000000000..6aaeff693 --- /dev/null +++ b/data/templates/ocserv/ocserv_config.tmpl @@ -0,0 +1,82 @@ +### generated by vpn_anyconnect.py ### + +tcp-port = {{ listen_ports.tcp }} +udp-port = {{ listen_ports.udp }} + +run-as-user = nobody +run-as-group = daemon + +{% if "radius" in authentication.mode %} +auth = "radius [config=/run/ocserv/radiusclient.conf]" +{% else %} +auth = "plain[/run/ocserv/ocpasswd]" +{% endif %} + +{% if ssl.cert_file %} +server-cert = {{ ssl.cert_file }} +{% endif %} + +{% if ssl.key_file %} +server-key = {{ ssl.key_file }} +{% endif %} + +{% if ssl.ca_cert_file %} +ca-cert = {{ ssl.ca_cert_file }} +{% endif %} + +socket-file = /run/ocserv/ocserv.socket +occtl-socket-file = /run/ocserv/occtl.socket +use-occtl = true +isolate-workers = true +keepalive = 300 +dpd = 60 +mobile-dpd = 300 +switch-to-tcp-timeout = 30 +tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128" +auth-timeout = 240 +idle-timeout = 1200 +mobile-idle-timeout = 1800 +min-reauth-time = 3 +cookie-timeout = 300 +rekey-method = ssl +try-mtu-discovery = true +cisco-client-compat = true +dtls-legacy = true + + +# The name to use for the tun device +device = sslvpn + +# An alternative way of specifying the network: +{% if network_settings %} +# DNS settings +{% if network_settings.name_server is string %} +dns = {{ network_settings.name_server }} +{% else %} +{% for dns in network_settings.name_server %} +dns = {{ dns }} +{% endfor %} +{% endif %} +# IPv4 network pool +{% if network_settings.client_ip_settings %} +{% if network_settings.client_ip_settings.subnet %} +ipv4-network = {{ network_settings.client_ip_settings.subnet }} +{% endif %} +{% endif %} +# IPv6 network pool +{% if network_settings.client_ipv6_pool %} +{% if network_settings.client_ipv6_pool.prefix %} +ipv6-network = {{ network_settings.client_ipv6_pool.prefix }} +ipv6-subnet-prefix = {{ network_settings.client_ipv6_pool.mask }} +{% endif %} +{% endif %} +{% endif %} + +{% if network_settings.push_route is string %} +route = {{ network_settings.push_route }} +{% else %} +{% for route in network_settings.push_route %} +route = {{ route }} +{% endfor %} +{% endif %} + diff --git a/data/templates/ocserv/ocserv_passwd.tmpl b/data/templates/ocserv/ocserv_passwd.tmpl new file mode 100644 index 000000000..ffadb4860 --- /dev/null +++ b/data/templates/ocserv/ocserv_passwd.tmpl @@ -0,0 +1,6 @@ +#:: +{% for user in username if username is defined %} +{% if not "disable" in username[user] %} +{{ user }}:*:{{ username[user].hash }} +{% endif %} +{% endfor %} \ No newline at end of file diff --git a/data/templates/ocserv/radius_conf.tmpl b/data/templates/ocserv/radius_conf.tmpl new file mode 100644 index 000000000..2d19306a0 --- /dev/null +++ b/data/templates/ocserv/radius_conf.tmpl @@ -0,0 +1,22 @@ +### generated by cpn_anyconnect.py ### +nas-identifier VyOS +{% for srv in server %} +{% if not "disable" in server[srv] %} +{% if "port" in server[srv] %} +authserver {{ srv }}:{{server[srv]["port"]}} +{% else %} +authserver {{ srv }} +{% endif %} +{% endif %} +{% endfor %} +radius_timeout {{ timeout }} +{% if source_address %} +bindaddr {{ source_address }} +{% else %} +bindaddr * +{% endif %} +servers /run/ocserv/radius_servers +dictionary /etc/radcli/dictionary +default_realm +radius_retries 3 +# \ No newline at end of file diff --git a/data/templates/ocserv/radius_servers.tmpl b/data/templates/ocserv/radius_servers.tmpl new file mode 100644 index 000000000..ba21fa074 --- /dev/null +++ b/data/templates/ocserv/radius_servers.tmpl @@ -0,0 +1,7 @@ +### generated by cpn_anyconnect.py ### +# server key +{% for srv in server %} +{% if not "disable" in server[srv] %} +{{ srv }} {{ server[srv].key }} +{% endif %} +{% endfor %} diff --git a/debian/control b/debian/control index 34ba4be8e..520401d57 100644 --- a/debian/control +++ b/debian/control @@ -107,6 +107,7 @@ Depends: python3, libatomic1, fastnetmon, libndp-tools, + ocserv, tcptraceroute Description: VyOS configuration scripts and data VyOS configuration scripts, interface definitions, and everything diff --git a/interface-definitions/vpn_anyconnect.xml.in b/interface-definitions/vpn_anyconnect.xml.in new file mode 100644 index 000000000..e74326986 --- /dev/null +++ b/interface-definitions/vpn_anyconnect.xml.in @@ -0,0 +1,258 @@ + + + + + + + SSL VPN AnyConnect + 901 + + + + + Authentication for remote access SSL VPN Server + + + + + Authentication mode used by this server + + local + Use local username/password configuration + + + radius + Use RADIUS server for user autentication + + + (local|radius) + + + local radius + + + + + + Local user authentication for SSL VPN server + + + + + User name for authentication + + + + + Option to disable a SSL VPN Server user + + + + + + Password for authentication + + + + + + + #include + + + + + Session timeout + + 1-30 + Session timeout in seconds (default: 2) + + + + + Timeout must be between 1 and 30 seconds + + 2 + + + + + + + + SSL Certificate, SSL Key and CA (/config/auth) + + + + + tcp port number to accept connections (default: 443) + + 1-65535 + Numeric IP port (default: 443) + + + + + + 443 + + + + udp port number to accept connections (default: 443) + + 1-65535 + Numeric IP port (default: 443) + + + + + + 443 + + + + + + SSL Certificate, SSL Key and CA (/config/auth) + + + + + Certificate Authority certificate + + + + + file + File in /config/auth directory + + + + + + + + + Server Certificate + + file + File in /config/auth directory + + + + + + + + + Privat Key of the Server Certificate + + file + File in /config/auth directory + + + + + + + + + + + Network settings + + + + + Route to be pushed to the client + + ipv4net + IPv4 network and prefix length + + + ipv6net + IPv6 network and prefix length + + + + + + + + + + Client IP pools settings + + + + + Client IP subnet (CIDR notation) + + ipv4net + IPv4 address and prefix length + + + + + Not a valid CIDR formatted prefix + + + + + + + Pool of client IPv6 addresses + + + + + Pool of addresses used to assign to clients + + ipv6net + IPv6 address and prefix length + + + + + + + + + Prefix length used for individual client + + <48-128> + Client prefix length (default: 64) + + + + + + 64 + + + + + + Domain Name Server (DNS) propagated to client + + ipv4 + Domain Name Server (DNS) IPv4 address + + + ipv6 + Domain Name Server (DNS) IPv6 address + + + + + + + + + + + + + + + diff --git a/op-mode-definitions/anyconnect.xml b/op-mode-definitions/anyconnect.xml new file mode 100644 index 000000000..7e8cdd35b --- /dev/null +++ b/op-mode-definitions/anyconnect.xml @@ -0,0 +1,20 @@ + + + + + + + show anyconnect-server information + + + + + Show active anyconnect server sessions + + ${vyos_op_scripts_dir}/anyconnect-control.py --action="show_sessions" + + + + + + diff --git a/src/conf_mode/vpn_anyconnect.py b/src/conf_mode/vpn_anyconnect.py new file mode 100755 index 000000000..45c06bffa --- /dev/null +++ b/src/conf_mode/vpn_anyconnect.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +from sys import exit + +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.xml import defaults +from vyos.template import render +from vyos.util import call +from vyos import ConfigError +from crypt import crypt, mksalt, METHOD_SHA512 + +from vyos import airbag +airbag.enable() + +cfg_dir = '/run/ocserv' +ocserv_conf = cfg_dir + '/ocserv.conf' +ocserv_passwd = cfg_dir + '/ocpasswd' +radius_cfg = cfg_dir + '/radiusclient.conf' +radius_servers = cfg_dir + '/radius_servers' + + +# Generate hash from user cleartext password +def get_hash(password): + return crypt(password, mksalt(METHOD_SHA512)) + + +def get_config(): + conf = Config() + base = ['vpn', 'anyconnect'] + ocserv = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + default_values = defaults(base) + ocserv = dict_merge(default_values, ocserv) + return ocserv + + +def verify(ocserv): + if ocserv is None: + return None + + # Check authentication + if "authentication" in ocserv: + if "mode" in ocserv["authentication"]: + if "local" in ocserv["authentication"]["mode"]: + if not ocserv["authentication"]["local_users"] or not ocserv["authentication"]["local_users"]["username"]: + raise ConfigError('Anyconect mode local required at leat one user') + else: + for user in ocserv["authentication"]["local_users"]["username"]: + if not "password" in ocserv["authentication"]["local_users"]["username"][user]: + raise ConfigError(f'password required for user {user}') + else: + raise ConfigError('anyconnect authentication mode required') + else: + raise ConfigError('anyconnect authentication credentials required') + + # Check ssl + if "ssl" in ocserv: + req_cert = ['ca_cert_file', 'cert_file', 'key_file'] + for cert in req_cert: + if not cert in ocserv["ssl"]: + raise ConfigError('anyconnect ssl {0} required'.format(cert.replace('_', '-'))) + else: + raise ConfigError('anyconnect ssl required') + + # Check network settings + if "network_settings" in ocserv: + if "push_route" in ocserv["network_settings"]: + # Replace default route + if "0.0.0.0/0" in ocserv["network_settings"]["push_route"]: + ocserv["network_settings"]["push_route"].remove("0.0.0.0/0") + ocserv["network_settings"]["push_route"].append("default") + else: + ocserv["network_settings"]["push_route"] = "default" + else: + raise ConfigError('anyconnect network settings required') + + +def generate(ocserv): + if not ocserv: + return None + + if "radius" in ocserv["authentication"]["mode"]: + # Render radius client configuration + render(radius_cfg, 'ocserv/radius_conf.tmpl', ocserv["authentication"]["radius"], trim_blocks=True) + # Render radius servers + render(radius_servers, 'ocserv/radius_servers.tmpl', ocserv["authentication"]["radius"], trim_blocks=True) + else: + if "local_users" in ocserv["authentication"]: + for user in ocserv["authentication"]["local_users"]["username"]: + ocserv["authentication"]["local_users"]["username"][user]["hash"] = get_hash(ocserv["authentication"]["local_users"]["username"][user]["password"]) + # Render local users + render(ocserv_passwd, 'ocserv/ocserv_passwd.tmpl', ocserv["authentication"]["local_users"], trim_blocks=True) + + # Render config + render(ocserv_conf, 'ocserv/ocserv_config.tmpl', ocserv, trim_blocks=True) + + + +def apply(ocserv): + if not ocserv: + call('systemctl stop ocserv.service') + for file in [ocserv_conf, ocserv_passwd]: + if os.path.exists(file): + os.unlink(file) + else: + call('systemctl restart ocserv.service') + + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + exit(1) diff --git a/src/etc/systemd/system/ocserv.service.d/override.conf b/src/etc/systemd/system/ocserv.service.d/override.conf new file mode 100644 index 000000000..89dbb153f --- /dev/null +++ b/src/etc/systemd/system/ocserv.service.d/override.conf @@ -0,0 +1,14 @@ +[Unit] +RequiresMountsFor=/run +ConditionPathExists=/run/ocserv/ocserv.conf +After= +After=vyos-router.service +After=dbus.service + +[Service] +WorkingDirectory=/run/ocserv +PIDFile= +PIDFile=/run/ocserv/ocserv.pid +ExecStart= +ExecStart=/usr/sbin/ocserv --foreground --pid-file /run/ocserv/ocserv.pid --config /run/ocserv/ocserv.conf + diff --git a/src/op_mode/anyconnect-control.py b/src/op_mode/anyconnect-control.py new file mode 100755 index 000000000..6382016b7 --- /dev/null +++ b/src/op_mode/anyconnect-control.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import sys +import argparse +import json + +from vyos.config import Config +from vyos.util import popen, run, DEVNULL +from tabulate import tabulate + +occtl = '/usr/bin/occtl' +occtl_socket = '/run/ocserv/occtl.socket' + +def show_sessions(): + out, code = popen("sudo {0} -j -s {1} show users".format(occtl, occtl_socket),stderr=DEVNULL) + if code: + sys.exit('Cannot get anyconnect users information') + else: + headers = ["interface", "username", "ip", "remote IP", "RX", "TX", "state", "uptime"] + sessions = json.loads(out) + ses_list = [] + for ses in sessions: + ses_list.append([ses["Device"], ses["Username"], ses["IPv4"], ses["Remote IP"], ses["_RX"], ses["_TX"], ses["State"], ses["_Connected at"]]) + if len(ses_list) > 0: + print(tabulate(ses_list, headers)) + else: + print("No active anyconnect sessions") + +def is_ocserv_configured(): + if not Config().exists_effective('vpn anyconnect'): + print("vpn anyconnect server is not configured") + sys.exit(1) + +def main(): + #parese args + parser = argparse.ArgumentParser() + parser.add_argument('--action', help='Control action', required=True) + parser.add_argument('--selector', help='Selector username|ifname|sid', required=False) + parser.add_argument('--target', help='Target must contain username|ifname|sid', required=False) + args = parser.parse_args() + + + # Check is IPoE configured + is_ocserv_configured() + + if args.action == "restart": + run("systemctl restart ocserv") + sys.exit(0) + elif args.action == "show_sessions": + show_sessions() + +if __name__ == '__main__': + main() -- cgit v1.2.3 From 20e66514c00cf6495370bac6bbbe45a505afe242 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 20 Aug 2020 22:27:30 +0200 Subject: lcd: T2564: remove lcdproc-extra-drivers package --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 520401d57..9be41df33 100644 --- a/debian/control +++ b/debian/control @@ -74,7 +74,6 @@ Depends: python3, udp-broadcast-relay, pdns-recursor, lcdproc, - lcdproc-extra-drivers, openvpn, openvpn-auth-ldap, openvpn-auth-radius, -- cgit v1.2.3 From 50a7544ad69cb7b631a499299f9ab32b2e8918a0 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 20 Aug 2020 22:54:50 +0200 Subject: Debian: alphabetically sort (build-)dependencies --- debian/control | 169 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 86 insertions(+), 83 deletions(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 9be41df33..d6b4420c7 100644 --- a/debian/control +++ b/debian/control @@ -2,112 +2,115 @@ Source: vyos-1x Section: contrib/net Priority: extra Maintainer: VyOS Package Maintainers -Build-Depends: debhelper (>= 9), - quilt, +Build-Depends: + debhelper (>= 9), + fakeroot, + libvyosconfig0 (>= 0.0.7), python3, - python3-setuptools, - python3-xmltodict, + python3-coverage, python3-lxml, python3-nose, - python3-coverage, - whois, - fakeroot, - libvyosconfig0 (>= 0.0.7) + python3-setuptools, + python3-xmltodict, + quilt, + whois Standards-Version: 3.9.6 Package: vyos-1x Architecture: all -Depends: python3, - ${python3:Depends}, - python3-netifaces, - python3-jinja2, - python3-pystache, - python3-psutil, - python3-tabulate, - python3-six, - python3-isc-dhcp-leases, - python3-hurry.filesize, - python3-vici (>= 5.7.2), - python3-flask, - python3-waitress, - python3-netaddr, - python3-zmq, - python3-jmespath, - python3-xmltodict, - python3-pyudev, - python3-voluptuous, +Depends: + accel-ppp, + beep, + bmon, bsdmainutils, + conntrack, + conserver-client, + conserver-server, + crda, cron, - etherwake, - systemd, + dbus, + dropbear, easy-rsa, + etherwake, + fastnetmon, + file, + frr, + frr-pythontools, + hostapd (>= 0.6.8), + hvinfo, + igmpproxy, ipaddrcheck, - tcpdump, + iperf, + iperf3, + iputils-arping, isc-dhcp-client, - wide-dhcpv6-client, - bmon, - hvinfo, + isc-dhcp-relay, + isc-dhcp-server, + iw, + keepalived (>=2.0.5), + lcdproc, + libatomic1, + libndp-tools, + libpam-radius-auth (>= 1.5.0), + libvyosconfig0, + lldpd, lm-sensors, - file, lsscsi, - pciutils, - usbutils, - procps, - snmp, snmpd, - openssh-server, + mdns-repeater, + mtr-tiny, + nftables (>= 0.9.3), + nginx-light, ntp, ntpdate, - iputils-arping, - libvyosconfig0, - beep, - dropbear, - conserver-server, - conserver-client, - isc-dhcp-server, - isc-dhcp-relay, - keepalived (>=2.0.5), - wireguard, - tftpd-hpa, - igmpproxy, - accel-ppp, - mdns-repeater, - udp-broadcast-relay, - pdns-recursor, - lcdproc, + ocserv, + openssh-server, openvpn, openvpn-auth-ldap, openvpn-auth-radius, - libpam-radius-auth (>= 1.5.0), - mtr-tiny, - telnet, - traceroute, - ssl-cert, - nginx-light, - lldpd, - iperf, - iperf3, - frr, - frr-pythontools, - radvd, - dbus, - usb-modeswitch, - hostapd (>= 0.6.8), - wpasupplicant (>= 0.6.7), - iw, - crda, - wireless-regdb, + pciutils, + pdns-recursor, pmacct (>= 1.6.0), - python3-certbot-nginx, pppoe, + procps, + python3, + python3-certbot-nginx, + ${python3:Depends}, + python3-flask, + python3-hurry.filesize, + python3-isc-dhcp-leases, + python3-jinja2, + python3-jmespath, + python3-netaddr, + python3-netifaces, + python3-psutil, + python3-pystache, + python3-pyudev, + python3-six, + python3-tabulate, + python3-vici (>= 5.7.2), + python3-voluptuous, + python3-waitress, + python3-xmltodict, + python3-zmq, + radvd, salt-minion, + snmp, + snmpd, + ssl-cert, + systemd, + tcpdump, + tcptraceroute, + telnet, + tftpd-hpa, + traceroute, + udp-broadcast-relay, + usb-modeswitch, + usbutils, vyos-utils, - nftables (>= 0.9.3), - conntrack, - libatomic1, - fastnetmon, - libndp-tools, - ocserv, - tcptraceroute + wide-dhcpv6-client, + wireguard, + wireless-regdb, + wpasupplicant (>= 0.6.7) Description: VyOS configuration scripts and data VyOS configuration scripts, interface definitions, and everything -- cgit v1.2.3 From da9ec80f80b15d88d3bc2bc1ee13e7136ee14c97 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 27 Aug 2020 21:13:27 +0200 Subject: Debian: set proper changelog version --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'debian') diff --git a/debian/changelog b/debian/changelog index fba9d77d0..2b65b22c6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -vyos-1x (1.0.0) unstable; urgency=medium +vyos-1x (1.3dev0) unstable; urgency=medium * Dummy changelog entry for vyos-1x repository This is a internal VyOS package and the VyOS package process does not use @@ -7,4 +7,4 @@ vyos-1x (1.0.0) unstable; urgency=medium The correct verion number of this package is auto-generated by GIT on build-time - -- Runar Borge Sat, 9 May 2020 22:00:00 +0100 + -- VyOS maintainers and contributors Wed, 26 Aug 2020 19:07:24 +0000 -- cgit v1.2.3 From bab1534e0fc1e6da538414b8b032342eb2598f03 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 30 Aug 2020 16:09:37 +0200 Subject: WireGuard: T2842: switch to binary package from buster-backports --- debian/control | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index 65808de86..a628fa9c4 100644 --- a/debian/control +++ b/debian/control @@ -108,7 +108,8 @@ Depends: usbutils, vyos-utils, wide-dhcpv6-client, - wireguard, + wireguard-tools, + wireguard-modules, wireless-regdb, wpasupplicant (>= 0.6.7) Description: VyOS configuration scripts and data -- cgit v1.2.3 From bd076f694a763991a0b0d3a7bb0fa5d194d56d7c Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 30 Aug 2020 21:41:27 +0200 Subject: Debian: T2843: drop wireguard-modules dependency with kernel 5.8 --- debian/control | 1 - 1 file changed, 1 deletion(-) (limited to 'debian') diff --git a/debian/control b/debian/control index a628fa9c4..65f3be228 100644 --- a/debian/control +++ b/debian/control @@ -109,7 +109,6 @@ Depends: vyos-utils, wide-dhcpv6-client, wireguard-tools, - wireguard-modules, wireless-regdb, wpasupplicant (>= 0.6.7) Description: VyOS configuration scripts and data -- cgit v1.2.3 From 88985dad133d5e85aca559dbfce53207a2292e0a Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 28 Aug 2020 15:49:55 -0500 Subject: configd: T2582: add config daemon and supporting files --- data/configd-include.json | 1 + data/vyos-configd-env-set | 2 + data/vyos-configd-env-unset | 2 + debian/control | 1 + debian/rules | 1 + src/services/vyos-configd | 224 +++++++++++++++++++++++++++++++++++++++ src/systemd/vyos-configd.service | 27 +++++ 7 files changed, 258 insertions(+) create mode 100644 data/configd-include.json create mode 100644 data/vyos-configd-env-set create mode 100644 data/vyos-configd-env-unset create mode 100755 src/services/vyos-configd create mode 100644 src/systemd/vyos-configd.service (limited to 'debian') diff --git a/data/configd-include.json b/data/configd-include.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/data/configd-include.json @@ -0,0 +1 @@ +[] diff --git a/data/vyos-configd-env-set b/data/vyos-configd-env-set new file mode 100644 index 000000000..d6d421eba --- /dev/null +++ b/data/vyos-configd-env-set @@ -0,0 +1,2 @@ +# +export vyshim=/usr/sbin/vyshim diff --git a/data/vyos-configd-env-unset b/data/vyos-configd-env-unset new file mode 100644 index 000000000..9616f9858 --- /dev/null +++ b/data/vyos-configd-env-unset @@ -0,0 +1,2 @@ +# +unset vyshim diff --git a/debian/control b/debian/control index 65f3be228..d9663d07b 100644 --- a/debian/control +++ b/debian/control @@ -6,6 +6,7 @@ Build-Depends: debhelper (>= 9), fakeroot, libvyosconfig0 (>= 0.0.7), + libzmq3-dev, python3, python3-coverage, python3-lxml, diff --git a/debian/rules b/debian/rules index 58bafd333..6b982fd8e 100755 --- a/debian/rules +++ b/debian/rules @@ -33,6 +33,7 @@ override_dh_auto_install: mkdir -p $(DIR)/$(VYOS_SBIN_DIR) mkdir -p $(DIR)/$(VYOS_BIN_DIR) cp -r src/utils/* $(DIR)/$(VYOS_BIN_DIR) + cp src/shim/vyshim $(DIR)/$(VYOS_SBIN_DIR) # Install conf mode scripts mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/conf_mode diff --git a/src/services/vyos-configd b/src/services/vyos-configd new file mode 100755 index 000000000..75f84d3df --- /dev/null +++ b/src/services/vyos-configd @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# + +import os +import sys +import grp +import re +import json +import logging +import signal +import importlib.util +import zmq + +from vyos.defaults import directories +from vyos.configsource import ConfigSourceString +from vyos.config import Config +from vyos import ConfigError + +CFG_GROUP = 'vyattacfg' + +debug = True + +logger = logging.getLogger(__name__) +logs_handler = logging.StreamHandler() +logger.addHandler(logs_handler) + +if debug: + logger.setLevel(logging.DEBUG) +else: + logger.setLevel(logging.INFO) + +SOCKET_PATH = "ipc:///run/vyos-configd.sock" + +# Response error codes +R_SUCCESS = 1 +R_ERROR_COMMIT = 2 +R_ERROR_DAEMON = 4 +R_PASS = 8 + +vyos_conf_scripts_dir = directories['conf_mode'] +configd_include_file = os.path.join(directories['data'], 'configd-include.json') +configd_env_set_file = os.path.join(directories['data'], 'vyos-configd-env-set') +configd_env_unset_file = os.path.join(directories['data'], 'vyos-configd-env-unset') +# sourced on entering config session +configd_env_file = '/etc/default/vyos-configd-env' + +active_string = '' +session_string = '' + +def key_name_from_file_name(f): + return os.path.splitext(f)[0] + +def module_name_from_key(k): + return k.replace('-', '_') + +def path_from_file_name(f): + return os.path.join(vyos_conf_scripts_dir, f) + +# opt-in to be run by daemon +with open(configd_include_file) as f: + try: + include = json.load(f) + except OSError as e: + logger.critical(f"configd include file error: {e}") + sys.exit(1) + except json.JSONDecodeError as e: + logger.critical(f"JSON load error: {e}") + sys.exit(1) + +# import conf_mode scripts +(_, _, filenames) = next(iter(os.walk(vyos_conf_scripts_dir))) +filenames.sort() + +load_filenames = [f for f in filenames if f in include] +imports = [key_name_from_file_name(f) for f in load_filenames] +module_names = [module_name_from_key(k) for k in imports] +paths = [path_from_file_name(f) for f in load_filenames] +to_load = list(zip(module_names, paths)) + +modules = [] + +for x in to_load: + spec = importlib.util.spec_from_file_location(x[0], x[1]) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + modules.append(module) + +conf_mode_scripts = dict(zip(imports, modules)) + +exclude_set = {key_name_from_file_name(f) for f in filenames if f not in include} +include_set = {key_name_from_file_name(f) for f in filenames if f in include} + + +def run_script(script, config) -> int: + config.set_level([]) + try: + c = script.get_config(config) + script.verify(c) + script.generate(c) + script.apply(c) + except ConfigError as e: + logger.critical(e) + return R_ERROR_COMMIT + except Exception: + return R_ERROR_DAEMON + + return R_SUCCESS + +def initialization(socket): + # Reset config strings: + active_string = '' + session_string = '' + # zmq synchronous for ipc from single client: + active_string = socket.recv().decode() + resp = "active" + socket.send(resp.encode()) + session_string = socket.recv().decode() + resp = "session" + socket.send(resp.encode()) + + configsource = ConfigSourceString(running_config_text=active_string, + session_config_text=session_string) + + config = Config(config_source=configsource) + + return config + +def process_node_data(config, data) -> int: + if not config: + logger.critical(f"Empty config") + return R_ERROR_DAEMON + + script_name = None + + res = re.match(r'^.+\/([^/].+).py(VYOS_TAGNODE_VALUE=.+)?', data) + if res.group(1): + script_name = res.group(1) + if res.group(2): + env = res.group(2).split('=') + os.environ[env[0]] = env[1] + + if not script_name: + logger.critical(f"Missing script_name") + return R_ERROR_DAEMON + + if script_name in exclude_set: + return R_PASS + + result = run_script(conf_mode_scripts[script_name], config) + + return result + +def remove_if_file(f: str): + try: + os.remove(f) + except FileNotFoundError: + pass + except OSError: + raise + +def shutdown(): + remove_if_file(configd_env_file) + os.symlink(configd_env_unset_file, configd_env_file) + sys.exit(0) + +if __name__ == '__main__': + context = zmq.Context() + socket = context.socket(zmq.REP) + + # Set the right permissions on the socket, then change it back + o_mask = os.umask(0) + socket.bind(SOCKET_PATH) + os.umask(o_mask) + + cfg_group = grp.getgrnam(CFG_GROUP) + os.setgid(cfg_group.gr_gid) + + os.environ['SUDO_USER'] = 'vyos' + os.environ['SUDO_GID'] = str(cfg_group.gr_gid) + + def sig_handler(signum, frame): + shutdown() + + signal.signal(signal.SIGTERM, sig_handler) + signal.signal(signal.SIGINT, sig_handler) + + # Define the vyshim environment variable + remove_if_file(configd_env_file) + os.symlink(configd_env_set_file, configd_env_file) + + config = None + + while True: + # Wait for next request from client + msg = socket.recv().decode() + logger.debug(f"Received message: {msg}") + message = json.loads(msg) + + if message["type"] == "init": + resp = "init" + socket.send(resp.encode()) + config = initialization(socket) + elif message["type"] == "node": + res = process_node_data(config, message["data"]) + response = res.to_bytes(1, byteorder=sys.byteorder) + logger.debug(f"Sending response {res}") + socket.send(response) + else: + logger.critical(f"Unexpected message: {message}") diff --git a/src/systemd/vyos-configd.service b/src/systemd/vyos-configd.service new file mode 100644 index 000000000..274ccc787 --- /dev/null +++ b/src/systemd/vyos-configd.service @@ -0,0 +1,27 @@ +[Unit] +Description=VyOS configuration daemon + +# Without this option, lots of default dependencies are added, +# among them network.target, which creates a dependency cycle +DefaultDependencies=no + +# Seemingly sensible way to say "as early as the system is ready" +# All vyos-configd needs is read/write mounted root +After=systemd-remount-fs.service +Before=vyos-router.service + +[Service] +ExecStart=/usr/bin/python3 -u /usr/libexec/vyos/services/vyos-configd +Type=idle + +SyslogIdentifier=vyos-configd +SyslogFacility=daemon + +Restart=on-failure + +# Does't work in Jessie but leave it here +User=root +Group=vyattacfg + +[Install] +WantedBy=vyos.target -- cgit v1.2.3 From d469e2f56e299a9d767d7db1f00646741f7ce367 Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 28 Aug 2020 15:50:19 -0500 Subject: configd: T2582: add shim as config daemon client --- Makefile | 10 +- debian/vyos-1x.install | 1 + src/shim/Makefile | 20 ++++ src/shim/vyshim.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 src/shim/Makefile create mode 100644 src/shim/vyshim.c (limited to 'debian') diff --git a/Makefile b/Makefile index 5b7e4da63..e85835eec 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,9 @@ TMPL_DIR := templates-cfg OP_TMPL_DIR := templates-op BUILD_DIR := build DATA_DIR := data +SHIM_DIR := src/shim +CC := gcc +LIBS := -lzmq CFLAGS := src = $(wildcard interface-definitions/*.xml.in) @@ -114,14 +117,19 @@ op_mode_definitions: component_versions: $(BUILD_DIR) $(obj) $(CURDIR)/scripts/build-component-versions $(BUILD_DIR)/interface-definitions $(DATA_DIR) +.PHONY: vyshim +vyshim: + $(MAKE) -C $(SHIM_DIR) + .PHONY: all -all: clean interface_definitions op_mode_definitions component_versions +all: clean interface_definitions op_mode_definitions component_versions vyshim .PHONY: clean clean: rm -rf $(BUILD_DIR) rm -rf $(TMPL_DIR) rm -rf $(OP_TMPL_DIR) + $(MAKE) -C $(SHIM_DIR) clean .PHONY: test test: diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install index 6cd678442..6d5026e91 100644 --- a/debian/vyos-1x.install +++ b/debian/vyos-1x.install @@ -7,6 +7,7 @@ etc/udev etc/vyos lib/ opt/ +usr/sbin/vyshim usr/bin/initial-setup usr/bin/vyos-config-file-query usr/bin/vyos-config-to-commands diff --git a/src/shim/Makefile b/src/shim/Makefile new file mode 100644 index 000000000..c8487e3c2 --- /dev/null +++ b/src/shim/Makefile @@ -0,0 +1,20 @@ +DEBUG = 0 + +CC := gcc +CFLAGS := -I./mkjson -L./mkjson/lib -DDEBUG=${DEBUG} +LIBS := -lmkjson -lzmq + +.PHONY: vyshim +vyshim: vyshim.c libmkjson + $(CC) $(CFLAGS) -o $@ $< $(LIBS) + +.PHONY: libmkjson +libmkjson: + $(MAKE) -C mkjson + +all: vyshim + +.PHONY: clean +clean: + $(MAKE) -C mkjson clean + rm -f vyshim diff --git a/src/shim/vyshim.c b/src/shim/vyshim.c new file mode 100644 index 000000000..8b6feab99 --- /dev/null +++ b/src/shim/vyshim.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2020 VyOS maintainers and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or later as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mkjson.h" + +/* + * + * + */ + +#if DEBUG +#define DEBUG_ON 1 +#else +#define DEBUG_ON 0 +#endif +#define debug_print(fmt, ...) \ + do { if (DEBUG_ON) fprintf(stderr, fmt, ##__VA_ARGS__); } while (0) +#define debug_call(f) \ + do { if (DEBUG_ON) f; } while (0) + +#define SOCKET_PATH "ipc:///run/vyos-configd.sock" + +#define GET_ACTIVE "cli-shell-api --show-active-only --show-show-defaults --show-ignore-edit showConfig" +#define GET_SESSION "cli-shell-api --show-working-only --show-show-defaults --show-ignore-edit showConfig" + +#define COMMIT_MARKER "/var/tmp/initial_in_commit" + +enum { + SUCCESS = 1 << 0, + ERROR_COMMIT = 1 << 1, + ERROR_DAEMON = 1 << 2, + PASS = 1 << 3 +}; + +volatile int init_alarm = 0; +volatile int timeout = 0; + +int initialization(void *); +int pass_through(char **, int); +void timer_handler(int); + +double get_posix_clock_time(void); + +int main(int argc, char* argv[]) +{ + // string for node data: conf_mode script and tagnode, if applicable + char string_node_data[256]; + string_node_data[0] = '\0'; + + void *context = zmq_ctx_new(); + void *requester = zmq_socket(context, ZMQ_REQ); + + int init_timeout = 0; + + debug_print("Connecting to vyos-configd ...\n"); + zmq_connect(requester, SOCKET_PATH); + + if (access(COMMIT_MARKER, F_OK) != -1) { + init_timeout = initialization(requester); + if (!init_timeout) remove(COMMIT_MARKER); + } + + int end = argc > 3 ? 2 : argc - 1; + + // if initial communication failed, pass through execution of script + if (init_timeout) { + int ret = pass_through(argv, end); + return ret; + } + + for (int i = end; i > 0 ; i--) { + strncat(&string_node_data[0], argv[i], 127); + } + + char error_code[1]; + debug_print("Sending node data ...\n"); + char *string_node_data_msg = mkjson(MKJSON_OBJ, 2, + MKJSON_STRING, "type", "node", + MKJSON_STRING, "data", &string_node_data[0]); + + zmq_send(requester, string_node_data_msg, strlen(string_node_data_msg), 0); + zmq_recv(requester, error_code, 1, 0); + debug_print("Received node data receipt\n"); + + int err = (int)error_code[0]; + + free(string_node_data_msg); + + zmq_close(requester); + zmq_ctx_destroy(context); + + if (err & PASS) { + debug_print("Received PASS\n"); + int ret = pass_through(argv, end); + return ret; + } + + if (err & ERROR_DAEMON) { + debug_print("Received ERROR_DAEMON\n"); + int ret = pass_through(argv, end); + return ret; + } + + if (err & ERROR_COMMIT) { + debug_print("Received ERROR_COMMIT\n"); + return -1; + } + + return 0; +} + +int initialization(void* Requester) +{ + char *active_str = NULL; + size_t active_len = 0; + + char *session_str = NULL; + size_t session_len = 0; + + char *empty_string = "\n"; + + char buffer[16]; + + struct sigaction sa; + struct itimerval timer, none_timer; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = &timer_handler; + sigaction(SIGALRM, &sa, NULL); + + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = 10000; + timer.it_interval.tv_sec = timer.it_interval.tv_usec = 0; + none_timer.it_value.tv_sec = none_timer.it_value.tv_usec = 0; + none_timer.it_interval.tv_sec = none_timer.it_interval.tv_usec = 0; + + double prev_time_value, time_value; + double time_diff; + + debug_print("Sending init announcement\n"); + char *init_announce = mkjson(MKJSON_OBJ, 1, + MKJSON_STRING, "type", "init"); + + // check for timeout on initial contact + while (!init_alarm) { + debug_call(prev_time_value = get_posix_clock_time()); + + setitimer(ITIMER_REAL, &timer, NULL); + + zmq_send(Requester, init_announce, strlen(init_announce), 0); + zmq_recv(Requester, buffer, 16, 0); + + setitimer(ITIMER_REAL, &none_timer, &timer); + + debug_call(time_value = get_posix_clock_time()); + + debug_print("Received init receipt\n"); + debug_call(time_diff = time_value - prev_time_value); + debug_print("time elapse %f\n", time_diff); + + break; + } + + free(init_announce); + + if (timeout) return -1; + + FILE *fp_a = popen(GET_ACTIVE, "r"); + getdelim(&active_str, &active_len, '\0', fp_a); + int ret = pclose(fp_a); + + if (!ret) { + debug_print("Sending active config\n"); + zmq_send(Requester, active_str, active_len - 1, 0); + zmq_recv(Requester, buffer, 16, 0); + debug_print("Received active receipt\n"); + } else { + debug_print("Sending empty active config\n"); + zmq_send(Requester, empty_string, 0, 0); + zmq_recv(Requester, buffer, 16, 0); + debug_print("Received active receipt\n"); + } + + free(active_str); + + FILE *fp_s = popen(GET_SESSION, "r"); + getdelim(&session_str, &session_len, '\0', fp_s); + pclose(fp_s); + + debug_print("Sending session config\n"); + zmq_send(Requester, session_str, session_len - 1, 0); + zmq_recv(Requester, buffer, 16, 0); + debug_print("Received session receipt\n"); + + free(session_str); + + return 0; +} + +int pass_through(char **argv, int end) +{ + char *newargv[] = { NULL, NULL }; + pid_t child_pid; + + newargv[0] = argv[end]; + if (end > 1) { + putenv(argv[end - 1]); + } + + debug_print("pass-through invoked\n"); + + if ((child_pid=fork()) < 0) { + debug_print("fork() failed\n"); + return -1; + } else if (child_pid == 0) { + if (-1 == execv(argv[end], newargv)) { + debug_print("pass_through execve failed %s: %s\n", + argv[end], strerror(errno)); + return -1; + } + } else if (child_pid > 0) { + int status; + pid_t wait_pid = waitpid(child_pid, &status, 0); + if (wait_pid < 0) { + debug_print("waitpid() failed\n"); + return -1; + } else if (wait_pid == child_pid) { + if (WIFEXITED(status)) { + debug_print("child exited with code %d\n", + WEXITSTATUS(status)); + return WEXITSTATUS(status); + } + } + } + + return 0; +} + +void timer_handler(int signum) +{ + debug_print("timer_handler invoked\n"); + timeout = 1; + init_alarm = 1; + + return; +} + +#ifdef _POSIX_MONOTONIC_CLOCK +double get_posix_clock_time(void) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + return (double) (ts.tv_sec + ts.tv_nsec / 1000000000.0); + } else { + return 0; + } +} +#else +double get_posix_clock_time(void) +{return (double)0;} +#endif -- cgit v1.2.3