From 0defe795c4b0ede8564278e7e4eaa23e00c356f5 Mon Sep 17 00:00:00 2001 From: Koda YeenBean Date: Mon, 13 Jul 2026 23:35:02 +0000 Subject: [PATCH] fixed Security Protocol Settings --- src/inform.c | 1 + src/models.c | 26 ++++----- src/state.h | 2 +- src/ufmodel.h | 3 +- src/wlan.c | 155 +++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 159 insertions(+), 28 deletions(-) diff --git a/src/inform.c b/src/inform.c index 850bffc..1d4c9ce 100644 --- a/src/inform.c +++ b/src/inform.c @@ -260,6 +260,7 @@ static void build_radio_table(struct json_object *root, json_object_object_add(o, "nss", json_object_new_int(r->nss)); json_object_object_add(o, "tx_power", json_object_new_int(r->tx_power)); json_object_object_add(o, "radio_caps", json_object_new_int(r->radio_caps)); + json_object_object_add(o, "radio_caps2", json_object_new_int(r->radio_caps2)); json_object_object_add(o, "antenna_gain", json_object_new_int(r->antenna_gain)); json_object_object_add(o, "he_enabled", json_object_new_boolean(r->he_enabled)); json_object_object_add(o, "builtin_antenna", json_object_new_boolean(true)); diff --git a/src/models.c b/src/models.c index 617180e..408a1a8 100644 --- a/src/models.c +++ b/src/models.c @@ -27,9 +27,9 @@ U6 InWall — 5 ports GbE + WiFi 6 (2.4+5 GHz) ═══════════════════════════════════════════════════════════════════ */ static const uf_radio_t u6iw_radios[] = { - /* name radio ch ht min max nss pwr caps ant he */ - { "wifi0", "ng", 6, "HT40", 5, 23, 2, 20, 4, 0, true }, - { "wifi1", "na", 36, "HT80", 5, 23, 2, 20, 7, 0, true }, + /* name radio ch ht min max nss pwr caps caps2 ant he */ + { "wifi0", "ng", 6, "HT40", 5, 23, 2, 20, 4, 0, 0, true }, + { "wifi1", "na", 36, "HT80", 5, 23, 2, 20, 7, 0, 0, true }, }; /* 5 ports: port 0 as uplink, port 1-4 as LAN */ @@ -76,8 +76,8 @@ const uf_model_t model_u6inwall = { U6 Lite — 1 port GbE + WiFi 6 (2.4+5 GHz) ═══════════════════════════════════════════════════════════════════ */ static const uf_radio_t u6lite_radios[] = { - { "wifi0", "ng", 6, "HT40", 5, 23, 2, 20, 4, 0, true }, - { "wifi1", "na", 36, "HT80", 5, 23, 2, 20, 7, 0, true }, + { "wifi0", "ng", 6, "HT40", 5, 23, 2, 20, 4, 1, 0, true }, + { "wifi1", "na", 36, "HT80", 5, 23, 2, 20, 7, 1, 0, true }, }; static const uf_port_t u6lite_ports[] = { { "eth0", "eth0", 0, 255, "GE", 1000, false, true, true }, @@ -87,10 +87,10 @@ static const uf_radio_map_t u6lite_rmap[] = { { "ng", "radio0" }, { "na", "radio1" }, }; const uf_model_t model_u6lite = { - .model="U6LITE", .model_display="U6 Lite", .display_name="U6-Lite", - .platform="U6LITE", .board_rev=3, .has_eth1=false, - .fw_pre="U6LITE.mt7622_5_4.v", .fw_ver="6.6.55.14430", - .fw_buildtime="230901.1200", .fw_factoryver="6.6.55.14430", + .model="UAL6", .model_display="U6 Lite", .display_name="U6-Lite", + .platform="UAL6", .board_rev=15, .has_eth1=false, + .fw_pre="BZ.mt7621.v", .fw_ver="6.6.55.15189", + .fw_buildtime="231127.1804", .fw_factoryver="6.6.55.15189", .radio_table=u6lite_radios, .radio_table_len=2, .port_table=u6lite_ports, .port_table_len=1, .ethernet_table=u6lite_eth, .ethernet_table_len=1, @@ -101,7 +101,7 @@ const uf_model_t model_u6lite = { UAP Gen 1 — 1 port Fast Ethernet + WiFi N 2.4 GHz ═══════════════════════════════════════════════════════════════════ */ static const uf_radio_t uapg1_radios[] = { - { "wifi0", "ng", 6, "HT20", 5, 23, 2, 20, 4, 0, false }, + { "wifi0", "ng", 6, "HT20", 5, 23, 2, 20, 4, 0, 0, false }, }; static const uf_port_t uapg1_ports[] = { { "eth0", "eth0", 0, 255, "GE", 100, false, true, true }, @@ -123,7 +123,7 @@ const uf_model_t model_uapg1 = { UAP Gen 1 LR ═══════════════════════════════════════════════════════════════════ */ static const uf_radio_t uapg1lr_radios[] = { - { "wifi0", "ng", 6, "HT20", 5, 23, 2, 22, 4, 0, false }, + { "wifi0", "ng", 6, "HT20", 5, 23, 2, 22, 4, 0, 0, false }, }; static const uf_port_t uapg1lr_ports[] = { { "eth0", "eth0", 0, 255, "GE", 100, false, true, true }, @@ -145,8 +145,8 @@ const uf_model_t model_uapg1lr = { UAP AC LR — 1 port GbE + WiFi AC dual-band ═══════════════════════════════════════════════════════════════════ */ static const uf_radio_t uapg2aclr_radios[] = { - { "wifi0", "ng", 6, "HT40", 5, 23, 2, 20, 4, 0, false }, - { "wifi1", "na", 36, "HT80", 5, 23, 2, 20, 7, 0, false }, + { "wifi0", "ng", 6, "HT40", 5, 23, 2, 20, 4, 0, 0, false }, + { "wifi1", "na", 36, "HT80", 5, 23, 2, 20, 7, 0, 0, false }, }; static const uf_port_t uapg2aclr_ports[] = { { "eth0", "eth0", 0, 255, "GE", 1000, false, true, true }, diff --git a/src/state.h b/src/state.h index d9a9dd2..22af7c0 100644 --- a/src/state.h +++ b/src/state.h @@ -3,7 +3,7 @@ #include -#define OPENUF_CONFIG_SCHEMA 3 +#define OPENUF_CONFIG_SCHEMA 6 typedef struct { bool adopted; diff --git a/src/ufmodel.h b/src/ufmodel.h index d58f5f3..9538195 100644 --- a/src/ufmodel.h +++ b/src/ufmodel.h @@ -14,6 +14,7 @@ typedef struct { int nss; int tx_power; int radio_caps; + int radio_caps2; int antenna_gain; bool he_enabled; } uf_radio_t; @@ -45,7 +46,7 @@ typedef struct { /* ─── Full model descriptor ───────────────────────────────────────── */ typedef struct { - const char *model; /* "U6IW", "U6LITE" */ + const char *model; /* "U6IW", "UAL6" */ const char *model_display; /* "U6 IW" */ const char *display_name; /* "U6-IW" */ const char *platform; /* used in announce PKT_PLATFORM */ diff --git a/src/wlan.c b/src/wlan.c index 5ae3a0f..6c278b2 100644 --- a/src/wlan.c +++ b/src/wlan.c @@ -853,11 +853,32 @@ static int apply_vap(struct uci_context *ctx, const char *essid = ""; const char *security = "wpa2psk"; const char *pass = ""; + const char *auth_server = NULL; + const char *auth_secret = NULL; + const char *acct_server = NULL; + const char *acct_secret = NULL; + int auth_port = 1812; + int acct_port = 1813; if (json_object_object_get_ex(vap_json, "essid", &v)) essid = json_object_get_string(v); if (json_object_object_get_ex(vap_json, "security", &v)) security = json_object_get_string(v); if (json_object_object_get_ex(vap_json, "x_passphrase",&v)) pass = json_object_get_string(v); + int enterprise = !strcmp(security, "wpa2enterprise") || + !strcmp(security, "wpa3enterprise"); + if (json_object_object_get_ex(vap_json, "auth_server", &v)) + auth_server = json_object_get_string(v); + if (json_object_object_get_ex(vap_json, "auth_secret", &v)) + auth_secret = json_object_get_string(v); + if (json_object_object_get_ex(vap_json, "auth_port", &v)) + auth_port = json_object_get_int(v); + if (json_object_object_get_ex(vap_json, "acct_server", &v)) + acct_server = json_object_get_string(v); + if (json_object_object_get_ex(vap_json, "acct_secret", &v)) + acct_secret = json_object_get_string(v); + if (json_object_object_get_ex(vap_json, "acct_port", &v)) + acct_port = json_object_get_int(v); + /* Resolve the final network before creating the VAP; never fail open. */ int vid = 0; char target_network[32] = "lan"; @@ -908,9 +929,50 @@ static int apply_vap(struct uci_context *ctx, UCI_SET(ctx, "wireless", sec_name, "openuf_vap_id", vap_id); /* Password */ - if (pass && pass[0] && strcmp(security,"open") != 0) + if (!enterprise && pass && pass[0] && strcmp(security,"open") != 0) UCI_SET(ctx, "wireless", sec_name, "key", pass); + if (enterprise) { + if (!auth_server || !auth_server[0] || + !auth_secret || !auth_secret[0]) { + printf("[openuf] Refusing Enterprise VAP '%s': missing RADIUS " + "authentication server or secret\n", essid); + return -1; + } + + char path[256]; + char port[16]; + snprintf(path, sizeof(path), "wireless.%s.auth_server", sec_name); + snprintf(port, sizeof(port), "%d", auth_port > 0 ? auth_port : 1812); + if (uci_add_list_val(ctx, path, auth_server) != 0 || + uci_set_required(ctx, pkg, sec_name, "auth_port", port) != 0 || + uci_set_required(ctx, pkg, sec_name, "auth_secret", + auth_secret) != 0) { + printf("[openuf] Failed to store RADIUS authentication for " + "VAP '%s'\n", essid); + return -1; + } + + if (acct_server && acct_server[0]) { + if (!acct_secret || !acct_secret[0]) { + printf("[openuf] Refusing Enterprise VAP '%s': accounting " + "server has no secret\n", essid); + return -1; + } + snprintf(path, sizeof(path), "wireless.%s.acct_server", sec_name); + snprintf(port, sizeof(port), "%d", + acct_port > 0 ? acct_port : 1813); + if (uci_add_list_val(ctx, path, acct_server) != 0 || + uci_set_required(ctx, pkg, sec_name, "acct_port", port) != 0 || + uci_set_required(ctx, pkg, sec_name, "acct_secret", + acct_secret) != 0) { + printf("[openuf] Failed to store RADIUS accounting for " + "VAP '%s'\n", essid); + return -1; + } + } + } + /* hidden SSID */ int hidden = 0; if (json_object_object_get_ex(vap_json, "hide_ssid", &v)) @@ -931,17 +993,18 @@ static int apply_vap(struct uci_context *ctx, /* ── PMF (Protected Management Frames / 802.11w) ────────────── * "disabled" → 0, "optional" → 1, "required" → 2 - * WPA3 (sae/sae-mixed) always requires "optional" or " required" ieee80211w=2 */ + * WPA3-only requires PMF. WPA2/WPA3 transition mode must leave PMF + * optional so WPA2-only clients can still associate. */ int pmf = 0; if (json_object_object_get_ex(vap_json, "pmf_mode", &v)) { const char *pm = json_object_get_string(v); if (!strcmp(pm, "optional")) pmf = 1; if (!strcmp(pm, "required")) pmf = 2; } - /* WPA3 forces PMF=2 */ - if (!strcmp(security,"wpa3") || !strcmp(security,"wpa3transition") || - !strcmp(security,"wpa3enterprise")) + if (!strcmp(security,"wpa3") || !strcmp(security,"wpa3enterprise")) pmf = 2; + else if (!strcmp(security,"wpa3transition") && pmf < 1) + pmf = 1; UCI_SET_INT(ctx, "wireless", sec_name, "ieee80211w", pmf); /* ── Fast Roaming (802.11r FT) ──────────────────────────────── @@ -1028,7 +1091,7 @@ static int apply_vap(struct uci_context *ctx, "could not be stored\n", essid); return -1; } - if (pass && pass[0] && strcmp(security, "open") != 0 && + if (!enterprise && pass && pass[0] && strcmp(security, "open") != 0 && uci_set_required(ctx, pkg, sec_name, "key", pass) != 0) { printf("[openuf] Refusing unsecured VAP '%s': key could not be stored\n", essid); @@ -1413,15 +1476,81 @@ int wlan_apply_system_cfg(const char *system_cfg, band = "na"; json_object_object_add(vap, "radio", json_object_new_string(band)); + char passphrase[256] = {0}; snprintf(key, sizeof(key), "aaa.%d.wpa.psk", i); - if (system_cfg_get(system_cfg, key, value, sizeof(value))) { - json_object_object_add(vap, "security", - json_object_new_string("wpa2psk")); + int has_passphrase = system_cfg_get(system_cfg, key, passphrase, + sizeof(passphrase)); + if (!has_passphrase) { + snprintf(key, sizeof(key), "aaa.%d.sae.psk.1.psk", i); + has_passphrase = system_cfg_get(system_cfg, key, passphrase, + sizeof(passphrase)); + } + + char key_mgmt[256] = {0}; + snprintf(key, sizeof(key), "aaa.%d.wpa.key.1.mgmt", i); + int has_key_mgmt = system_cfg_get(system_cfg, key, key_mgmt, + sizeof(key_mgmt)); + + int wpa3_support = 0; + snprintf(key, sizeof(key), "aaa.%d.wpa3.support", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + wpa3_support = feature_text_enabled(value); + + int wpa3_transition = 0; + snprintf(key, sizeof(key), "aaa.%d.wpa3.transition", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + wpa3_transition = feature_text_enabled(value); + + const char *security = "open"; + if (has_key_mgmt && strstr(key_mgmt, "WPA-EAP")) { + security = wpa3_support ? "wpa3enterprise" : "wpa2enterprise"; + } else if (has_key_mgmt && strstr(key_mgmt, "SAE")) { + /* A transition BSS permits both WPA2-PSK and SAE. */ + security = wpa3_transition || strstr(key_mgmt, "WPA-PSK") + ? "wpa3transition" : "wpa3"; + } else if (has_passphrase) { + security = "wpa2psk"; + } + json_object_object_add(vap, "security", + json_object_new_string(security)); + + int enterprise = !strcmp(security, "wpa2enterprise") || + !strcmp(security, "wpa3enterprise"); + if (has_passphrase && !enterprise) { json_object_object_add(vap, "x_passphrase", - json_object_new_string(value)); - } else { - json_object_object_add(vap, "security", - json_object_new_string("open")); + json_object_new_string(passphrase)); + } + + if (enterprise) { + snprintf(key, sizeof(key), "aaa.%d.radius.auth.1.ip", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + json_object_object_add(vap, "auth_server", + json_object_new_string(value)); + + snprintf(key, sizeof(key), "aaa.%d.radius.auth.1.port", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + json_object_object_add(vap, "auth_port", + json_object_new_int(atoi(value))); + + snprintf(key, sizeof(key), "aaa.%d.radius.auth.1.secret", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + json_object_object_add(vap, "auth_secret", + json_object_new_string(value)); + + snprintf(key, sizeof(key), "aaa.%d.radius.acct.1.ip", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + json_object_object_add(vap, "acct_server", + json_object_new_string(value)); + + snprintf(key, sizeof(key), "aaa.%d.radius.acct.1.port", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + json_object_object_add(vap, "acct_port", + json_object_new_int(atoi(value))); + + snprintf(key, sizeof(key), "aaa.%d.radius.acct.1.secret", i); + if (system_cfg_get(system_cfg, key, value, sizeof(value))) + json_object_object_add(vap, "acct_secret", + json_object_new_string(value)); } snprintf(key, sizeof(key), "aaa.%d.hide_ssid", i); -- 2.54.0