Skip to content

Commit

Permalink
wifi: Adds support for additional wpa_supplicant options
Browse files Browse the repository at this point in the history
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
  • Loading branch information
photoninger authored and monich committed Dec 5, 2016
1 parent ec5c013 commit ddfbb20
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 0 deletions.
9 changes: 9 additions & 0 deletions connman/doc/config-format.txt
Expand Up @@ -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).
Expand Down
4 changes: 4 additions & 0 deletions connman/gsupplicant/gsupplicant.h
Expand Up @@ -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;
Expand Down
20 changes: 20 additions & 0 deletions connman/gsupplicant/supplicant.c
Expand Up @@ -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);
}

Expand Down
12 changes: 12 additions & 0 deletions connman/plugins/wifi.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
60 changes: 60 additions & 0 deletions connman/src/config.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions connman/src/connman.h
Expand Up @@ -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,
Expand Down
28 changes: 28 additions & 0 deletions connman/src/network.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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"))
Expand Down
104 changes: 104 additions & 0 deletions connman/src/service.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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",
Expand Down

0 comments on commit ddfbb20

Please sign in to comment.