summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiga Murphy <giga1699@gmail.com>2025-07-24 00:18:27 +0000
committerChristian Breunig <christian@breunig.cc>2025-12-29 07:11:33 +0100
commitbb7476e1a2f61504f274823ced93c5bb608a76c6 (patch)
tree75db95dca7a1be5d70d2ffa45a19b961bfd4c193
parent51036f9d188bd7e0061a6c8c4798fb2b0ce63297 (diff)
downloadvyos-1x-bb7476e1a2f61504f274823ced93c5bb608a76c6.tar.gz
vyos-1x-bb7476e1a2f61504f274823ced93c5bb608a76c6.zip
T7635: OpenConnect Certificate Authentication
-rw-r--r--data/templates/ocserv/ocserv_config.j29
-rw-r--r--interface-definitions/vpn_openconnect.xml.in31
-rwxr-xr-xsrc/conf_mode/vpn_openconnect.py15
3 files changed, 52 insertions, 3 deletions
diff --git a/data/templates/ocserv/ocserv_config.j2 b/data/templates/ocserv/ocserv_config.j2
index 81f777031..76d3e6e4e 100644
--- a/data/templates/ocserv/ocserv_config.j2
+++ b/data/templates/ocserv/ocserv_config.j2
@@ -30,6 +30,15 @@ auth = "plain[otp=/run/ocserv/users.oath]"
{% else %}
auth = "plain[/run/ocserv/ocpasswd]"
{% endif %}
+{% elif "certificate" in authentication.mode %}
+auth = "certificate"
+{% if authentication.mode.certificate.user_identifier_field == "cn" %}
+cert-user-oid = 2.5.4.3
+{% elif authentication.mode.certificate.user_identifier_field == "uid" %}
+cert-user-oid = 0.9.2342.19200300.100.1.1
+{% else %}
+cert-user-oid = {{ authentication.mode.certificate.user_identifier_field }}
+{% endif %}
{% else %}
auth = "plain[/run/ocserv/ocpasswd]"
{% endif %}
diff --git a/interface-definitions/vpn_openconnect.xml.in b/interface-definitions/vpn_openconnect.xml.in
index a2f040b2f..085f181fd 100644
--- a/interface-definitions/vpn_openconnect.xml.in
+++ b/interface-definitions/vpn_openconnect.xml.in
@@ -69,6 +69,37 @@
<valueless/>
</properties>
</leafNode>
+ <node name="certificate">
+ <properties>
+ <help>Use certificate based authentication</help>
+ </properties>
+ <children>
+ <leafNode name="user-identifier-field">
+ <properties>
+ <help>Defines what field in the certificate identifies the username</help>
+ <valueHelp>
+ <format>cn</format>
+ <description>OID 2.5.4.3 - Common Name</description>
+ </valueHelp>
+ <valueHelp>
+ <format>uid</format>
+ <description>OID 0.9.2342.19200300.100.1.1 - UID</description>
+ </valueHelp>
+ <valueHelp>
+ <format>x.x.xx.xxx</format>
+ <description>Custom OID in dotted decimal format</description>
+ </valueHelp>
+ <constraint>
+ <regex>(^\d{1,5}(?:\.\d{1,5})*$|cn|uid)</regex>
+ </constraint>
+ <constraintErrorMessage>Invalid OID selection. Must be cn, uid, or a valid OID format.</constraintErrorMessage>
+ <completionHelp>
+ <list>cn uid x.x.xx.xxx</list>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
</children>
</node>
<node name="identity-based-config">
diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py
index 68cd363f0..8522a325b 100755
--- a/src/conf_mode/vpn_openconnect.py
+++ b/src/conf_mode/vpn_openconnect.py
@@ -105,11 +105,17 @@ def verify(ocserv):
if 'authentication' in ocserv:
if 'mode' in ocserv['authentication']:
if (
- 'local' in ocserv['authentication']['mode']
- and 'radius' in ocserv['authentication']['mode']
+ ('local' in ocserv['authentication']['mode']
+ and 'radius' in ocserv['authentication']['mode'])
+ or
+ ('local' in ocserv['authentication']['mode']
+ and 'certificate' in ocserv['authentication']['mode'])
+ or
+ ('radius' in ocserv['authentication']['mode']
+ and 'certificate' in ocserv['authentication']['mode'])
):
raise ConfigError(
- 'OpenConnect authentication modes are mutually-exclusive, remove either local or radius from your configuration'
+ 'OpenConnect authentication modes are mutually-exclusive. Only one of local, radius, or certificate.'
)
if 'radius' in ocserv['authentication']['mode']:
if 'server' not in ocserv['authentication']['radius']:
@@ -203,6 +209,9 @@ def verify(ocserv):
raise ConfigError('SSL certificate missing on OpenConnect config!')
verify_pki_certificate(ocserv, ocserv['ssl']['certificate'])
+ if 'ca_certificate' not in ocserv['ssl'] and 'certificiate' in ocserv['authentication']['mode']:
+ raise ConfigError('CA certificate must be provided in certificate authentication mode!')
+
if 'ca_certificate' in ocserv['ssl']:
for ca_cert in ocserv['ssl']['ca_certificate']:
verify_pki_ca_certificate(ocserv, ca_cert)