summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRitika Chopra <r.chopra@vyos.io>2026-05-27 11:33:57 -0500
committerRitika Chopra <r.chopra@vyos.io>2026-08-12 14:50:06 -0700
commit28ea92afb73a6627c2050474187ace25bb5e3e4e (patch)
treeda575500828fba952844d02259307beb42fa4943 /src
parentba8924dd23477c4fb9635858b23e9945f9b4ddbd (diff)
downloadvyos-1x-28ea92afb73a6627c2050474187ace25bb5e3e4e.tar.gz
vyos-1x-28ea92afb73a6627c2050474187ace25bb5e3e4e.zip
T8598: CLI support to configure a secret which will be used along with calling-station-id, to generate Peer Interface Identifier (IID) (BP 2188)
(cherry picked from commit 5354959b60c97df699ad14ef561ab9aa92b37922)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/service_pppoe-server.py27
-rwxr-xr-xsrc/conf_mode/vpn_l2tp.py22
-rwxr-xr-xsrc/conf_mode/vpn_pptp.py22
-rwxr-xr-xsrc/conf_mode/vpn_sstp.py22
4 files changed, 93 insertions, 0 deletions
diff --git a/src/conf_mode/service_pppoe-server.py b/src/conf_mode/service_pppoe-server.py
index 1f6f6ecc7..5a59df372 100755
--- a/src/conf_mode/service_pppoe-server.py
+++ b/src/conf_mode/service_pppoe-server.py
@@ -41,6 +41,17 @@ airbag.enable()
pppoe_conf = r'/run/accel-pppd/pppoe.conf'
pppoe_chap_secrets = r'/run/accel-pppd/pppoe.chap-secrets'
+iid_secret_min_len = 16
+iid_secret_max_len = 128
+
+
+def _is_safe_ascii_secret(value):
+ # Restrict to ASCII printable non-whitespace characters.
+ return value.isascii() and all(ch.isprintable() and not ch.isspace() for ch in value)
+
+
+def _is_valid_iid_secret(value):
+ return iid_secret_min_len <= len(value) <= iid_secret_max_len and _is_safe_ascii_secret(value)
def base_ifname(ifname):
@@ -127,6 +138,11 @@ def get_config(config=None):
is_node_changed(conf, base + ['authentication', 'radius']),
is_node_changed(conf, base + ['authentication', 'mode']),
is_node_changed(conf, base + ['authentication', 'protocols']),
+
+ # IPv6 peer IID mode/secret affect negotiated session state.
+ # Restart is required to force existing sessions to re-negotiate.
+ is_node_changed(conf, base + ['ppp-options', 'ipv6-peer-interface-id']),
+ is_node_changed(conf, base + ['ppp-options', 'ipv6-peer-interface-id-secret']),
any(
base_ifname(iface) in all_changed_vpp_ifaces
for iface in pppoe.get('interface', {})
@@ -175,6 +191,17 @@ def verify(pppoe):
verify_accel_ppp_wins_servers(pppoe)
verify_pado_delay(pppoe)
+ peer_id_mode = dict_search('ppp_options.ipv6_peer_interface_id', pppoe)
+ peer_id_secret = dict_search('ppp_options.ipv6_peer_interface_id_secret', pppoe)
+ if peer_id_mode == 'calling-sid':
+ if not peer_id_secret:
+ raise ConfigError('ppp-options ipv6-peer-interface-id calling-sid requires ipv6-peer-interface-id-secret')
+ if not _is_valid_iid_secret(peer_id_secret):
+ raise ConfigError(
+ f'ppp-options ipv6-peer-interface-id-secret must be {iid_secret_min_len} to '
+ f'{iid_secret_max_len} printable non-whitespace ASCII characters'
+ )
+
if 'interface' not in pppoe:
raise ConfigError('At least one listen interface must be defined!')
diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py
index d6f5e4c28..bf4c9eadd 100755
--- a/src/conf_mode/vpn_l2tp.py
+++ b/src/conf_mode/vpn_l2tp.py
@@ -37,6 +37,17 @@ airbag.enable()
l2tp_conf = '/run/accel-pppd/l2tp.conf'
l2tp_chap_secrets = '/run/accel-pppd/l2tp.chap-secrets'
+iid_secret_min_len = 16
+iid_secret_max_len = 128
+
+
+def _is_safe_ascii_secret(value):
+ # Restrict to ASCII printable non-whitespace characters.
+ return value.isascii() and all(ch.isprintable() and not ch.isspace() for ch in value)
+
+
+def _is_valid_iid_secret(value):
+ return iid_secret_min_len <= len(value) <= iid_secret_max_len and _is_safe_ascii_secret(value)
def get_config(config=None):
if config:
@@ -69,6 +80,17 @@ def verify(l2tp):
verify_accel_ppp_name_servers(l2tp)
verify_accel_ppp_wins_servers(l2tp)
+ peer_id_mode = dict_search('ppp_options.ipv6_peer_interface_id', l2tp)
+ peer_id_secret = dict_search('ppp_options.ipv6_peer_interface_id_secret', l2tp)
+ if peer_id_mode == 'calling-sid':
+ if not peer_id_secret:
+ raise ConfigError('ppp-options ipv6-peer-interface-id calling-sid requires ipv6-peer-interface-id-secret')
+ if not _is_valid_iid_secret(peer_id_secret):
+ raise ConfigError(
+ f'ppp-options ipv6-peer-interface-id-secret must be {iid_secret_min_len} to '
+ f'{iid_secret_max_len} printable non-whitespace ASCII characters'
+ )
+
return None
diff --git a/src/conf_mode/vpn_pptp.py b/src/conf_mode/vpn_pptp.py
index c11619779..ff96ff95a 100755
--- a/src/conf_mode/vpn_pptp.py
+++ b/src/conf_mode/vpn_pptp.py
@@ -35,6 +35,17 @@ airbag.enable()
pptp_conf = '/run/accel-pppd/pptp.conf'
pptp_chap_secrets = '/run/accel-pppd/pptp.chap-secrets'
+iid_secret_min_len = 16
+iid_secret_max_len = 128
+
+
+def _is_safe_ascii_secret(value):
+ # Restrict to ASCII printable non-whitespace characters.
+ return value.isascii() and all(ch.isprintable() and not ch.isspace() for ch in value)
+
+
+def _is_valid_iid_secret(value):
+ return iid_secret_min_len <= len(value) <= iid_secret_max_len and _is_safe_ascii_secret(value)
def get_config(config=None):
@@ -67,6 +78,17 @@ def verify(pptp):
verify_accel_ppp_name_servers(pptp)
verify_accel_ppp_wins_servers(pptp)
+ peer_id_mode = dict_search('ppp_options.ipv6_peer_interface_id', pptp)
+ peer_id_secret = dict_search('ppp_options.ipv6_peer_interface_id_secret', pptp)
+ if peer_id_mode == 'calling-sid':
+ if not peer_id_secret:
+ raise ConfigError('ppp-options ipv6-peer-interface-id calling-sid requires ipv6-peer-interface-id-secret')
+ if not _is_valid_iid_secret(peer_id_secret):
+ raise ConfigError(
+ f'ppp-options ipv6-peer-interface-id-secret must be {iid_secret_min_len} to '
+ f'{iid_secret_max_len} printable non-whitespace ASCII characters'
+ )
+
def generate(pptp):
if not pptp:
diff --git a/src/conf_mode/vpn_sstp.py b/src/conf_mode/vpn_sstp.py
index 5382fc711..a4e84c42f 100755
--- a/src/conf_mode/vpn_sstp.py
+++ b/src/conf_mode/vpn_sstp.py
@@ -46,6 +46,17 @@ sstp_chap_secrets = '/run/accel-pppd/sstp.chap-secrets'
cert_file_path = os.path.join(cfg_dir, 'sstp-cert.pem')
cert_key_path = os.path.join(cfg_dir, 'sstp-cert.key')
ca_cert_file_path = os.path.join(cfg_dir, 'sstp-ca.pem')
+iid_secret_min_len = 16
+iid_secret_max_len = 128
+
+
+def _is_safe_ascii_secret(value):
+ # Restrict to ASCII printable non-whitespace characters.
+ return value.isascii() and all(ch.isprintable() and not ch.isspace() for ch in value)
+
+
+def _is_valid_iid_secret(value):
+ return iid_secret_min_len <= len(value) <= iid_secret_max_len and _is_safe_ascii_secret(value)
def get_config(config=None):
@@ -82,6 +93,17 @@ def verify(sstp):
verify_accel_ppp_name_servers(sstp)
verify_accel_ppp_wins_servers(sstp)
+ peer_id_mode = dict_search('ppp_options.ipv6_peer_interface_id', sstp)
+ peer_id_secret = dict_search('ppp_options.ipv6_peer_interface_id_secret', sstp)
+ if peer_id_mode == 'calling-sid':
+ if not peer_id_secret:
+ raise ConfigError('ppp-options ipv6-peer-interface-id calling-sid requires ipv6-peer-interface-id-secret')
+ if not _is_valid_iid_secret(peer_id_secret):
+ raise ConfigError(
+ f'ppp-options ipv6-peer-interface-id-secret must be {iid_secret_min_len} to '
+ f'{iid_secret_max_len} printable non-whitespace ASCII characters'
+ )
+
if 'ssl' not in sstp:
raise ConfigError('SSL missing on SSTP config!')