From 4c9d0ec3ac7b88af225118b60f5aa01e6f3d29f1 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 6 Oct 2019 17:20:34 +0200 Subject: wireless: T1627: initial rewrite in XML/Python style Working: - Wireless modes b, g, n, ac - WPA/WPA2 psk and RADIUS (tested using Microsoft NPS) --- src/migration-scripts/interfaces/3-to-4 | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100755 src/migration-scripts/interfaces/3-to-4 (limited to 'src/migration-scripts') diff --git a/src/migration-scripts/interfaces/3-to-4 b/src/migration-scripts/interfaces/3-to-4 new file mode 100755 index 000000000..4a2fd9c0d --- /dev/null +++ b/src/migration-scripts/interfaces/3-to-4 @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +# Change syntax of wireless interfaces +# Migrate boolean nodes to valueless + +import sys +from vyos.configtree import ConfigTree + +if (len(sys.argv) < 1): + print("Must specify file name!") + sys.exit(1) + +file_name = sys.argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) +base = ['interfaces', 'wireless'] + +if not config.exists(base): + # Nothing to do + sys.exit(0) +else: + for wifi in config.list_nodes(base): + # as converting a node to bool is always the same, we can script it + to_bool_nodes = ['capabilities ht 40MHz-incapable', 'capabilities ht auto-powersave', + 'capabilities ht delayed-block-ack', 'capabilities ht dsss-cck-40', + 'capabilities ht greenfield', 'capabilities ht ldpc', 'capabilities ht lsig-protection', + 'capabilities ht stbc tx', 'capabilities require-ht', 'capabilities require-vht', + 'capabilities vht antenna-pattern-fixed', 'capabilities vht ldpc', + 'capabilities vht stbc tx', 'capabilities vht tx-powersave', + 'capabilities vht vht-cf', 'expunge-failing-stations', 'isolate-stations'] + + for node in to_bool_nodes: + if config.exists(base + [wifi, node]): + tmp = config.return_value(base + [wifi, node]) + # delete old node + config.delete(base + [wifi, node]) + if tmp == 'true': + config.set(base + [wifi, node]) + + if config.exists(base + [wifi, 'debug']): + tmp = config.return_value(base + [wifi, 'debug']) + config.delete(base + [wifi, 'debug']) + + try: + with open(file_name, 'w') as f: + f.write(config.to_string()) + except OSError as e: + print("Failed to save the modified config: {}".format(e)) + sys.exit(1) -- cgit v1.2.3 From 3308bc150646abcf523c001a7b6086c46703b204 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 18 Nov 2019 16:07:37 +0100 Subject: wireless: T1627: config migrator does not support camel casing convert all nodes to lowercase --- interface-definitions/interfaces-wireless.xml | 2 +- src/migration-scripts/interfaces/3-to-4 | 30 +++++++++++++++++++-------- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'src/migration-scripts') diff --git a/interface-definitions/interfaces-wireless.xml b/interface-definitions/interfaces-wireless.xml index c9b9618e8..4d098ac37 100644 --- a/interface-definitions/interfaces-wireless.xml +++ b/interface-definitions/interfaces-wireless.xml @@ -43,7 +43,7 @@ HT (High Throughput) settings - + 40MHz intolerance, use 20MHz only! diff --git a/src/migration-scripts/interfaces/3-to-4 b/src/migration-scripts/interfaces/3-to-4 index 4a2fd9c0d..8b9bf7f96 100755 --- a/src/migration-scripts/interfaces/3-to-4 +++ b/src/migration-scripts/interfaces/3-to-4 @@ -24,24 +24,36 @@ if not config.exists(base): else: for wifi in config.list_nodes(base): # as converting a node to bool is always the same, we can script it - to_bool_nodes = ['capabilities ht 40MHz-incapable', 'capabilities ht auto-powersave', - 'capabilities ht delayed-block-ack', 'capabilities ht dsss-cck-40', - 'capabilities ht greenfield', 'capabilities ht ldpc', 'capabilities ht lsig-protection', - 'capabilities ht stbc tx', 'capabilities require-ht', 'capabilities require-vht', - 'capabilities vht antenna-pattern-fixed', 'capabilities vht ldpc', - 'capabilities vht stbc tx', 'capabilities vht tx-powersave', - 'capabilities vht vht-cf', 'expunge-failing-stations', 'isolate-stations'] + to_bool_nodes = ['capabilities ht 40MHz-incapable', + 'capabilities ht auto-powersave', + 'capabilities ht delayed-block-ack', + 'capabilities ht dsss-cck-40', + 'capabilities ht greenfield', + 'capabilities ht ldpc', + 'capabilities ht lsig-protection', + 'capabilities ht stbc tx', + 'capabilities require-ht', + 'capabilities require-vht', + 'capabilities vht antenna-pattern-fixed', + 'capabilities vht ldpc', + 'capabilities vht stbc tx', + 'capabilities vht tx-powersave', + 'capabilities vht vht-cf', + 'expunge-failing-stations', + 'isolate-stations'] for node in to_bool_nodes: if config.exists(base + [wifi, node]): tmp = config.return_value(base + [wifi, node]) # delete old node config.delete(base + [wifi, node]) + # set new node if it was enabled if tmp == 'true': - config.set(base + [wifi, node]) + # OLD CLI used camel casing in 40MHz-incapable which is + # not supported in the new backend. Convert all to lower-case + config.set(base + [wifi, node.lower()]) if config.exists(base + [wifi, 'debug']): - tmp = config.return_value(base + [wifi, 'debug']) config.delete(base + [wifi, 'debug']) try: -- cgit v1.2.3 From dfa2f0e8ecd8a117bf47b64d7099d613f487d799 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 18 Nov 2019 21:07:07 +0100 Subject: wireless: T1627: change RADIUS CLI syntax Adopt RADIUS configuration and harmonize it with the rest of VyOS. Move the following configuration block: security { wpa { cipher CCMP mode wpa2 radius-server 172.16.100.10 { port 1812 secret secretkey } radius-server 172.16.100.11 { port 1812 secret secretkey } } } to the harmonized version of: security { wpa { cipher CCMP mode wpa2 radius { server 172.16.100.10 { port 1812 secret secretkey } server 172.16.100.11 { port 1812 secret secretkey } } } } And add the new "set interfaces wireless wlan0 security wpa radius source-address" CLI command to specify the origin of any RADIUS query on systems having multiple IP addresses. --- interface-definitions/interfaces-wireless.xml | 65 ++++++++++++++------------- src/conf_mode/interfaces-wireless.py | 43 +++++++++++------- src/migration-scripts/interfaces/3-to-4 | 33 ++++++++++++++ 3 files changed, 94 insertions(+), 47 deletions(-) (limited to 'src/migration-scripts') diff --git a/interface-definitions/interfaces-wireless.xml b/interface-definitions/interfaces-wireless.xml index a1712cb33..f1928ee0c 100644 --- a/interface-definitions/interfaces-wireless.xml +++ b/interface-definitions/interfaces-wireless.xml @@ -744,46 +744,47 @@ Invalid WPA pass phrase, must be 8 to 63 printable characters! - + - RADIUS server authentication - - ipv4 - IPv4 address of RADIUS server - + RADIUS specific configuration - - - RADIUS server to receive accounting info (default: 1813) - - 1-65535 - RADIUS server accounting port - - - - - - - + - RADIUS server port (default: 1812) + RADIUS server - 1-65535 - RADIUS server port + ipv4 + IPv4 address of RADIUS server - - - - - - - - Secret for radius access - + + + + Enable RADIUS server to receive accounting info + + + + + + RADIUS server port (default: 1812) + + 1-65535 + RADIUS server port + + + + + + + + + RADIUS shared secret key + + + + - + diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index b25205590..3b270a064 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -633,14 +633,24 @@ ieee8021x=1 # WPA-EAP-SHA256 = WPA2-Enterprise using SHA256 wpa_key_mgmt=WPA-EAP +{% if sec_wpa_radius_source -%} +# RADIUS client forced local IP address for the access point +# Normally the local IP address is determined automatically based on configured +# IP addresses, but this field can be used to force a specific address to be +# used, e.g., when the device has multiple IP addresses. +radius_client_addr={{ sec_wpa_radius_source }} +{% endif %} + {% for radius in sec_wpa_radius -%} +# RADIUS authentication server auth_server_addr={{ radius.server }} auth_server_port={{ radius.port }} -auth_server_shared_secret={{ radius.secret }} -{% if radius.accounting -%} +auth_server_shared_secret={{ radius.key }} +{% if radius.acc_port -%} +# RADIUS accounting server acct_server_addr={{ radius.server }} acct_server_port={{ radius.acc_port }} -acct_server_shared_secret={{ radius.secret }} +acct_server_shared_secret={{ radius.key }} {% endif %} {% endfor %} @@ -1156,29 +1166,32 @@ def get_config(): if conf.exists('security wpa passphrase'): wifi['sec_wpa_passphrase'] = conf.return_value('security wpa passphrase') - # WPA radius server goes here - for server in conf.list_nodes('security wpa radius-server'): - # set new configuration level - conf.set_level(cfg_base + ' security wpa radius-server ' + server) + # WPA RADIUS source address + if conf.exists('security wpa radius source-address'): + wifi['sec_wpa_radius_source'] = conf.return_value('security wpa radius source-address') + # WPA RADIUS server + for server in conf.list_nodes('security wpa radius server'): + # set new configuration level + conf.set_level(cfg_base + ' security wpa radius server ' + server) radius = { 'server' : server, 'acc_port' : '', 'port' : 1812, - 'secret' : '' + 'key' : '' } - # receive RADIUS accounting info - if conf.exists('accounting'): - radius['acc_port'] = conf.return_value('accounting') - # RADIUS server port if conf.exists('port'): - radius['port'] = conf.return_value('port') + radius['port'] = int(conf.return_value('port')) + + # receive RADIUS accounting info + if conf.exists('accounting'): + radius['acc_port'] = radius['port'] + 1 # RADIUS server shared-secret - if conf.exists('secret'): - radius['secret'] = conf.return_value('secret') + if conf.exists('key'): + radius['key'] = conf.return_value('key') # append RADIUS server to list of servers wifi['sec_wpa_radius'].append(radius) diff --git a/src/migration-scripts/interfaces/3-to-4 b/src/migration-scripts/interfaces/3-to-4 index 8b9bf7f96..e3bd25a68 100755 --- a/src/migration-scripts/interfaces/3-to-4 +++ b/src/migration-scripts/interfaces/3-to-4 @@ -53,9 +53,42 @@ else: # not supported in the new backend. Convert all to lower-case config.set(base + [wifi, node.lower()]) + # Remove debug node if config.exists(base + [wifi, 'debug']): config.delete(base + [wifi, 'debug']) + # RADIUS servers + if config.exists(base + [wifi, 'security', 'wpa', 'radius-server']): + for server in config.list_nodes(base + [wifi, 'security', 'wpa', 'radius-server']): + base_server = base + [wifi, 'security', 'wpa', 'radius-server', server] + + # Migrate RADIUS shared secret + if config.exists(base_server + ['secret']): + key = config.return_value(base_server + ['secret']) + # write new configuration node + config.set(base + [wifi, 'security', 'wpa', 'radius', 'server', server, 'key'], value=key) + # format as tag node + config.set_tag(base + [wifi, 'security', 'wpa', 'radius', 'server']) + + # Migrate RADIUS port + if config.exists(base_server + ['port']): + port = config.return_value(base_server + ['port']) + # write new configuration node + config.set(base + [wifi, 'security', 'wpa', 'radius', 'server', server, 'port'], value=port) + # format as tag node + config.set_tag(base + [wifi, 'security', 'wpa', 'radius', 'server']) + + # Migrate RADIUS accounting + if config.exists(base_server + ['accounting']): + port = config.return_value(base_server + ['accounting']) + # write new configuration node + config.set(base + [wifi, 'security', 'wpa', 'radius', 'server', server, 'accounting']) + # format as tag node + config.set_tag(base + [wifi, 'security', 'wpa', 'radius', 'server']) + + # delete old radius-server nodes + config.delete(base + [wifi, 'security', 'wpa', 'radius-server']) + try: with open(file_name, 'w') as f: f.write(config.to_string()) -- cgit v1.2.3