diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c index 3d841f957..a71677cce 100644 --- a/src/supplicant/nm-supplicant-settings-verify.c +++ b/src/supplicant/nm-supplicant-settings-verify.c @@ -13,67 +13,62 @@ struct Opt { const char *key; const NMSupplOptType type; - const gint32 int_low; /* Inclusive */ - const gint32 int_high; /* Inclusive; max length for strings */ + const guint32 int_low; /* Inclusive */ + const guint32 int_high; /* Inclusive; max length for strings */ const char *const*str_allowed; }; -static gboolean validate_type_int (const struct Opt * opt, - 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 }, -}; +typedef gboolean (*validate_func) (const struct Opt *, const char *, const guint32); static const struct Opt opt_table[] = { - { "ssid", NM_SUPPL_OPT_TYPE_BYTES, 0, 32, NULL }, - { "bssid", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NULL }, - { "scan_ssid", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, - { "frequency", NM_SUPPL_OPT_TYPE_INT, 2412, 5825, NULL }, + { "altsubject_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "altsubject_match2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "anonymous_identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "auth_alg", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( "OPEN", "SHARED", "LEAP", ) }, - { "psk", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, - { "pairwise", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( - "CCMP", - "TKIP", - "NONE", + { "bgscan", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "bssid", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NULL }, + { "ca_cert", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, + { "ca_cert2", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, + { "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 ( "CCMP", "TKIP", "WEP104", "WEP40", ) }, - { "proto", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( - "WPA", - "RSN", - ) }, + { "identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "ieee80211w", NM_SUPPL_OPT_TYPE_INT, 0, 2, NULL }, + { "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 ( "WPA-PSK", "WPA-PSK-SHA256", @@ -92,34 +87,20 @@ static const struct Opt opt_table[] = { "OWE", "NONE", ) }, - { "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 }, - { "eapol_flags", NM_SUPPL_OPT_TYPE_INT, 0, 3, NULL }, - { "eap", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( - "LEAP", - "MD5", - "TLS", - "PEAP", - "TTLS", - "SIM", - "PSK", - "FAST", - "PWD", + { "macsec_integ_only", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, + { "macsec_policy", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, + { "macsec_port", NM_SUPPL_OPT_TYPE_INT, 1, 65534, NULL }, + { "mka_cak", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, + { "mka_ckn", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, + { "nai", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "pac_file", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "pairwise", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( + "CCMP", + "TKIP", + "NONE", ) }, - { "identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "password", NM_SUPPL_OPT_TYPE_UTF8, 0, 0, NULL }, - { "ca_path", 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 }, + { "pcsc", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, { "phase1", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( "peapver=0", "peapver=1", @@ -153,35 +134,26 @@ static const struct Opt opt_table[] = { "autheap=GTC", "autheap=TLS", ) }, - { "anonymous_identity", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, - { "ca_path2", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, 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 }, + { "pin", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "private_key", 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 }, - { "pin", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, 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 }, + { "private_key_passwd", NM_SUPPL_OPT_TYPE_BYTES, 0, 1024, NULL }, { "proactive_key_caching", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, - { "bgscan", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, - { "freq_list", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NULL }, - { "macsec_policy", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, - { "macsec_integ_only", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, - { "mka_cak", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, - { "mka_ckn", NM_SUPPL_OPT_TYPE_BYTES, 0, 65536, NULL }, - { "macsec_port", NM_SUPPL_OPT_TYPE_INT, 1, 65534, NULL }, - { "ieee80211w", NM_SUPPL_OPT_TYPE_INT, 0, 2, NULL }, - { "ignore_broadcast_ssid", NM_SUPPL_OPT_TYPE_INT, 0, 2, NULL }, + { "proto", NM_SUPPL_OPT_TYPE_KEYWORD, 0, 0, NM_MAKE_STRV ( + "WPA", + "RSN", + ) }, + { "psk", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, NULL }, + { "scan_ssid", NM_SUPPL_OPT_TYPE_INT, 0, 1, NULL }, + { "ssid", NM_SUPPL_OPT_TYPE_BYTES, 0, 32, NULL }, + { "subject_match", NM_SUPPL_OPT_TYPE_BYTES, 0, 0, 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 @@ -191,8 +163,8 @@ validate_type_int (const struct Opt * opt, { gint64 v; - g_return_val_if_fail (opt != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); + nm_assert (opt); + nm_assert (value); v = _nm_utils_ascii_str_to_int64 (value, 10, opt->int_low, opt->int_high, G_MININT64); return v != G_MININT64 || errno == 0; @@ -205,8 +177,8 @@ validate_type_bytes (const struct Opt * opt, { guint32 check_len; - g_return_val_if_fail (opt != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); + nm_assert (opt); + nm_assert (value); check_len = opt->int_high ?: 255; if (len > check_len) @@ -222,8 +194,8 @@ validate_type_utf8 (const struct Opt *opt, { guint32 check_len; - g_return_val_if_fail (opt != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); + nm_assert (opt); + nm_assert (value); check_len = opt->int_high ?: 255; /* 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; - g_return_val_if_fail (opt != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); + nm_assert (opt); + nm_assert (value); /* Allow everything */ if (!opt->str_allowed) @@ -279,40 +251,73 @@ validate_type_keyword (const struct Opt * opt, } NMSupplOptType -nm_supplicant_settings_verify_setting (const char * key, - const char * value, +nm_supplicant_settings_verify_setting (const char *key, + const char *value, const guint32 len) { - NMSupplOptType type = NM_SUPPL_OPT_TYPE_INVALID; - int opt_count = sizeof (opt_table) / sizeof (opt_table[0]); - int val_count = sizeof (validate_table) / sizeof (validate_table[0]); - int i, j; + static const validate_func validate_table[_NM_SUPPL_OPT_TYPE_NUM - 1] = { + [NM_SUPPL_OPT_TYPE_INT - 1] = validate_type_int, + [NM_SUPPL_OPT_TYPE_BYTES - 1] = validate_type_bytes, + [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 (value != NULL, FALSE); + g_return_val_if_fail (key, FALSE); + g_return_val_if_fail (value, FALSE); - if (strcmp (key, "mode") == 0) { - if (len != 1) - return NM_SUPPL_OPT_TYPE_INVALID; - if (!NM_IN_SET (value[0], '1', '2', '5')) - return NM_SUPPL_OPT_TYPE_INVALID; - return NM_SUPPL_OPT_TYPE_INT; - } + if (NM_MORE_ASSERT_ONCE (5)) { + gsize i; - for (i = 0; i < opt_count; i++) { - if (strcmp (opt_table[i].key, key) != 0) - continue; + for (i = 0; i < G_N_ELEMENTS (opt_table); i++) { + opt = &opt_table[i]; - 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; - } - } + 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); } } - return type; -} + 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) + return NM_SUPPL_OPT_TYPE_INVALID; + if (!NM_IN_SET (value[0], '1', '2', '5')) + return NM_SUPPL_OPT_TYPE_INVALID; + return NM_SUPPL_OPT_TYPE_INT; + } + return NM_SUPPL_OPT_TYPE_INVALID; + } + opt = &opt_table[opt_idx]; + if (!((validate_table[opt->type - 1]) (opt, value, len))) + return NM_SUPPL_OPT_TYPE_INVALID; + + return opt->type; +} diff --git a/src/supplicant/nm-supplicant-settings-verify.h b/src/supplicant/nm-supplicant-settings-verify.h index 3059b89c3..d804a97eb 100644 --- a/src/supplicant/nm-supplicant-settings-verify.h +++ b/src/supplicant/nm-supplicant-settings-verify.h @@ -12,7 +12,8 @@ typedef enum { NM_SUPPL_OPT_TYPE_BYTES, NM_SUPPL_OPT_TYPE_UTF8, NM_SUPPL_OPT_TYPE_KEYWORD, - NM_SUPPL_OPT_TYPE_STRING + NM_SUPPL_OPT_TYPE_STRING, + _NM_SUPPL_OPT_TYPE_NUM, } NMSupplOptType; NMSupplOptType nm_supplicant_settings_verify_setting (const char *key,