Commit ddfbb206 authored by Bernhard Lichtinger's avatar Bernhard Lichtinger Committed by Slava Monich

wifi: Adds support for additional wpa_supplicant options

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

Conflicts:
	connman/src/service.c
parent ec5c0134
......@@ -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).
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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,
......
......@@ -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);
......@@ -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);
......
......@@ -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,
......
......@@ -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"))
......
......@@ -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",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment