summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/openvpn/server.conf.tmpl4
-rw-r--r--interface-definitions/interfaces-openvpn.xml.in6
-rw-r--r--python/vyos/util.py35
-rwxr-xr-xsrc/conf_mode/host_name.py16
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py68
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py7
-rwxr-xr-xsrc/conf_mode/snmp.py20
-rwxr-xr-xsrc/conf_mode/system-login.py8
-rw-r--r--src/etc/systemd/system/pdns-recursor.service.d/override.conf2
-rwxr-xr-xsrc/op_mode/dns_forwarding_reset.py6
-rwxr-xr-xsrc/op_mode/dns_forwarding_statistics.py7
-rwxr-xr-xsrc/system/on-dhcp-event.sh2
12 files changed, 97 insertions, 84 deletions
diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl
index a9dacd36e..e2f9062a1 100644
--- a/data/templates/openvpn/server.conf.tmpl
+++ b/data/templates/openvpn/server.conf.tmpl
@@ -78,10 +78,10 @@ topology {% if server_topology == 'point-to-point' %}p2p{% else %}{{ server_topo
mode server
tls-server
{%- else %}
-server {{ server_subnet }}{% if server_pool_start %} nopool{% endif %}
+server {{ server_subnet }} nopool
{%- endif %}
-{%- if server_pool_start %}
+{%- if server_pool %}
ifconfig-pool {{ server_pool_start }} {{ server_pool_stop }}{% if server_pool_netmask %} {{ server_pool_netmask }}{% endif %}
{%- endif %}
diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in
index d926876f7..574a3a58c 100644
--- a/interface-definitions/interfaces-openvpn.xml.in
+++ b/interface-definitions/interfaces-openvpn.xml.in
@@ -449,6 +449,12 @@
<help>Pool of client IP addresses</help>
</properties>
<children>
+ <leafNode name="disable">
+ <properties>
+ <help>Disable client IP pool</help>
+ <valueless/>
+ </properties>
+ </leafNode>
<leafNode name="start">
<properties>
<help>First IP address in the pool</help>
diff --git a/python/vyos/util.py b/python/vyos/util.py
index 49c47cd85..eb78c4a26 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -14,20 +14,16 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import os
-import re
-import sys
-from subprocess import Popen
-from subprocess import PIPE
-from subprocess import STDOUT
-from subprocess import DEVNULL
-from vyos import debug
+#
+# NOTE: Do not import full classes here, move your import to the function
+# where it is used so it is as local as possible to the execution
+#
# There is many (too many) ways to run command with python
# os.system, subprocess.Popen, subproces.{run,call,check_output}
# which all have slighty different behaviour
-
-
+from subprocess import Popen, PIPE, STDOUT, DEVNULL
def popen(command, flag='', shell=None, input=None, timeout=None, env=None,
stdout=PIPE, stderr=None, decode=None):
"""
@@ -57,7 +53,7 @@ def popen(command, flag='', shell=None, input=None, timeout=None, env=None,
to get both stdout, and stderr: popen('command', stdout=PIPE, stderr=STDOUT)
to discard stdout and get stderr: popen('command', stdout=DEVNUL, stderr=PIPE)
"""
-
+ from vyos import debug
# log if the flag is set, otherwise log if command is set
if not debug.enabled(flag):
flag = 'command'
@@ -229,6 +225,7 @@ def colon_separated_to_dict(data_string, uniquekeys=False):
If uniquekeys=True, then dict entries are always strings,
otherwise they are always lists of strings.
"""
+ import re
key_value_re = re.compile('([^:]+)\s*\:\s*(.*)')
data_raw = re.split('\n', data_string)
@@ -268,6 +265,17 @@ def process_running(pid_file):
return pid_exists(int(pid))
+def process_named_running(name):
+ """ Checks if process with given name is running and returns its PID.
+ If Process is not running, return None
+ """
+ from psutil import process_iter
+ for p in process_iter():
+ if name in p.name():
+ return p.pid
+ return None
+
+
def seconds_to_human(s, separator=""):
""" Converts number of seconds passed to a human-readable
interval such as 1w4d18h35m59s
@@ -317,6 +325,7 @@ def get_cfg_group_id():
def file_is_persistent(path):
+ import re
if not re.match(r'^(/config|/opt/vyatta/etc/config)', os.path.dirname(path)):
warning = "Warning: file {0} is outside the /config directory\n".format(path)
warning += "It will not be automatically migrated to a new image on system update"
@@ -373,9 +382,10 @@ def wait_for_commit_lock():
def ask_yes_no(question, default=False) -> bool:
"""Ask a yes/no question via input() and return their answer."""
+ from sys import stdout
default_msg = "[Y/n]" if default else "[y/N]"
while True:
- sys.stdout.write("%s %s " % (question, default_msg))
+ stdout.write("%s %s " % (question, default_msg))
c = input().lower()
if c == '':
return default
@@ -384,7 +394,7 @@ def ask_yes_no(question, default=False) -> bool:
elif c in ("n", "no"):
return False
else:
- sys.stdout.write("Please respond with yes/y or no/n\n")
+ stdout.write("Please respond with yes/y or no/n\n")
def is_admin() -> bool:
@@ -402,6 +412,7 @@ def mac2eui64(mac, prefix=None):
IPv6 address.
Thankfully copied from https://gist.github.com/wido/f5e32576bb57b5cc6f934e177a37a0d3
"""
+ import re
from ipaddress import ip_network
# http://tools.ietf.org/html/rfc4291#section-2.5.1
eui64 = re.sub(r'[.:-]', '', mac).lower()
diff --git a/src/conf_mode/host_name.py b/src/conf_mode/host_name.py
index dd5819f9f..a669580ae 100755
--- a/src/conf_mode/host_name.py
+++ b/src/conf_mode/host_name.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018 VyOS maintainers and contributors
+# 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
@@ -13,8 +13,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#
"""
conf-mode script for 'system host-name' and 'system domain-name'.
@@ -33,10 +31,7 @@ import vyos.hostsd_client
from vyos.config import Config
from vyos import ConfigError
-from vyos.util import cmd
-from vyos.util import call
-from vyos.util import run
-
+from vyos.util import cmd, call, run, process_named_running
default_config_data = {
'hostname': 'vyos',
@@ -166,12 +161,11 @@ def apply(config):
call("systemctl restart rsyslog.service")
# If SNMP is running, restart it too
- ret = run("pgrep snmpd")
- if ret == 0:
- call("systemctl restart snmpd.service")
+ if process_named_running('snmpd'):
+ call('systemctl restart snmpd.service')
# restart pdns if it is used
- ret = run('/usr/bin/rec_control ping')
+ ret = run('/usr/bin/rec_control --socket-dir=/run/powerdns ping')
if ret == 0:
call('systemctl restart pdns-recursor.service')
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index b42765586..435e8a8f0 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -72,14 +72,14 @@ default_config_data = {
'server_domain': '',
'server_max_conn': '',
'server_dns_nameserver': [],
- 'server_pool': False,
+ 'server_pool': True,
'server_pool_start': '',
'server_pool_stop': '',
'server_pool_netmask': '',
'server_push_route': [],
'server_reject_unconfigured': False,
'server_subnet': '',
- 'server_topology': 'net30',
+ 'server_topology': '',
'shared_secret_file': '',
'tls': False,
'tls_auth': '',
@@ -124,13 +124,10 @@ def getDefaultServer(network, topology, devtype):
Logic from openvpn's src/openvpn/helper.c.
Returns a dict with addresses or False if the input parameters were incorrect.
"""
- if not (topology and devtype):
- return False
-
if not (devtype == 'tun' or devtype == 'tap'):
return False
- if not network.prefixlen:
+ if not network.version == 4:
return False
elif (devtype == 'tun' and network.prefixlen > 29) or (devtype == 'tap' and network.prefixlen > 30):
return False
@@ -198,6 +195,10 @@ def get_config():
if intf == openvpn['intf']:
openvpn['bridge_member'].append(intf)
+ # bridged server should not have a pool by default (but can be specified manually)
+ if openvpn['bridge_member']:
+ openvpn['server_pool'] = False
+
# set configuration level
conf.set_level('interfaces openvpn ' + openvpn['intf'])
@@ -345,6 +346,7 @@ def get_config():
openvpn['server_topology'] = conf.return_value('server topology')
# Server-mode subnet (from which client IPs are allocated)
+ server_network = None
if conf.exists('server subnet'):
# server_network is used later in this function
server_network = IPv4Network(conf.return_value('server subnet'))
@@ -388,16 +390,22 @@ def get_config():
# Server client IP pool
if conf.exists('server client-ip-pool'):
- openvpn['server_pool'] = True
+ conf.set_level('interfaces openvpn ' + openvpn['intf'] + ' server client-ip-pool')
+
+ # enable or disable server_pool where necessary
+ # default is enabled, or disabled in bridge mode
+ openvpn['server_pool'] = not conf.exists('disable')
- if conf.exists('server client-ip-pool start'):
- openvpn['server_pool_start'] = conf.return_value('server client-ip-pool start')
+ if conf.exists('start'):
+ openvpn['server_pool_start'] = conf.return_value('start')
- if conf.exists('server client-ip-pool stop'):
- openvpn['server_pool_stop'] = conf.return_value('server client-ip-pool stop')
+ if conf.exists('stop'):
+ openvpn['server_pool_stop'] = conf.return_value('stop')
- if conf.exists('server client-ip-pool netmask'):
- openvpn['server_pool_netmask'] = conf.return_value('server client-ip-pool netmask')
+ if conf.exists('netmask'):
+ openvpn['server_pool_netmask'] = conf.return_value('netmask')
+
+ conf.set_level('interfaces openvpn ' + openvpn['intf'])
# DNS suffix to be pushed to all clients
if conf.exists('server domain-name'):
@@ -476,25 +484,30 @@ def get_config():
if not openvpn['tls_dh'] and openvpn['tls_key'] and checkCertHeader('-----BEGIN EC PRIVATE KEY-----', openvpn['tls_key']):
openvpn['tls_dh'] = 'none'
+ # set default server topology to net30
+ if openvpn['mode'] == 'server' and not openvpn['server_topology']:
+ openvpn['server_topology'] = 'net30'
+
# Set defaults where necessary.
- # If any of the input parameters are missing or wrong,
+ # If any of the input parameters are wrong,
# this will return False and no defaults will be set.
- default_server = getDefaultServer(server_network, openvpn['server_topology'], openvpn['type'])
- if default_server:
- # server-bridge doesn't require a pool so don't set defaults for it
- if not openvpn['bridge_member']:
- openvpn['server_pool'] = True
- if not openvpn['server_pool_start']:
- openvpn['server_pool_start'] = default_server['pool_start']
+ if server_network and openvpn['server_topology'] and openvpn['type']:
+ default_server = None
+ default_server = getDefaultServer(server_network, openvpn['server_topology'], openvpn['type'])
+ if default_server:
+ # server-bridge doesn't require a pool so don't set defaults for it
+ if openvpn['server_pool'] and not openvpn['bridge_member']:
+ if not openvpn['server_pool_start']:
+ openvpn['server_pool_start'] = default_server['pool_start']
- if not openvpn['server_pool_stop']:
- openvpn['server_pool_stop'] = default_server['pool_stop']
+ if not openvpn['server_pool_stop']:
+ openvpn['server_pool_stop'] = default_server['pool_stop']
- if not openvpn['server_pool_netmask']:
- openvpn['server_pool_netmask'] = default_server['pool_netmask']
+ if not openvpn['server_pool_netmask']:
+ openvpn['server_pool_netmask'] = default_server['pool_netmask']
- for client in openvpn['client']:
- client['remote_netmask'] = default_server['client_remote_netmask']
+ for client in openvpn['client']:
+ client['remote_netmask'] = default_server['client_remote_netmask']
return openvpn
@@ -606,7 +619,6 @@ def verify(openvpn):
if not openvpn['bridge_member']:
raise ConfigError('Must specify "server subnet" or "bridge member interface" in server mode')
-
if openvpn['server_pool']:
if not (openvpn['server_pool_start'] and openvpn['server_pool_stop']):
raise ConfigError('Server client-ip-pool requires both start and stop addresses in bridged mode')
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index c51048aeb..06c2ea29b 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -19,6 +19,7 @@ import netifaces
from sys import exit
from copy import deepcopy
+from netifaces import interfaces
from vyos.config import Config
from vyos.ifconfig import Interface, GREIf, GRETapIf, IPIPIf, IP6GREIf, IPIP6If, IP6IP6If, SitIf, Sit6RDIf
@@ -506,6 +507,12 @@ def verify(conf):
if ipv6_count and not IP6 in kls.ip:
print(f'Should not use IPv6 addresses on tunnel {iftype} {ifname}')
+ # vrf check
+
+ vrf = options['vrf']
+ if vrf and vrf not in interfaces():
+ raise ConfigError(f'VRF "{vrf}" does not exist')
+
# tunnel encapsulation check
convert = {
diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py
index d654dcb84..7530da2dc 100755
--- a/src/conf_mode/snmp.py
+++ b/src/conf_mode/snmp.py
@@ -535,23 +535,9 @@ def apply(snmp):
# start SNMP daemon
call("systemctl restart snmpd.service")
- # Passwords are not available immediately in the configuration file,
- # after daemon startup - we wait until they have been processed by
- # snmpd, which we see when a magic line appears in this file.
- while True:
- while not os.path.exists(config_file_user):
- sleep(0.5)
-
- try:
- with open(config_file_user, 'r') as f:
- for line in f:
- # Search for our magic string inside the file
- if 'usmUser' in line:
- break
- except IOError:
- continue
- else:
- break
+ while (call('systemctl -q is-active snmpd.service') != 0):
+ print("service not yet started")
+ sleep(0.5)
# net-snmp is now regenerating the configuration file in the background
# thus we need to re-open and re-read the file as the content changed.
diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py
index 6008ca0b3..91e2b369f 100755
--- a/src/conf_mode/system-login.py
+++ b/src/conf_mode/system-login.py
@@ -16,6 +16,7 @@
import os
+from crypt import crypt, METHOD_SHA512
from psutil import users
from pwd import getpwall, getpwnam
from stat import S_IRUSR, S_IWUSR, S_IRWXU, S_IRGRP, S_IXGRP
@@ -52,11 +53,6 @@ def get_local_users():
return local_users
-
-def get_crypt_pw(password):
- return cmd(f'/usr/bin/mkpasswd --method=sha-512 {password}')
-
-
def get_config():
login = default_config_data
conf = Config()
@@ -204,7 +200,7 @@ def generate(login):
# calculate users encrypted password
for user in login['add_users']:
if user['password_plaintext']:
- user['password_encrypted'] = get_crypt_pw(user['password_plaintext'])
+ user['password_encrypted'] = crypt(user['password_plaintext'], METHOD_SHA512)
user['password_plaintext'] = ''
# remove old plaintext password
diff --git a/src/etc/systemd/system/pdns-recursor.service.d/override.conf b/src/etc/systemd/system/pdns-recursor.service.d/override.conf
index 602d7b774..ef4dec303 100644
--- a/src/etc/systemd/system/pdns-recursor.service.d/override.conf
+++ b/src/etc/systemd/system/pdns-recursor.service.d/override.conf
@@ -2,4 +2,4 @@
WorkingDirectory=
WorkingDirectory=/run/powerdns
ExecStart=
-ExecStart=/usr/sbin/pdns_recursor --daemon=no --write-pid=no --disable-syslog --log-timestamp=no --config-dir=/run/powerdns
+ExecStart=/usr/sbin/pdns_recursor --daemon=no --write-pid=no --disable-syslog --log-timestamp=no --config-dir=/run/powerdns --socket-dir=/run/powerdns
diff --git a/src/op_mode/dns_forwarding_reset.py b/src/op_mode/dns_forwarding_reset.py
index 8e2ee546c..bfc640a26 100755
--- a/src/op_mode/dns_forwarding_reset.py
+++ b/src/op_mode/dns_forwarding_reset.py
@@ -27,6 +27,8 @@ from sys import exit
from vyos.config import Config
from vyos.util import call
+PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns'
+
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Reset all cache")
parser.add_argument("domain", type=str, nargs="?", help="Domain to reset cache entries for")
@@ -41,11 +43,11 @@ if __name__ == '__main__':
exit(0)
if args.all:
- call("rec_control wipe-cache \'.$\'")
+ call(f"{PDNS_CMD} wipe-cache \'.$\'")
exit(0)
elif args.domain:
- call("rec_control wipe-cache \'{0}$\'".format(args.domain))
+ call(f"{PDNS_CMD} wipe-cache \'{0}$\'".format(args.domain))
else:
parser.print_help()
diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py
index c400a72cd..8ae92beb7 100755
--- a/src/op_mode/dns_forwarding_statistics.py
+++ b/src/op_mode/dns_forwarding_statistics.py
@@ -1,12 +1,12 @@
#!/usr/bin/env python3
import jinja2
-import sys
+from sys import exit
from vyos.config import Config
from vyos.config import cmd
-PDNS_CMD='/usr/bin/rec_control'
+PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns'
OUT_TMPL_SRC = """
DNS forwarding statistics:
@@ -16,13 +16,12 @@ Cache size: {{ cache_size }} kbytes
"""
-
if __name__ == '__main__':
# Do nothing if service is not configured
c = Config()
if not c.exists_effective('service dns forwarding'):
print("DNS forwarding is not configured")
- sys.exit(0)
+ exit(0)
data = {}
diff --git a/src/system/on-dhcp-event.sh b/src/system/on-dhcp-event.sh
index 5046912a6..385ae460f 100755
--- a/src/system/on-dhcp-event.sh
+++ b/src/system/on-dhcp-event.sh
@@ -63,7 +63,7 @@ if [ $changes -gt 0 ]; then
echo Success
pid=`pgrep pdns_recursor`
if [ -n "$pid" ]; then
- sudo rec_control reload-zones
+ sudo rec_control --socket-dir=/run/powerdns reload-zones
fi
else
echo No changes made