From addd2af53753a3062ff02c4316045ee3cde5f292 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 16 Sep 2010 16:43:27 +0200 Subject: [PATCH] WPA-EAP support for GSupplicant --- gsupplicant/gsupplicant.h | 14 +++--- gsupplicant/supplicant.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++ plugins/wifi.c | 47 +++++++++++++++--- 3 files changed, 167 insertions(+), 15 deletions(-) diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h index 8461c49..5d8c617 100644 --- a/gsupplicant/gsupplicant.h +++ b/gsupplicant/gsupplicant.h @@ -102,14 +102,14 @@ struct _GSupplicantSSID { unsigned int ssid_len; GSupplicantMode mode; GSupplicantSecurity security; - unsigned int eap_method; + const char *eap; const char *passphrase; - char *identity; - char *ca_cert_path; - char *client_cert_path; - char *private_key_path; - char *private_key_passphrase; - char *phase2_auth; + const char *identity; + const char *ca_cert_path; + const char *client_cert_path; + const char *private_key_path; + const char *private_key_passphrase; + const char *phase2_auth; }; typedef struct _GSupplicantSSID GSupplicantSSID; diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index c1679b5..6e4b5fb 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -2063,6 +2063,126 @@ static void add_network_security_psk(DBusMessageIter *dict, &ssid->passphrase); } +static void add_network_security_tls(DBusMessageIter *dict, + GSupplicantSSID *ssid) +{ + /* + * For TLS, we at least need: + * The client certificate + * The client private key file + * The client private key file password + * + * The Authority certificate is optional. + */ + if (ssid->client_cert_path == NULL) + return; + + if (ssid->private_key_path == NULL) + return; + + if (ssid->private_key_passphrase == NULL) + return; + + if (ssid->ca_cert_path) + supplicant_dbus_dict_append_basic(dict, "ca_cert", + DBUS_TYPE_STRING, &ssid->ca_cert_path); + + supplicant_dbus_dict_append_basic(dict, "private_key", + DBUS_TYPE_STRING, + &ssid->private_key_path); + supplicant_dbus_dict_append_basic(dict, "private_key_passwd", + DBUS_TYPE_STRING, + &ssid->private_key_passphrase); + supplicant_dbus_dict_append_basic(dict, "client_cert", + DBUS_TYPE_STRING, + &ssid->client_cert_path); +} + +static void add_network_security_peap(DBusMessageIter *dict, + GSupplicantSSID *ssid) +{ + char *phase2_auth; + + /* + * For PEAP/TTLS, we at least need + * The authority certificate + * The 2nd phase authentication method + * The 2nd phase passphrase + * + * The Client certificate is optional although strongly required + * When setting it, we need in addition + * The Client private key file + * The Client private key file password + */ + if (ssid->passphrase == NULL) + return; + + if (ssid->ca_cert_path == NULL) + return; + + if (ssid->phase2_auth == NULL) + return; + + if (ssid->client_cert_path) { + if (ssid->private_key_path == NULL) + return; + + if (ssid->private_key_passphrase == NULL) + return; + + supplicant_dbus_dict_append_basic(dict, "client_cert", + DBUS_TYPE_STRING, + &ssid->client_cert_path); + + supplicant_dbus_dict_append_basic(dict, "private_key", + DBUS_TYPE_STRING, + &ssid->private_key_path); + + supplicant_dbus_dict_append_basic(dict, "private_key_passwd", + DBUS_TYPE_STRING, + &ssid->private_key_passphrase); + + } + + phase2_auth = g_strdup_printf("\"auth=%s\"", ssid->phase2_auth); + + supplicant_dbus_dict_append_basic(dict, "password", + DBUS_TYPE_STRING, + &ssid->passphrase); + + supplicant_dbus_dict_append_basic(dict, "ca_cert", + DBUS_TYPE_STRING, + &ssid->ca_cert_path); + + supplicant_dbus_dict_append_basic(dict, "phase2", + DBUS_TYPE_STRING, + &ssid->phase2_auth); + + g_free(phase2_auth); +} + +static void add_network_security_eap(DBusMessageIter *dict, + GSupplicantSSID *ssid) +{ + if (ssid->eap == NULL || ssid->identity == NULL) + return; + + if (g_strcmp0(ssid->eap, "tls") == 0) { + add_network_security_tls(dict, ssid); + } else if (g_strcmp0(ssid->eap, "peap") == 0 || + g_strcmp0(ssid->eap, "ttls") == 0) { + add_network_security_peap(dict, ssid); + } else + return; + + supplicant_dbus_dict_append_basic(dict, "eap", + DBUS_TYPE_STRING, + &ssid->eap); + supplicant_dbus_dict_append_basic(dict, "identity", + DBUS_TYPE_STRING, + &ssid->identity); +} + static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) { char *key_mgmt; @@ -2080,6 +2200,7 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) break; case G_SUPPLICANT_SECURITY_IEEE8021X: key_mgmt = "WPA-EAP"; + add_network_security_eap(dict, ssid); break; } diff --git a/plugins/wifi.c b/plugins/wifi.c index 4cde53e..f8bd87e 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -538,13 +538,50 @@ static GSupplicantSecurity network_security(const char *security) return G_SUPPLICANT_SECURITY_UNKNOWN; } +static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) +{ + const char *security; + + memset(ssid, 0, sizeof(*ssid)); + ssid->ssid = connman_network_get_blob(network, "WiFi.SSID", + &ssid->ssid_len); + security = connman_network_get_string(network, "WiFi.Security"); + ssid->security = network_security(security); + ssid->passphrase = connman_network_get_string(network, + "WiFi.Passphrase"); + ssid->eap = connman_network_get_string(network, "WiFi.EAP"); + + /* + * If our private key password is unset, + * we use the supplied passphrase. That is needed + * for PEAP where 2 passphrases (identity and client + * cert may have to be provided. + */ + if (connman_network_get_string(network, + "WiFi.PrivateKeyPassphrase") == NULL) + connman_network_set_string(network, + "WiFi.PrivateKeyPassphrase", + ssid->passphrase); + /* We must have an identity for both PEAP and TLS */ + ssid->identity = connman_network_get_string(network, "WiFi.Identity"); + ssid->ca_cert_path = connman_network_get_string(network, + "WiFi.CACertFile"); + ssid->client_cert_path = connman_network_get_string(network, + "WiFi.ClientCertFile"); + ssid->private_key_path = connman_network_get_string(network, + "WiFi.PrivateKeyFile"); + ssid->private_key_passphrase = connman_network_get_string(network, + "WiFi.PrivateKeyPassphrase"); + ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2"); + +} + static int network_connect(struct connman_network *network) { struct connman_device *device = connman_network_get_device(network); struct wifi_data *wifi; GSupplicantInterface *interface; GSupplicantSSID ssid; - const char *security; DBG("network %p", network); @@ -557,13 +594,7 @@ static int network_connect(struct connman_network *network) interface = wifi->interface; - memset(&ssid, 0, sizeof(ssid)); - ssid.ssid = connman_network_get_blob(network, "WiFi.SSID", - &ssid.ssid_len); - security = connman_network_get_string(network, "WiFi.Security"); - ssid.security = network_security(security); - ssid.passphrase = connman_network_get_string(network, - "WiFi.Passphrase"); + ssid_init(&ssid, network); wifi->network = connman_network_ref(network); -- 2.7.4