diff --git a/connman/doc/config-format.txt b/connman/doc/config-format.txt index eae51e0f9..ed3123aad 100644 --- a/connman/doc/config-format.txt +++ b/connman/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/connman/gsupplicant/gsupplicant.h b/connman/gsupplicant/gsupplicant.h index 4aa49510e..a8c2483f4 100644 --- a/connman/gsupplicant/gsupplicant.h +++ b/connman/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/connman/gsupplicant/supplicant.c b/connman/gsupplicant/supplicant.c index a7ea4d2cc..c8d9cc2fe 100644 --- a/connman/gsupplicant/supplicant.c +++ b/connman/gsupplicant/supplicant.c @@ -4585,6 +4585,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/connman/plugins/wifi.c b/connman/plugins/wifi.c index 2084d815c..df8f5646e 100644 --- a/connman/plugins/wifi.c +++ b/connman/plugins/wifi.c @@ -87,6 +87,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; @@ -2252,6 +2256,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/connman/src/config.c b/connman/src/config.c index 4fe1acf69..a842a190e 100644 --- a/connman/src/config.c +++ b/connman/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 @@ static void unregister_service(gpointer data) 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); @@ -1054,6 +1098,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/connman/src/connman.h b/connman/src/connman.h index d1d5cfd9f..0af2aae50 100644 --- a/connman/src/connman.h +++ b/connman/src/connman.h @@ -798,6 +798,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/connman/src/network.c b/connman/src/network.c index 0e53cf3ff..7f44e05dc 100644 --- a/connman/src/network.c +++ b/connman/src/network.c @@ -84,6 +84,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; @@ -890,6 +894,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); @@ -1866,6 +1874,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); @@ -1922,6 +1942,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/connman/src/service.c b/connman/src/service.c index 8eea5039a..998ab7397 100644 --- a/connman/src/service.c +++ b/connman/src/service.c @@ -116,6 +116,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; @@ -3109,6 +3113,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) { @@ -4428,6 +4492,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; @@ -5408,6 +5484,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); @@ -6311,6 +6399,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",