]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
wifi-scripts: ucode: fix EAP certificate constraint handling
authorHauke Mehrtens <hauke@hauke-m.de>
Sun, 5 Jul 2026 17:38:25 +0000 (19:38 +0200)
committerHauke Mehrtens <hauke@hauke-m.de>
Mon, 6 Jul 2026 23:50:56 +0000 (01:50 +0200)
The supplicant config generator emitted the altsubject_match,
domain_match and domain_suffix_match server certificate constraints
through the plain (unquoted) variable list. As these are UCI arrays,
they were rendered space-separated and without quotes, e.g.

  altsubject_match=DNS:a.example.com DNS:b.example.com

wpa_supplicant parses an unquoted string value as a hex blob, so such a
line fails to parse and the constraint is dropped. wpa_supplicant
expects a single quoted, semicolon-separated string:

  altsubject_match="DNS:a.example.com;DNS:b.example.com"

Join these lists with semicolons and emit them as quoted strings.

The inner-tunnel (phase 2) constraints subject_match2, altsubject_match2,
domain_match2 and domain_suffix_match2 were not written to the config at
all; emit them as well. Add the matching inner EAP-TLS options ca_cert2,
client_cert2, private_key2 and private_key2_passwd to the schema so they
validate cleanly.

Fixes: 218f3884d2fb ("wifi-scripts: add ucode based scripts")
Assisted-by: Claude:claude-opus-4-8
Link: https://github.com/openwrt/openwrt/pull/24088
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
package/network/config/wifi-scripts/files-ucode/usr/share/schema/wireless.wifi-iface.json
package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc

index 432827d8e7fdd10748b37f0a11d4f3b6b9805622..285279c22ec68bdb8df808d4696d1116de7bdb68 100644 (file)
                        "description": "Specifies the path the CA certificate used for authentication",
                        "type": "string"
                },
+               "ca_cert2": {
+                       "description": "Path to the inner-tunnel (phase 2) CA certificate for EAP-TLS",
+                       "type": "string"
+               },
                "ca_cert2_usesystem": {
                        "type": "boolean"
                },
                        "description": "File path to client certificate file (PEM/DER)",
                        "type": "string"
                },
+               "client_cert2": {
+                       "description": "File path to the inner-tunnel (phase 2) client certificate for EAP-TLS",
+                       "type": "string"
+               },
                "dae_client": {
                        "type": "alias",
                        "default": "radius_das_client"
                        "description": "Private key matching with the server certificate for EAP-TLS/PEAP/TTLS",
                        "type": "string"
                },
+               "private_key2": {
+                       "description": "Inner-tunnel (phase 2) private key for EAP-TLS",
+                       "type": "string"
+               },
                "private_key_passwd": {
                        "description": "Passphrase for private key",
                        "type": "string"
                },
+               "private_key2_passwd": {
+                       "description": "Passphrase for the inner-tunnel (phase 2) private key",
+                       "type": "string"
+               },
                "proxy_arp": {
                        "description": "Proxy ARP",
                        "type": "boolean"
index e99df269aec3b1aa6640f5361389c8781e07c57f..80c9bd91e7f8c26c6ace10ed7da7ec426ded1189 100644 (file)
@@ -211,9 +211,24 @@ function setup_sta(data, config) {
 
        config.mcast_rate = ratestr(config.mcast_rate);
 
+       /*
+        * Certificate constraint lists are semicolon-separated strings in the
+        * wpa_supplicant config, while UCI stores them as arrays. Join them here
+        * so they are emitted as a single quoted value below.
+        */
+       for (let key in [ 'altsubject_match', 'altsubject_match2',
+                         'domain_match', 'domain_match2',
+                         'domain_suffix_match', 'domain_suffix_match2' ])
+               if (type(config[key]) == 'array')
+                       config[key] = length(config[key]) ? join(';', config[key]) : null;
+
        network_append_string_vars(config, [ 'ssid',
                'identity', 'anonymous_identity', 'password',
-               'ca_cert', 'ca_cert2', 'client_cert', 'client_cert2', 'subject_match',
+               'ca_cert', 'ca_cert2', 'client_cert', 'client_cert2',
+               'subject_match', 'subject_match2',
+               'altsubject_match', 'altsubject_match2',
+               'domain_match', 'domain_match2',
+               'domain_suffix_match', 'domain_suffix_match2',
                'private_key', 'private_key_passwd', 'private_key2', 'private_key2_passwd',
                 ]);
        network_append_vars(config, [
@@ -222,7 +237,6 @@ function setup_sta(data, config) {
                'proto', 'mesh_fwding', 'mesh_rssi_threshold', 'frequency', 'fixed_freq',
                'disable_ht', 'disable_ht40', 'disable_vht', 'vht', 'max_oper_chwidth',
                'ht40', 'beacon_int', 'ieee80211w', 'rates', 'mesh_basic_rates', 'mcast_rate',
-               'altsubject_match', 'domain_match', 'domain_suffix_match',
                'bssid_blacklist', 'bssid_whitelist', 'erp', 'eap', 'phase2',
                'dpp_connector', 'dpp_csign', 'dpp_netaccesskey',
        ]);