supplicant: use binary search to lookup option in "nm-supplicant-settings-verify"

This commit is contained in:
Thomas Haller
2020-06-10 12:15:58 +02:00
parent 1fc1a40dd5
commit 4afd62246b
2 changed files with 138 additions and 132 deletions

View File

@@ -13,67 +13,62 @@
struct Opt { struct Opt {
const char *key; const char *key;
const NMSupplOptType type; const NMSupplOptType type;
const gint32 int_low; /* Inclusive */ const guint32 int_low; /* Inclusive */
const gint32 int_high; /* Inclusive; max length for strings */ const guint32 int_high; /* Inclusive; max length for strings */
const char *const*str_allowed; const char *const*str_allowed;
}; };
static gboolean validate_type_int (const struct Opt * opt, typedef gboolean (*validate_func) (const struct Opt *, const char *, const guint32);
const char * value,
const guint32 len);
static gboolean validate_type_bytes (const struct Opt * opt,
const char * value,
const guint32 len);
static gboolean validate_type_utf8 (const struct Opt *opt,
const char * value,
const guint32 len);
static gboolean validate_type_keyword (const struct Opt * opt,
const char * value,
const guint32 len);
typedef gboolean (*validate_func)(const struct Opt *, const char *, const guint32);
struct validate_entry {
const NMSupplOptType type;
const validate_func func;
};
static const struct validate_entry validate_table[] = {
{ NM_SUPPL_OPT_TYPE_INT, validate_type_int },
{ NM_SUPPL_OPT_TYPE_BYTES, validate_type_bytes },
{ NM_SUPPL_OPT_TYPE_UTF8, validate_type_utf8 },
{ NM_SUPPL_OPT_TYPE_KEYWORD, validate_type_keyword },
};
static const struct Opt opt_table[] = { static const struct Opt opt_table[] = {
{ "ssid", NM_SUPPL_OPT_TYPE_BYTES, 0, 32, NULL }, { "altsubject_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "bssid", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NULL }, { "altsubject_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "scan_ssid", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, { "anonymous_identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "frequency", NM_SUPPL_OPT_TYPE_INT, 2412, 5825, NULL },
{ "auth_alg", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( { "auth_alg", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV (
"OPEN", "OPEN",
"SHARED", "SHARED",
"LEAP", "LEAP",
) }, ) },
{ "psk", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "bgscan", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "pairwise", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( { "bssid", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NULL },
"CCMP", { "ca_cert", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
"TKIP", { "ca_cert2", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
"NONE", { "ca_path", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "ca_path2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "client_cert", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "client_cert2", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "domain_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "domain_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "domain_suffix_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "domain_suffix_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "eap", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV (
"LEAP",
"MD5",
"TLS",
"PEAP",
"TTLS",
"SIM",
"PSK",
"FAST",
"PWD",
) }, ) },
{ "eapol_flags", NM_SUPPL_OPT_TYPE_INT, 0, 3, NULL },
{ "eappsk", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "engine", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL },
{ "engine_id", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "fragment_size", NM_SUPPL_OPT_TYPE_INT, 1, 2000, NULL },
{ "freq_list", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NULL },
{ "frequency", NM_SUPPL_OPT_TYPE_INT, 2412, 5825, NULL },
{ "group", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( { "group", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV (
"CCMP", "CCMP",
"TKIP", "TKIP",
"WEP104", "WEP104",
"WEP40", "WEP40",
) }, ) },
{ "proto", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( { "identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
"WPA", { "ieee80211w", NM_SUPPL_OPT_TYPE_INT, 0, 2, NULL },
"RSN", { "ignore_broadcast_ssid", NM_SUPPL_OPT_TYPE_INT, 0, 2, NULL },
) }, { "key_id", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "key_mgmt", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( { "key_mgmt", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV (
"WPA-PSK", "WPA-PSK",
"WPA-PSK-SHA256", "WPA-PSK-SHA256",
@@ -92,34 +87,20 @@ static const struct Opt opt_table[] = {
"OWE", "OWE",
"NONE", "NONE",
) }, ) },
{ "wep_key0", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "macsec_integ_only", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL },
{ "wep_key1", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "macsec_policy", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL },
{ "wep_key2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "macsec_port", NM_SUPPL_OPT_TYPE_INT, 1, 65534, NULL },
{ "wep_key3", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "mka_cak", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "wep_tx_keyidx", NM_SUPPL_OPT_TYPE_INT, 0, 3, NULL }, { "mka_ckn", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "eapol_flags", NM_SUPPL_OPT_TYPE_INT, 0, 3, NULL }, { "nai", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "eap", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( { "pac_file", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
"LEAP", { "pairwise", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV (
"MD5", "CCMP",
"TLS", "TKIP",
"PEAP", "NONE",
"TTLS",
"SIM",
"PSK",
"FAST",
"PWD",
) }, ) },
{ "identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "password", NM_SUPPL_OPT_TYPE_UTF8, 0, 0, NULL }, { "password", NM_SUPPL_OPT_TYPE_UTF8, 0, 0, NULL },
{ "ca_path", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "pcsc", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "subject_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "altsubject_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "domain_suffix_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "domain_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "ca_cert", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "client_cert", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "private_key", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "private_key_passwd", NM_SUPPL_OPT_TYPE_BYTES, 0, 1024, NULL },
{ "phase1", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( { "phase1", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV (
"peapver=0", "peapver=0",
"peapver=1", "peapver=1",
@@ -153,35 +134,26 @@ static const struct Opt opt_table[] = {
"autheap=GTC", "autheap=GTC",
"autheap=TLS", "autheap=TLS",
) }, ) },
{ "anonymous_identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "pin", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "ca_path2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "private_key", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "subject_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "altsubject_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "domain_suffix_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "domain_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "ca_cert2", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "client_cert2", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "private_key2", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, { "private_key2", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL },
{ "private_key2_passwd", NM_SUPPL_OPT_TYPE_BYTES, 0, 1024, NULL }, { "private_key2_passwd", NM_SUPPL_OPT_TYPE_BYTES, 0, 1024, NULL },
{ "pin", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "private_key_passwd", NM_SUPPL_OPT_TYPE_BYTES, 0, 1024, NULL },
{ "pcsc", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "nai", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "eappsk", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "pac_file", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "engine", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL },
{ "engine_id", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "key_id", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "fragment_size", NM_SUPPL_OPT_TYPE_INT, 1, 2000, NULL },
{ "proactive_key_caching", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, { "proactive_key_caching", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL },
{ "bgscan", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "proto", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV (
{ "freq_list", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NULL }, "WPA",
{ "macsec_policy", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, "RSN",
{ "macsec_integ_only", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, ) },
{ "mka_cak", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, { "psk", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "mka_ckn", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, { "scan_ssid", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL },
{ "macsec_port", NM_SUPPL_OPT_TYPE_INT, 1, 65534, NULL }, { "ssid", NM_SUPPL_OPT_TYPE_BYTES, 0, 32, NULL },
{ "ieee80211w", NM_SUPPL_OPT_TYPE_INT, 0, 2, NULL }, { "subject_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "ignore_broadcast_ssid", NM_SUPPL_OPT_TYPE_INT, 0, 2, NULL }, { "subject_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "wep_key0", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "wep_key1", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "wep_key2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "wep_key3", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL },
{ "wep_tx_keyidx", NM_SUPPL_OPT_TYPE_INT, 0, 3, NULL },
}; };
static gboolean static gboolean
@@ -191,8 +163,8 @@ validate_type_int (const struct Opt * opt,
{ {
gint64 v; gint64 v;
g_return_val_if_fail (opt != NULL, FALSE); nm_assert (opt);
g_return_val_if_fail (value != NULL, FALSE); nm_assert (value);
v = _nm_utils_ascii_str_to_int64 (value, 10, opt->int_low, opt->int_high, G_MININT64); v = _nm_utils_ascii_str_to_int64 (value, 10, opt->int_low, opt->int_high, G_MININT64);
return v != G_MININT64 || errno == 0; return v != G_MININT64 || errno == 0;
@@ -205,8 +177,8 @@ validate_type_bytes (const struct Opt * opt,
{ {
guint32 check_len; guint32 check_len;
g_return_val_if_fail (opt != NULL, FALSE); nm_assert (opt);
g_return_val_if_fail (value != NULL, FALSE); nm_assert (value);
check_len = opt->int_high ?: 255; check_len = opt->int_high ?: 255;
if (len > check_len) if (len > check_len)
@@ -222,8 +194,8 @@ validate_type_utf8 (const struct Opt *opt,
{ {
guint32 check_len; guint32 check_len;
g_return_val_if_fail (opt != NULL, FALSE); nm_assert (opt);
g_return_val_if_fail (value != NULL, FALSE); nm_assert (value);
check_len = opt->int_high ?: 255; check_len = opt->int_high ?: 255;
/* Note that we deliberately don't validate the UTF-8, because /* Note that we deliberately don't validate the UTF-8, because
@@ -242,8 +214,8 @@ validate_type_keyword (const struct Opt * opt,
{ {
gs_free char *value_free = NULL; gs_free char *value_free = NULL;
g_return_val_if_fail (opt != NULL, FALSE); nm_assert (opt);
g_return_val_if_fail (value != NULL, FALSE); nm_assert (value);
/* Allow everything */ /* Allow everything */
if (!opt->str_allowed) if (!opt->str_allowed)
@@ -279,40 +251,73 @@ validate_type_keyword (const struct Opt * opt,
} }
NMSupplOptType NMSupplOptType
nm_supplicant_settings_verify_setting (const char * key, nm_supplicant_settings_verify_setting (const char *key,
const char * value, const char *value,
const guint32 len) const guint32 len)
{ {
NMSupplOptType type = NM_SUPPL_OPT_TYPE_INVALID; static const validate_func validate_table[_NM_SUPPL_OPT_TYPE_NUM - 1] = {
int opt_count = sizeof (opt_table) / sizeof (opt_table[0]); [NM_SUPPL_OPT_TYPE_INT - 1] = validate_type_int,
int val_count = sizeof (validate_table) / sizeof (validate_table[0]); [NM_SUPPL_OPT_TYPE_BYTES - 1] = validate_type_bytes,
int i, j; [NM_SUPPL_OPT_TYPE_UTF8 - 1] = validate_type_utf8,
[NM_SUPPL_OPT_TYPE_KEYWORD - 1] = validate_type_keyword,
};
const struct Opt *opt;
gssize opt_idx;
g_return_val_if_fail (key != NULL, FALSE); g_return_val_if_fail (key, FALSE);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value, FALSE);
if (strcmp (key, "mode") == 0) { if (NM_MORE_ASSERT_ONCE (5)) {
gsize i;
for (i = 0; i < G_N_ELEMENTS (opt_table); i++) {
opt = &opt_table[i];
nm_assert (opt->key);
nm_assert (opt->type > NM_SUPPL_OPT_TYPE_INVALID);
nm_assert (opt->type < _NM_SUPPL_OPT_TYPE_NUM);
if (i > 0)
nm_assert (strcmp (opt[-1].key, opt->key) < 0);
nm_assert (validate_table[opt->type - 1]);
nm_assert ( !opt->str_allowed
|| (opt->type == NM_SUPPL_OPT_TYPE_KEYWORD));
nm_assert ( !opt->str_allowed
|| NM_PTRARRAY_LEN (opt->str_allowed) > 0);
nm_assert ( opt->int_low == 0
|| opt->type == NM_SUPPL_OPT_TYPE_INT);
nm_assert ( opt->int_high == 0
|| NM_IN_SET (opt->type, NM_SUPPL_OPT_TYPE_INT,
NM_SUPPL_OPT_TYPE_UTF8,
NM_SUPPL_OPT_TYPE_BYTES));
nm_assert ( opt->type != NM_SUPPL_OPT_TYPE_INT
|| opt->int_low < opt->int_high);
}
}
opt_idx = nm_utils_array_find_binary_search (opt_table,
sizeof (opt_table[0]),
G_N_ELEMENTS (opt_table),
&key,
nm_strcmp_p_with_data,
NULL);
if (opt_idx < 0) {
if (nm_streq (key, "mode")) {
if (len != 1) if (len != 1)
return NM_SUPPL_OPT_TYPE_INVALID; return NM_SUPPL_OPT_TYPE_INVALID;
if (!NM_IN_SET (value[0], '1', '2', '5')) if (!NM_IN_SET (value[0], '1', '2', '5'))
return NM_SUPPL_OPT_TYPE_INVALID; return NM_SUPPL_OPT_TYPE_INVALID;
return NM_SUPPL_OPT_TYPE_INT; return NM_SUPPL_OPT_TYPE_INT;
} }
return NM_SUPPL_OPT_TYPE_INVALID;
for (i = 0; i < opt_count; i++) {
if (strcmp (opt_table[i].key, key) != 0)
continue;
for (j = 0; j < val_count; j++) {
if (validate_table[j].type == opt_table[i].type) {
if ((*(validate_table[j].func))(&opt_table[i], value, len)) {
type = opt_table[i].type;
break;
}
}
}
} }
return type; opt = &opt_table[opt_idx];
if (!((validate_table[opt->type - 1]) (opt, value, len)))
return NM_SUPPL_OPT_TYPE_INVALID;
return opt->type;
} }

View File

@@ -12,7 +12,8 @@ typedef enum {
NM_SUPPL_OPT_TYPE_BYTES, NM_SUPPL_OPT_TYPE_BYTES,
NM_SUPPL_OPT_TYPE_UTF8, NM_SUPPL_OPT_TYPE_UTF8,
NM_SUPPL_OPT_TYPE_KEYWORD, NM_SUPPL_OPT_TYPE_KEYWORD,
NM_SUPPL_OPT_TYPE_STRING NM_SUPPL_OPT_TYPE_STRING,
_NM_SUPPL_OPT_TYPE_NUM,
} NMSupplOptType; } NMSupplOptType;
NMSupplOptType nm_supplicant_settings_verify_setting (const char *key, NMSupplOptType nm_supplicant_settings_verify_setting (const char *key,