diff --git a/data/templates/ocserv/ocserv_config.j2 b/data/templates/ocserv/ocserv_config.j2
index 81f7770314..76d3e6e4ee 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 a2f040b2fa..085f181fdd 100644
--- a/interface-definitions/vpn_openconnect.xml.in
+++ b/interface-definitions/vpn_openconnect.xml.in
@@ -69,6 +69,37 @@
+
+
+ Use certificate based authentication
+
+
+
+
+ Defines what field in the certificate identifies the username
+
+ cn
+ OID 2.5.4.3 - Common Name
+
+
+ uid
+ OID 0.9.2342.19200300.100.1.1 - UID
+
+
+ x.x.xx.xxx
+ Custom OID in dotted decimal format
+
+
+ (^\d{1,5}(?:\.\d{1,5})*$|cn|uid)
+
+ Invalid OID selection. Must be cn, uid, or a valid OID format.
+
+ cn uid x.x.xx.xxx
+
+
+
+
+
diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py
index 68cd363f08..8522a325bb 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)