summary refs log tree commit diff
path: root/src/supplicant/nm-supplicant-settings-verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/supplicant/nm-supplicant-settings-verify.c')
-rw-r--r--src/supplicant/nm-supplicant-settings-verify.c370
1 files changed, 213 insertions, 157 deletions
diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c
index 58dbd73a..954a4649 100644
--- a/src/supplicant/nm-supplicant-settings-verify.c
+++ b/src/supplicant/nm-supplicant-settings-verify.c
@@ -11,131 +11,154 @@
 #include <stdlib.h>
 
 struct Opt {
-	const char *     key;
-	const OptType    type;
-	const gint32     int_low;  /* Inclusive */
-	const gint32     int_high; /* Inclusive; max length for strings */
-	const gboolean   str_allowed_multiple;
+	const char *key;
 	const char *const*str_allowed;
+	const NMSupplOptType type;
+	const guint32 int_low;  /* Inclusive */
+	const guint32 int_high; /* Inclusive; max length for strings */
 };
 
-static gboolean validate_type_int     (const struct Opt * opt,
-                                       const char * value,
-                                       const guint32 len);
+typedef gboolean (*validate_func) (const struct Opt *, const char *, const guint32);
 
-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 OptType  type;
-	const validate_func func;
-};
-
-static const struct validate_entry validate_table[] = {
-	{ TYPE_INT,     validate_type_int     },
-	{ TYPE_BYTES,   validate_type_bytes   },
-	{ TYPE_UTF8,    validate_type_utf8    },
-	{ TYPE_KEYWORD, validate_type_keyword },
-};
-
-static const char *const pairwise_allowed[] = { "CCMP", "TKIP", "NONE", NULL };
-static const char *const group_allowed[] =    { "CCMP", "TKIP", "WEP104", "WEP40", NULL };
-static const char *const proto_allowed[] =    { "WPA", "RSN", NULL };
-static const char *const key_mgmt_allowed[] = { "WPA-PSK", "WPA-PSK-SHA256", "FT-PSK",
-                                                "WPA-EAP", "WPA-EAP-SHA256", "FT-EAP", "FT-EAP-SHA384",
-                                                "FILS-SHA256", "FILS-SHA384",
-                                                "IEEE8021X", "SAE", "FT-SAE",
-                                                "OWE", "NONE", NULL };
-static const char *const auth_alg_allowed[] = { "OPEN", "SHARED", "LEAP", NULL };
-static const char *const eap_allowed[] =      { "LEAP", "MD5", "TLS", "PEAP", "TTLS", "SIM",
-                                                "PSK", "FAST", "PWD", NULL };
-
-static const char *const phase1_allowed[] =   { "peapver=0", "peapver=1", "peaplabel=1",
-                                                "peap_outer_success=0", "include_tls_length=1",
-                                                "sim_min_num_chal=3", "fast_provisioning=0",
-                                                "fast_provisioning=1", "fast_provisioning=2",
-                                                "fast_provisioning=3", "tls_disable_tlsv1_0=0",
-                                                "tls_disable_tlsv1_0=1", "tls_disable_tlsv1_1=0",
-                                                "tls_disable_tlsv1_1=1", "tls_disable_tlsv1_2=0",
-                                                "tls_disable_tlsv1_2=1", NULL };
-static const char *const phase2_allowed[] =   { "auth=PAP", "auth=CHAP", "auth=MSCHAP",
-                                                "auth=MSCHAPV2", "auth=GTC", "auth=OTP",
-                                                "auth=MD5", "auth=TLS", "autheap=MD5",
-                                                "autheap=MSCHAPV2", "autheap=OTP",
-                                                "autheap=GTC", "autheap=TLS", NULL };
+#define OPT_INT(    _key, _int_low, _int_high) { .key = _key, .type = NM_SUPPL_OPT_TYPE_INT,     .int_high = _int_high, .int_low = _int_low, }
+#define OPT_BYTES(  _key,           _int_high) { .key = _key, .type = NM_SUPPL_OPT_TYPE_BYTES,   .int_high = _int_high,                      }
+#define OPT_UTF8(   _key,           _int_high) { .key = _key, .type = NM_SUPPL_OPT_TYPE_UTF8,    .int_high = _int_high,                      }
+#define OPT_KEYWORD(_key, _str_allowed)        { .key = _key, .type = NM_SUPPL_OPT_TYPE_KEYWORD, .str_allowed = _str_allowed,                }
 
 static const struct Opt opt_table[] = {
-	{ "ssid",               TYPE_BYTES,   0, 32,FALSE,  NULL },
-	{ "bssid",              TYPE_KEYWORD, 0, 0, FALSE,  NULL },
-	{ "scan_ssid",          TYPE_INT,     0, 1, FALSE,  NULL },
-	{ "frequency",          TYPE_INT,     2412, 5825, FALSE,  NULL },
-	{ "auth_alg",           TYPE_KEYWORD, 0, 0, FALSE,  auth_alg_allowed },
-	{ "psk",                TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "pairwise",           TYPE_KEYWORD, 0, 0, FALSE,  pairwise_allowed },
-	{ "group",              TYPE_KEYWORD, 0, 0, FALSE,  group_allowed },
-	{ "proto",              TYPE_KEYWORD, 0, 0, FALSE,  proto_allowed },
-	{ "key_mgmt",           TYPE_KEYWORD, 0, 0, FALSE,  key_mgmt_allowed },
-	{ "wep_key0",           TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "wep_key1",           TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "wep_key2",           TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "wep_key3",           TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "wep_tx_keyidx",      TYPE_INT,     0, 3, FALSE,  NULL },
-	{ "eapol_flags",        TYPE_INT,     0, 3, FALSE,  NULL },
-	{ "eap",                TYPE_KEYWORD, 0, 0, FALSE,  eap_allowed },
-	{ "identity",           TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "password",           TYPE_UTF8,    0, 0, FALSE,  NULL },
-	{ "ca_path",            TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "subject_match",      TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "altsubject_match",   TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "domain_suffix_match",TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "domain_match",       TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "ca_cert",            TYPE_BYTES,   0, 65536, FALSE,  NULL },
-	{ "client_cert",        TYPE_BYTES,   0, 65536, FALSE,  NULL },
-	{ "private_key",        TYPE_BYTES,   0, 65536, FALSE,  NULL },
-	{ "private_key_passwd", TYPE_BYTES,   0, 1024, FALSE,  NULL },
-	{ "phase1",             TYPE_KEYWORD, 0, 0, TRUE, phase1_allowed },
-	{ "phase2",             TYPE_KEYWORD, 0, 0, TRUE, phase2_allowed },
-	{ "anonymous_identity", TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "ca_path2",           TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "subject_match2",     TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "altsubject_match2",  TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "domain_suffix_match2", TYPE_BYTES, 0, 0, FALSE,  NULL },
-	{ "domain_match2",      TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "ca_cert2",           TYPE_BYTES,   0, 65536, FALSE,  NULL },
-	{ "client_cert2",       TYPE_BYTES,   0, 65536, FALSE,  NULL },
-	{ "private_key2",       TYPE_BYTES,   0, 65536, FALSE,  NULL },
-	{ "private_key2_passwd",TYPE_BYTES,   0, 1024, FALSE,  NULL },
-	{ "pin",                TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "pcsc",               TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "nai",                TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "eappsk",             TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "pac_file",           TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "engine",             TYPE_INT,     0, 1, FALSE,  NULL },
-	{ "engine_id",          TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "key_id",             TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "fragment_size",      TYPE_INT,     1, 2000, FALSE,  NULL },
-	{ "proactive_key_caching", TYPE_INT,  0, 1, FALSE,  NULL },
-	{ "bgscan",             TYPE_BYTES,   0, 0, FALSE,  NULL },
-	{ "pac_file",           TYPE_BYTES,   0, 1024, FALSE,  NULL },
-	{ "freq_list",          TYPE_KEYWORD, 0, 0, FALSE,  NULL },
-	{ "macsec_policy",      TYPE_INT,     0, 1, FALSE, NULL },
-	{ "macsec_integ_only",  TYPE_INT,     0, 1, FALSE, NULL },
-	{ "mka_cak",            TYPE_BYTES,   0, 65536, FALSE, NULL },
-	{ "mka_ckn",            TYPE_BYTES,   0, 65536, FALSE, NULL },
-	{ "macsec_port",        TYPE_INT,     1, 65534, FALSE, NULL },
-	{ "ieee80211w",         TYPE_INT,     0, 2, FALSE, NULL },
-	{ "ignore_broadcast_ssid", TYPE_INT,  0, 2, FALSE, NULL },
+	OPT_BYTES   ("altsubject_match",      0),
+	OPT_BYTES   ("altsubject_match2",     0),
+	OPT_BYTES   ("anonymous_identity",    0),
+	OPT_KEYWORD ("auth_alg",              NM_MAKE_STRV (
+	                                        "OPEN",
+	                                        "SHARED",
+	                                        "LEAP",
+	                                      )),
+	OPT_BYTES   ("bgscan",                0),
+	OPT_KEYWORD ("bssid",                 NULL),
+	OPT_BYTES   ("ca_cert",               65536),
+	OPT_BYTES   ("ca_cert2",              65536),
+	OPT_BYTES   ("ca_path",               0),
+	OPT_BYTES   ("ca_path2",              0),
+	OPT_BYTES   ("client_cert",           65536),
+	OPT_BYTES   ("client_cert2",          65536),
+	OPT_BYTES   ("domain_match",          0),
+	OPT_BYTES   ("domain_match2",         0),
+	OPT_BYTES   ("domain_suffix_match",   0),
+	OPT_BYTES   ("domain_suffix_match2",  0),
+	OPT_KEYWORD ("eap",                   NM_MAKE_STRV (
+	                                        "LEAP",
+	                                        "MD5",
+	                                        "TLS",
+	                                        "PEAP",
+	                                        "TTLS",
+	                                        "SIM",
+	                                        "PSK",
+	                                        "FAST",
+	                                        "PWD",
+	                                      )),
+	OPT_INT     ("eapol_flags",           0, 3),
+	OPT_BYTES   ("eappsk",                0),
+	OPT_INT     ("engine",                0, 1),
+	OPT_BYTES   ("engine_id",             0),
+	OPT_INT     ("fragment_size",         1, 2000),
+	OPT_KEYWORD ("freq_list",             NULL),
+	OPT_INT     ("frequency",             2412, 5825),
+	OPT_KEYWORD ("group",                 NM_MAKE_STRV (
+	                                        "CCMP",
+	                                        "TKIP",
+	                                        "WEP104",
+	                                        "WEP40",
+	                                      )),
+	OPT_BYTES   ("identity",              0),
+	OPT_INT     ("ieee80211w",            0, 2),
+	OPT_INT     ("ignore_broadcast_ssid", 0, 2),
+	OPT_BYTES   ("key_id",                0),
+	OPT_KEYWORD ("key_mgmt",              NM_MAKE_STRV (
+	                                        "WPA-PSK",
+	                                        "WPA-PSK-SHA256",
+	                                        "FT-PSK",
+	                                        "WPA-EAP",
+	                                        "WPA-EAP-SHA256",
+	                                        "FT-EAP",
+	                                        "FT-EAP-SHA384",
+	                                        "FILS-SHA256",
+	                                        "FILS-SHA384",
+	                                        "FT-FILS-SHA256",
+	                                        "FT-FILS-SHA384",
+	                                        "IEEE8021X",
+	                                        "SAE",
+	                                        "FT-SAE",
+	                                        "OWE",
+	                                        "NONE",
+	                                      )),
+	OPT_INT     ("macsec_integ_only",     0, 1),
+	OPT_INT     ("macsec_policy",         0, 1),
+	OPT_INT     ("macsec_port",           1, 65534),
+	OPT_BYTES   ("mka_cak",               65536),
+	OPT_BYTES   ("mka_ckn",               65536),
+	OPT_BYTES   ("nai",                   0),
+	OPT_BYTES   ("pac_file",              0),
+	OPT_KEYWORD ("pairwise",              NM_MAKE_STRV (
+	                                        "CCMP",
+	                                        "TKIP",
+	                                        "NONE",
+	                                      )),
+	OPT_UTF8    ("password",              0),
+	OPT_BYTES   ("pcsc",                  0),
+	OPT_KEYWORD ("phase1",                NM_MAKE_STRV (
+	                                        "peapver=0",
+	                                        "peapver=1",
+	                                        "peaplabel=1",
+	                                        "peap_outer_success=0",
+	                                        "include_tls_length=1",
+	                                        "sim_min_num_chal=3",
+	                                        "fast_provisioning=0",
+	                                        "fast_provisioning=1",
+	                                        "fast_provisioning=2",
+	                                        "fast_provisioning=3",
+	                                        "tls_disable_tlsv1_0=0",
+	                                        "tls_disable_tlsv1_0=1",
+	                                        "tls_disable_tlsv1_1=0",
+	                                        "tls_disable_tlsv1_1=1",
+	                                        "tls_disable_tlsv1_2=0",
+	                                        "tls_disable_tlsv1_2=1",
+	                                      )),
+	OPT_KEYWORD ("phase2",                NM_MAKE_STRV (
+	                                        "auth=PAP",
+	                                        "auth=CHAP",
+	                                        "auth=MSCHAP",
+	                                        "auth=MSCHAPV2",
+	                                        "auth=GTC",
+	                                        "auth=OTP",
+	                                        "auth=MD5",
+	                                        "auth=TLS",
+	                                        "autheap=MD5",
+	                                        "autheap=MSCHAPV2",
+	                                        "autheap=OTP",
+	                                        "autheap=GTC",
+	                                        "autheap=TLS",
+	                                      )),
+	OPT_BYTES   ("pin",                   0),
+	OPT_BYTES   ("private_key",           65536),
+	OPT_BYTES   ("private_key2",          65536),
+	OPT_BYTES   ("private_key2_passwd",   1024),
+	OPT_BYTES   ("private_key_passwd",    1024),
+	OPT_INT     ("proactive_key_caching", 0, 1),
+	OPT_KEYWORD ("proto",                 NM_MAKE_STRV (
+	                                        "WPA",
+	                                        "RSN",
+	                                      )),
+	OPT_BYTES   ("psk",                   0),
+	OPT_INT     ("scan_ssid",             0, 1),
+	OPT_BYTES   ("ssid",                  32),
+	OPT_BYTES   ("subject_match",         0),
+	OPT_BYTES   ("subject_match2",        0),
+	OPT_BYTES   ("wep_key0",              0),
+	OPT_BYTES   ("wep_key1",              0),
+	OPT_BYTES   ("wep_key2",              0),
+	OPT_BYTES   ("wep_key3",              0),
+	OPT_INT     ("wep_tx_keyidx",         0, 3),
 };
 
 static gboolean
@@ -145,8 +168,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;
@@ -159,8 +182,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)
@@ -176,8 +199,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
@@ -196,8 +219,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)
@@ -232,41 +255,74 @@ validate_type_keyword (const struct Opt * opt,
 	}
 }
 
-OptType
-nm_supplicant_settings_verify_setting (const char * key,
-                                       const char * value,
+NMSupplOptType
+nm_supplicant_settings_verify_setting (const char *key,
+                                       const char *value,
                                        const guint32 len)
 {
-	OptType type = 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;
-
-	g_return_val_if_fail (key != NULL, FALSE);
-	g_return_val_if_fail (value != NULL, FALSE);
-
-	if (strcmp (key, "mode") == 0) {
-		if (len != 1)
-			return TYPE_INVALID;
-		if (!NM_IN_SET (value[0], '1', '2', '5'))
-			return TYPE_INVALID;
-		return TYPE_INT;
+	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, FALSE);
+	g_return_val_if_fail (value, FALSE);
+
+	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);
+		}
 	}
 
-	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;
-				}
-			}
+	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;
 	}
 
-	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;
+}