subject_match, altsubject_match, domain_suffix_match,
domain_match
they are used for 802.1X aka. enterprise-wpa to check
the authentication server's certificate in order to
prevent MITM attacks using a valid certificate issued
by the same root-CA as configured by CACertFile.
More details at
https://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf
---
doc/config-format.txt | 9 ++++
gsupplicant/gsupplicant.h | 4 ++
gsupplicant/supplicant.c | 20 +++++++++
plugins/wifi.c | 12 ++++++
src/config.c | 60 ++++++++++++++++++++++++++
src/connman.h | 8 ++++
src/network.c | 28 ++++++++++++
src/service.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 249 insertions(+)
diff --git a/doc/config-format.txt b/doc/config-format.txt
index eae51e0..ed3123a 100644
--- a/doc/config-format.txt
+++ b/doc/config-format.txt
@@ -84,6 +84,15 @@ The following options are valid if Type is "wifi"
to fsid.
- Identity: Identity string for EAP.
- AnonymousIdentity: Anonymous Identity string for EAP.
+- SubjectMatch: Substring to be matched against the subject of the
+ authentication server certificate for EAP.
+- AltSubjectMatch: Semicolon separated string of entries to be matched against
+ the alternative subject name of the authentication server certificate for EAP.
+- DomainSuffixMatch: Constraint for server domain name. If set, this FQDN is
+ used as a suffix match requirement for the authentication server certificate
+ for EAP.
+- DomainMatch: This FQDN is used as a full match requirement for the
+ authentication server certificate for EAP.
- Phase2: Phase2 (inner authentication with TLS tunnel) authentication method.
Prefix the value with "EAP-" to indicate the usage of an EAP-based inner
authentication method (should only be used with EAP = TTLS).
diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
index 26fd2ca..678cf8b 100644
--- a/gsupplicant/gsupplicant.h
+++ b/gsupplicant/gsupplicant.h
@@ -144,6 +144,10 @@ struct _GSupplicantSSID {
const char *identity;
const char *anonymous_identity;
const char *ca_cert_path;
+ const char *subject_match;
+ const char *altsubject_match;
+ const char *domain_suffix_match;
+ const char *domain_match;
const char *client_cert_path;
const char *private_key_path;
const char *private_key_passphrase;
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 7200041..8890447 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -4512,6 +4512,26 @@ static void add_network_security_eap(DBusMessageIter *dict,
DBUS_TYPE_STRING,
&ssid->anonymous_identity);
+ if(ssid->subject_match)
+ supplicant_dbus_dict_append_basic(dict, "subject_match",
+ DBUS_TYPE_STRING,
+ &ssid->subject_match);
+
+ if(ssid->altsubject_match)
+ supplicant_dbus_dict_append_basic(dict, "altsubject_match",
+ DBUS_TYPE_STRING,
+ &ssid->altsubject_match);
+
+ if(ssid->domain_suffix_match)
+ supplicant_dbus_dict_append_basic(dict, "domain_suffix_match",
+ DBUS_TYPE_STRING,
+ &ssid->domain_suffix_match);
+
+ if(ssid->domain_match)
+ supplicant_dbus_dict_append_basic(dict, "domain_match",
+ DBUS_TYPE_STRING,
+ &ssid->domain_match);
+
g_free(eap_value);
}
diff --git a/plugins/wifi.c b/plugins/wifi.c
index 68b231d..70cec77 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -88,6 +88,10 @@ struct hidden_params {
unsigned int ssid_len;
char *identity;
char *anonymous_identity;
+ char *subject_match;
+ char *altsubject_match;
+ char *domain_suffix_match;
+ char *domain_match;
char *passphrase;
char *security;
GSupplicantScanParams *scan_params;
@@ -2058,6 +2062,14 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network
*network)
"WiFi.AnonymousIdentity");
ssid->ca_cert_path = connman_network_get_string(network,
"WiFi.CACertFile");
+ ssid->subject_match = connman_network_get_string(network,
+ "WiFi.SubjectMatch");
+ ssid->altsubject_match = connman_network_get_string(network,
+ "WiFi.AltSubjectMatch");
+ ssid->domain_suffix_match = connman_network_get_string(network,
+ "WiFi.DomainSuffixMatch");
+ ssid->domain_match = connman_network_get_string(network,
+ "WiFi.DomainMatch");
ssid->client_cert_path = connman_network_get_string(network,
"WiFi.ClientCertFile");
ssid->private_key_path = connman_network_get_string(network,
diff --git a/src/config.c b/src/config.c
index ba10fbb..c40f76c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -47,6 +47,10 @@ struct connman_config_service {
char *identity;
char *anonymous_identity;
char *ca_cert_file;
+ char *subject_match;
+ char *altsubject_match;
+ char *domain_suffix_match;
+ char *domain_match;
char *client_cert_file;
char *private_key_file;
char *private_key_passphrase;
@@ -100,6 +104,10 @@ static bool cleanup = false;
#define SERVICE_KEY_PRV_KEY_PASS_TYPE "PrivateKeyPassphraseType"
#define SERVICE_KEY_IDENTITY "Identity"
#define SERVICE_KEY_ANONYMOUS_IDENTITY "AnonymousIdentity"
+#define SERVICE_KEY_SUBJECT_MATCH "SubjectMatch"
+#define SERVICE_KEY_ALT_SUBJECT_MATCH "AltSubjectMatch"
+#define SERVICE_KEY_DOMAIN_SUFF_MATCH "DomainSuffixMatch"
+#define SERVICE_KEY_DOMAIN_MATCH "DomainMatch"
#define SERVICE_KEY_PHASE2 "Phase2"
#define SERVICE_KEY_PASSPHRASE "Passphrase"
#define SERVICE_KEY_SECURITY "Security"
@@ -132,6 +140,10 @@ static const char *service_possible_keys[] = {
SERVICE_KEY_PRV_KEY_PASS_TYPE,
SERVICE_KEY_IDENTITY,
SERVICE_KEY_ANONYMOUS_IDENTITY,
+ SERVICE_KEY_SUBJECT_MATCH,
+ SERVICE_KEY_ALT_SUBJECT_MATCH,
+ SERVICE_KEY_DOMAIN_SUFF_MATCH,
+ SERVICE_KEY_DOMAIN_MATCH,
SERVICE_KEY_PHASE2,
SERVICE_KEY_PASSPHRASE,
SERVICE_KEY_SECURITY,
@@ -225,6 +237,10 @@ free_only:
g_free(config_service->identity);
g_free(config_service->anonymous_identity);
g_free(config_service->ca_cert_file);
+ g_free(config_service->subject_match);
+ g_free(config_service->altsubject_match);
+ g_free(config_service->domain_suffix_match);
+ g_free(config_service->domain_match);
g_free(config_service->client_cert_file);
g_free(config_service->private_key_file);
g_free(config_service->private_key_passphrase);
@@ -666,6 +682,34 @@ static bool load_service(GKeyFile *keyfile, const char *group,
service->anonymous_identity = str;
}
+ str = __connman_config_get_string(keyfile, group,
+ SERVICE_KEY_SUBJECT_MATCH, NULL);
+ if (str) {
+ g_free(service->subject_match);
+ service->subject_match = str;
+ }
+
+ str = __connman_config_get_string(keyfile, group,
+ SERVICE_KEY_ALT_SUBJECT_MATCH, NULL);
+ if (str) {
+ g_free(service->altsubject_match);
+ service->altsubject_match = str;
+ }
+
+ str = __connman_config_get_string(keyfile, group,
+ SERVICE_KEY_DOMAIN_SUFF_MATCH, NULL);
+ if (str) {
+ g_free(service->domain_suffix_match);
+ service->domain_suffix_match = str;
+ }
+
+ str = __connman_config_get_string(keyfile, group,
+ SERVICE_KEY_DOMAIN_MATCH, NULL);
+ if (str) {
+ g_free(service->domain_match);
+ service->domain_match = str;
+ }
+
str = __connman_config_get_string(keyfile, group, SERVICE_KEY_PHASE2, NULL);
if (str) {
g_free(service->phase2);
@@ -1060,6 +1104,22 @@ static void provision_service_wifi(struct connman_config_service
*config,
__connman_service_set_string(service, "CACertFile",
config->ca_cert_file);
+ if (config->subject_match)
+ __connman_service_set_string(service, "SubjectMatch",
+ config->subject_match);
+
+ if (config->altsubject_match)
+ __connman_service_set_string(service, "AltSubjectMatch",
+ config->altsubject_match);
+
+ if (config->domain_suffix_match)
+ __connman_service_set_string(service, "DomainSuffixMatch",
+ config->domain_suffix_match);
+
+ if (config->domain_match)
+ __connman_service_set_string(service, "DomainMatch",
+ config->domain_match);
+
if (config->client_cert_file)
__connman_service_set_string(service, "ClientCertFile",
config->client_cert_file);
diff --git a/src/connman.h b/src/connman.h
index f85d243..577c808 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -779,6 +779,14 @@ void __connman_service_set_identity(struct connman_service *service,
const char *identity);
void __connman_service_set_anonymous_identity(struct connman_service *service,
const char *anonymous_identity);
+void __connman_service_set_subject_match(struct connman_service *service,
+ const char *subject_match);
+void __connman_service_set_altsubject_match(struct connman_service *service,
+ const char *altsubject_match);
+void __connman_service_set_domain_suffix_match(struct connman_service *service,
+ const char *domain_suffix_match);
+void __connman_service_set_domain_match(struct connman_service *service,
+ const char *domain_match);
void __connman_service_set_agent_identity(struct connman_service *service,
const char *agent_identity);
int __connman_service_set_passphrase(struct connman_service *service,
diff --git a/src/network.c b/src/network.c
index 4c7f2d5..aa82b74 100644
--- a/src/network.c
+++ b/src/network.c
@@ -82,6 +82,10 @@ struct connman_network {
char *anonymous_identity;
char *agent_identity;
char *ca_cert_path;
+ char *subject_match;
+ char *altsubject_match;
+ char *domain_suffix_match;
+ char *domain_match;
char *client_cert_path;
char *private_key_path;
char *private_key_passphrase;
@@ -893,6 +897,10 @@ static void network_destruct(struct connman_network *network)
g_free(network->wifi.anonymous_identity);
g_free(network->wifi.agent_identity);
g_free(network->wifi.ca_cert_path);
+ g_free(network->wifi.subject_match);
+ g_free(network->wifi.altsubject_match);
+ g_free(network->wifi.domain_suffix_match);
+ g_free(network->wifi.domain_match);
g_free(network->wifi.client_cert_path);
g_free(network->wifi.private_key_path);
g_free(network->wifi.private_key_passphrase);
@@ -1796,6 +1804,18 @@ int connman_network_set_string(struct connman_network *network,
} else if (g_str_equal(key, "WiFi.CACertFile")) {
g_free(network->wifi.ca_cert_path);
network->wifi.ca_cert_path = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.SubjectMatch")) {
+ g_free(network->wifi.subject_match);
+ network->wifi.subject_match = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.AltSubjectMatch")) {
+ g_free(network->wifi.altsubject_match);
+ network->wifi.altsubject_match = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.DomainSuffixMatch")) {
+ g_free(network->wifi.domain_suffix_match);
+ network->wifi.domain_suffix_match = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.DomainMatch")) {
+ g_free(network->wifi.domain_match);
+ network->wifi.domain_match = g_strdup(value);
} else if (g_str_equal(key, "WiFi.ClientCertFile")) {
g_free(network->wifi.client_cert_path);
network->wifi.client_cert_path = g_strdup(value);
@@ -1850,6 +1870,14 @@ const char *connman_network_get_string(struct connman_network
*network,
return network->wifi.agent_identity;
else if (g_str_equal(key, "WiFi.CACertFile"))
return network->wifi.ca_cert_path;
+ else if (g_str_equal(key, "WiFi.SubjectMatch"))
+ return network->wifi.subject_match;
+ else if (g_str_equal(key, "WiFi.AltSubjectMatch"))
+ return network->wifi.altsubject_match;
+ else if (g_str_equal(key, "WiFi.DomainSuffixMatch"))
+ return network->wifi.domain_suffix_match;
+ else if (g_str_equal(key, "WiFi.DomainMatch"))
+ return network->wifi.domain_match;
else if (g_str_equal(key, "WiFi.ClientCertFile"))
return network->wifi.client_cert_path;
else if (g_str_equal(key, "WiFi.PrivateKeyFile"))
diff --git a/src/service.c b/src/service.c
index e5a106e..09472ab 100644
--- a/src/service.c
+++ b/src/service.c
@@ -104,6 +104,10 @@ struct connman_service {
char *anonymous_identity;
char *agent_identity;
char *ca_cert_file;
+ char *subject_match;
+ char *altsubject_match;
+ char *domain_suffix_match;
+ char *domain_match;
char *client_cert_file;
char *private_key_file;
char *private_key_passphrase;
@@ -2868,6 +2872,66 @@ void __connman_service_set_anonymous_identity(struct
connman_service *service,
service->anonymous_identity);
}
+void __connman_service_set_subject_match(struct connman_service *service,
+ const char *subject_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->subject_match);
+ service->subject_match = g_strdup(subject_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.SubjectMatch",
+ service->subject_match);
+}
+
+void __connman_service_set_altsubject_match(struct connman_service *service,
+ const char *altsubject_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->altsubject_match);
+ service->altsubject_match = g_strdup(altsubject_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.AltSubjectMatch",
+ service->altsubject_match);
+}
+
+void __connman_service_set_domain_suffix_match(struct connman_service *service,
+ const char *domain_suffix_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->domain_suffix_match);
+ service->domain_suffix_match = g_strdup(domain_suffix_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.DomainSuffixMatch",
+ service->domain_suffix_match);
+}
+
+void __connman_service_set_domain_match(struct connman_service *service,
+ const char *domain_match)
+{
+ if (service->immutable || service->hidden)
+ return;
+
+ g_free(service->domain_match);
+ service->domain_match = g_strdup(domain_match);
+
+ if (service->network)
+ connman_network_set_string(service->network,
+ "WiFi.DomainMatch",
+ service->domain_match);
+}
+
void __connman_service_set_agent_identity(struct connman_service *service,
const char *agent_identity)
{
@@ -4195,6 +4259,18 @@ bool __connman_service_remove(struct connman_service *service)
g_free(service->anonymous_identity);
service->anonymous_identity = NULL;
+ g_free(service->subject_match);
+ service->subject_match = NULL;
+
+ g_free(service->altsubject_match);
+ service->altsubject_match = NULL;
+
+ g_free(service->domain_suffix_match);
+ service->domain_suffix_match = NULL;
+
+ g_free(service->domain_match);
+ service->domain_match = NULL;
+
g_free(service->agent_identity);
service->agent_identity = NULL;
@@ -4651,6 +4727,10 @@ static void service_free(gpointer user_data)
g_free(service->anonymous_identity);
g_free(service->agent_identity);
g_free(service->ca_cert_file);
+ g_free(service->subject_match);
+ g_free(service->altsubject_match);
+ g_free(service->domain_suffix_match);
+ g_free(service->domain_match);
g_free(service->client_cert_file);
g_free(service->private_key_file);
g_free(service->private_key_passphrase);
@@ -5148,6 +5228,18 @@ void __connman_service_set_string(struct connman_service *service,
} else if (g_str_equal(key, "CACertFile")) {
g_free(service->ca_cert_file);
service->ca_cert_file = g_strdup(value);
+ } else if (g_str_equal(key, "SubjectMatch")) {
+ g_free(service->subject_match);
+ service->subject_match = g_strdup(value);
+ } else if (g_str_equal(key, "AltSubjectMatch")) {
+ g_free(service->altsubject_match);
+ service->altsubject_match = g_strdup(value);
+ } else if (g_str_equal(key, "DomainSuffixMatch")) {
+ g_free(service->domain_suffix_match);
+ service->domain_suffix_match = g_strdup(value);
+ } else if (g_str_equal(key, "DomainMatch")) {
+ g_free(service->domain_match);
+ service->domain_match = g_strdup(value);
} else if (g_str_equal(key, "ClientCertFile")) {
g_free(service->client_cert_file);
service->client_cert_file = g_strdup(value);
@@ -5989,6 +6081,22 @@ static void prepare_8021x(struct connman_service *service)
connman_network_set_string(service->network, "WiFi.CACertFile",
service->ca_cert_file);
+ if (service->subject_match)
+ connman_network_set_string(service->network, "WiFi.SubjectMatch",
+ service->subject_match);
+
+ if (service->altsubject_match)
+ connman_network_set_string(service->network, "WiFi.AltSubjectMatch",
+ service->altsubject_match);
+
+ if (service->domain_suffix_match)
+ connman_network_set_string(service->network, "WiFi.DomainSuffixMatch",
+ service->domain_suffix_match);
+
+ if (service->domain_match)
+ connman_network_set_string(service->network, "WiFi.DomainMatch",
+ service->domain_match);
+
if (service->client_cert_file)
connman_network_set_string(service->network,
"WiFi.ClientCertFile",
--
2.9.3 (Apple Git-75)