From ef045af46f310530133dd771d5217362c31bb737 Mon Sep 17 00:00:00 2001 From: Niraj Kumar Goit Date: Thu, 16 Apr 2020 12:52:29 +0530 Subject: [PATCH] [net-config] Added support for EAPoL connection. Change-Id: Ic18901757f7ea1d205804e43641c5d36e7d83704 Signed-off-by: Niraj Kumar Goit Signed-off-by: Nishant Chaprana --- CMakeLists.txt | 3 +- include/ethernet.h | 43 +++ include/netdbus.h | 3 + include/netsupplicant.h | 4 + include/wifi-power.h | 1 + interfaces/netconfig-iface-ethernet.xml | 17 + resources/etc/dbus-1/system.d/net-config.conf | 4 + src/dbus/netdbus.c | 12 + src/dbus/netsupplicant.c | 14 +- src/ethernet.c | 301 ++++++++++++++++++ src/main.c | 9 + src/wifi-power.c | 13 +- 12 files changed, 418 insertions(+), 6 deletions(-) create mode 100644 include/ethernet.h create mode 100755 interfaces/netconfig-iface-ethernet.xml create mode 100644 src/ethernet.c diff --git a/CMakeLists.txt b/CMakeLists.txt index bce51e7..c5d0a9a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ SET(SRCS src/ip-conflict-detect.c src/clatd-handler.c src/wifi-dpp.c + src/ethernet.c ) IF("${CMAKE_BUILD_TYPE}" STREQUAL "") @@ -121,7 +122,7 @@ ADD_CUSTOM_COMMAND( --generate-c-code generated-code --c-generate-object-manager --generate-docbook generated-code-docs - ${INTERFACES}/netconfig-iface-network-state.xml ${INTERFACES}/netconfig-iface-network-statistics.xml ${INTERFACES}/netconfig-iface-wifi.xml ${INTERFACES}/netconfig-iface-vpnsvc.xml ${INTERFACES}/netconfig-iface-mptcp.xml + ${INTERFACES}/netconfig-iface-network-state.xml ${INTERFACES}/netconfig-iface-network-statistics.xml ${INTERFACES}/netconfig-iface-wifi.xml ${INTERFACES}/netconfig-iface-vpnsvc.xml ${INTERFACES}/netconfig-iface-mptcp.xml ${INTERFACES}/netconfig-iface-ethernet.xml COMMENT "Generating GDBus .c/.h") ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS} ${CMAKE_SOURCE_DIR}/generated-code.c) diff --git a/include/ethernet.h b/include/ethernet.h new file mode 100644 index 0000000..22df62a --- /dev/null +++ b/include/ethernet.h @@ -0,0 +1,43 @@ +/* + * Network Configuration - EAPoL Service Module + * + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __NETCONFIG_ETHERNET_H__ +#define __NETCONFIG_ETHERNET_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "generated-code.h" + +void ethernet_object_create_and_init(void); +void ethernet_object_deinit(void); +Ethernet *get_ethernet_object(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETCONFIG_ETHERNET_H__ */ + + diff --git a/include/netdbus.h b/include/netdbus.h index 11fe40c..9bce844 100755 --- a/include/netdbus.h +++ b/include/netdbus.h @@ -66,6 +66,8 @@ extern "C" { #define NETCONFIG_VPNSVC_INTERFACE "net.netconfig.vpnsvc" #define NETCONFIG_MPTCP_PATH "/net/netconfig/mptcp" #define NETCONFIG_MPTCP_INTERFACE "net.netconfig.mptcp" +#define NETCONFIG_ETHERNET_PATH "/net/netconfig/ethernet" +#define NETCONFIG_ETHERNET_INTERFACE "net.netconfig.ethernet" #define DBUS_PATH_MAX_BUFLEN 512 #define DBUS_STATE_MAX_BUFLEN 64 @@ -82,6 +84,7 @@ GDBusObjectManagerServer *netdbus_get_state_manager(void); GDBusObjectManagerServer *netdbus_get_statistics_manager(void); GDBusObjectManagerServer *netdbus_get_vpn_manager(void); GDBusObjectManagerServer *netdbus_get_mptcp_manager(void); +GDBusObjectManagerServer *netdbus_get_ethernet_manager(void); GDBusConnection *netdbus_get_connection(void); GCancellable *netdbus_get_cancellable(void); diff --git a/include/netsupplicant.h b/include/netsupplicant.h index d64da19..889a2d5 100755 --- a/include/netsupplicant.h +++ b/include/netsupplicant.h @@ -43,6 +43,10 @@ struct dbus_input_arguments { void *data; }; +/* Returns Supplicant interface. + * Need to release interface using g_free */ +char *netconfig_get_supplicant_interface(const char *ifname); + /* Returns Supplicant interface. * Need to release interface using g_free */ char *netconfig_wifi_get_supplicant_interface(void); diff --git a/include/wifi-power.h b/include/wifi-power.h index 49f25aa..387a56c 100755 --- a/include/wifi-power.h +++ b/include/wifi-power.h @@ -46,6 +46,7 @@ gboolean handle_load_p2p_driver(Wifi *wifi, GDBusMethodInvocation *context); gboolean handle_remove_p2p_driver(Wifi *wifi, GDBusMethodInvocation *context); void __netconfig_set_ether_macaddr(); +int __execute_supplicant(gboolean enable); #ifdef __cplusplus } diff --git a/interfaces/netconfig-iface-ethernet.xml b/interfaces/netconfig-iface-ethernet.xml new file mode 100755 index 0000000..11d4d45 --- /dev/null +++ b/interfaces/netconfig-iface-ethernet.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/resources/etc/dbus-1/system.d/net-config.conf b/resources/etc/dbus-1/system.d/net-config.conf index b37e0a3..88371b6 100755 --- a/resources/etc/dbus-1/system.d/net-config.conf +++ b/resources/etc/dbus-1/system.d/net-config.conf @@ -116,5 +116,9 @@ + + + + diff --git a/src/dbus/netdbus.c b/src/dbus/netdbus.c index 7c25df8..2abc159 100755 --- a/src/dbus/netdbus.c +++ b/src/dbus/netdbus.c @@ -43,6 +43,7 @@ static GDBusObjectManagerServer *manager_server_state = NULL; static GDBusObjectManagerServer *manager_server_statistics = NULL; static GDBusObjectManagerServer *manager_server_vpn = NULL; static GDBusObjectManagerServer *manager_server_mptcp = NULL; +static GDBusObjectManagerServer *manager_server_ethernet = NULL; static guint owner_id = 0; static got_name_cb g_callback = NULL; @@ -79,6 +80,11 @@ GDBusObjectManagerServer *netdbus_get_mptcp_manager(void) return manager_server_mptcp; } +GDBusObjectManagerServer *netdbus_get_ethernet_manager(void) +{ + return manager_server_ethernet; +} + GDBusConnection *netdbus_get_connection(void) { return gconn_data.connection; @@ -342,6 +348,12 @@ int setup_gdbus(got_name_cb cb) exit(1); } + manager_server_ethernet = g_dbus_object_manager_server_new(NETCONFIG_ETHERNET_PATH); + if (manager_server_ethernet == NULL) { + ERR("Manager server for NETCONFIG_ETHERNET_PATH not created."); + exit(1); + } + owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, NETCONFIG_SERVICE, G_BUS_NAME_OWNER_FLAGS_NONE, _got_bus_cb, _got_name_cb, _lost_name_cb, diff --git a/src/dbus/netsupplicant.c b/src/dbus/netsupplicant.c index e422128..ee52eec 100755 --- a/src/dbus/netsupplicant.c +++ b/src/dbus/netsupplicant.c @@ -21,20 +21,23 @@ #include "netdbus.h" #include "netsupplicant.h" -char *netconfig_wifi_get_supplicant_interface(void) +char *netconfig_get_supplicant_interface(const char *ifname) { GVariant *message = NULL; GVariant *params = NULL; gchar *path = NULL; - params = g_variant_new("(s)", WIFI_IFNAME); + if (!ifname) + return NULL; + + params = g_variant_new("(s)", ifname); message = netconfig_supplicant_invoke_dbus_method( SUPPLICANT_SERVICE, SUPPLICANT_PATH, SUPPLICANT_INTERFACE, "GetInterface", params); if (message == NULL) { - ERR("Failed to get object path"); + ERR("Failed to get interface"); return NULL; } @@ -45,6 +48,11 @@ char *netconfig_wifi_get_supplicant_interface(void) return (char *)path; } +char *netconfig_wifi_get_supplicant_interface(void) +{ + return netconfig_get_supplicant_interface(WIFI_IFNAME); +} + char *netconfig_wifi_get_supplicant_p2p_interface(void) { GVariant *message = NULL; diff --git a/src/ethernet.c b/src/ethernet.c new file mode 100644 index 0000000..8c7fb52 --- /dev/null +++ b/src/ethernet.c @@ -0,0 +1,301 @@ +/* + * Network Configuration - EAPoL Service Module + * + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "ethernet.h" +#include "netdbus.h" +#include "util.h" +#include "log.h" +#include "wifi-power.h" +#include "netsupplicant.h" + +#define EAPOL_STORAGEDIR "/opt/usr/data/network/" +#define ETH_IFNAME "eth0" + +#define CONNMAN_CONFIG_FIELD_EAP_METHOD "EAP" +#define CONNMAN_CONFIG_FIELD_IDENTITY "Identity" +#define CONNMAN_CONFIG_FIELD_PASSPHRASE "Passphrase" +#define CONNMAN_CONFIG_FIELD_ANONYMOUS_IDENTITY "AnonymousIdentity" +#define CONNMAN_CONFIG_FIELD_CA_CERT_FILE "CACertFile" +#define CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE "ClientCertFile" +#define CONNMAN_CONFIG_FIELD_PVT_KEY_FILE "PrivateKeyFile" +#define CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE "PrivateKeyPassphrase" +#define CONNMAN_CONFIG_FIELD_PAC_FILE "PacFile" +#define CONNMAN_CONFIG_FIELD_PHASE2 "Phase2" +#define CONNMAN_CONFIG_FIELD_PHASE1 "Phase1" + +static Ethernet *ethernet_object = NULL; +static gboolean g_eap_supported = FALSE; + +Ethernet *get_ethernet_object(void) +{ + return ethernet_object; +} + +static gboolean __netconfig_set_eap_config_file(GVariant *fields) +{ + GVariantIter *iter; + gchar *field, *value; + gchar *filename = NULL; + FILE *fp = NULL; + int err = 0; + + /* create eapol conf file */ + filename = g_strdup_printf("%s/%s-eapol.conf", EAPOL_STORAGEDIR, ETH_IFNAME); + if (!filename) { + ERR("Failed to allocate memory."); + err = -ENOMEM; + goto out; + } + + fp = fopen(filename, "w"); + if (!fp) { + ERR("Failed to open %s", filename); + err = -EIO; + goto out; + } + + /* update eapol conf file */ + fprintf (fp, "network={\n"); + fprintf (fp, "key_mgmt=WPA-EAP\n"); + + g_variant_get(fields, "a{ss}", &iter); + while (g_variant_iter_loop(iter, "{ss}", &field, &value)) { + if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_EAP_METHOD) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "eap=%s\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_IDENTITY) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "identity=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_ANONYMOUS_IDENTITY) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "anonymous_identity=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PASSPHRASE) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "password=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CA_CERT_FILE) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "ca_cert=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "client_cert=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_FILE) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "private_key=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "private_key_passwd=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PAC_FILE) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) + fprintf (fp, "pac_file=\"%s\"\n", value); + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE2) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) { + char str[50] = {0,}; + sprintf(str, "auth=%s", value); + fprintf (fp, "phase2=\"%s\"\n", str); + } + } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE1) == 0) { + DBG("field: %s, value: %s", field, value); + + if (value != NULL) { + int peap_version; + char str[50] = {0,}; + if ((g_strcmp0(value, "VERSION_AUTO") == 0) || + (g_strcmp0(value, "VERSION_0") == 0)) + peap_version = 0; + else + peap_version = 1; + sprintf(str, "peapver=%d", peap_version); + fprintf (fp, "phase1=\"%s\"\n", str); + } + } + } + + fprintf (fp, "}"); /* closing of conf file */ + fflush(fp); +out: + g_free(filename); + fclose(fp); + fp = NULL; + + return err; +} + +/********************* + * Handler Functions * + ********************/ + +gboolean handle_enable_eap(Ethernet *object, GDBusMethodInvocation *invocation, + const gchar *service, gboolean enable) +{ + g_return_val_if_fail(object != NULL, TRUE); + + DBG("%s EAPoL", enable ? "enable" : "disable"); + + if (netconfig_is_ethernet_profile(service) != TRUE) { + netconfig_error_dbus_method_return(invocation, NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService"); + return TRUE; + } + + /* TODO: Execute WPA Supplicant if not running */ + __execute_supplicant(enable); + + /* TODO: Make below variable interface specific and set + connMan profile associated with this interface as EAP enabled. + */ + g_eap_supported = enable; + + if (enable == false) { + gboolean use_eapol = false; + GVariant *params = g_variant_new("(sv)", "UseEapol", g_variant_new_boolean(use_eapol)); + + GVariant *message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, service, + CONNMAN_SERVICE_INTERFACE, "SetProperty", params); + if (message == NULL) + ERR("Failed to reset EAPoL property"); + + g_variant_unref(message); + } + + ethernet_complete_enable_eap(object, invocation); + return TRUE; +} + +gboolean handle_is_eap_supported(Ethernet *object, GDBusMethodInvocation *invocation) +{ + g_return_val_if_fail(object != NULL, TRUE); + + DBG("handle_is_eap_supported"); + gboolean value = FALSE; + + value = g_eap_supported; + + ethernet_complete_is_eap_supported(object, invocation, value); + return TRUE; +} + +gboolean handle_set_eap_config(Ethernet *object, GDBusMethodInvocation *invocation, + const gchar *service, GVariant *fields) +{ + g_return_val_if_fail(object != NULL, TRUE); + + GVariant *message = NULL; + GVariant *params = NULL; + gboolean use_eapol = true; + + DBG("handle_set_eap_config for service [%s]", service); + + if (netconfig_is_ethernet_profile(service) != TRUE) { + netconfig_error_dbus_method_return(invocation, NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService"); + return TRUE; + } + + if (g_eap_supported == FALSE) { + netconfig_error_dbus_method_return(invocation, + NETCONFIG_ERROR_INTERNAL, + "EapNotEnabled"); + return TRUE; + } + + /** Create conf file */ + int err = __netconfig_set_eap_config_file(fields); + if (err < 0) { + ERR("Failed to save eapol conf file."); + netconfig_error_dbus_method_return(invocation, NETCONFIG_ERROR_INTERNAL, "InternalError"); + return TRUE; + } + + params = g_variant_new("(sv)", "UseEapol", g_variant_new_boolean(use_eapol)); + + message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, service, + CONNMAN_SERVICE_INTERFACE, "SetProperty", params); + if (message == NULL) + ERR("Failed to Set EAPoL property"); + + g_variant_unref(message); + + ethernet_complete_set_eap_config(object, invocation); + return TRUE; +} + +/***************************** + * Initializations Functions * + ****************************/ +void ethernet_object_create_and_init(void) +{ + DBG("Create ethernet object."); + GDBusInterfaceSkeleton *interface_ethernet = NULL; + GDBusConnection *connection = NULL; + GDBusObjectManagerServer *server = netdbus_get_ethernet_manager(); + if (server == NULL) + return; + + connection = netdbus_get_connection(); + g_dbus_object_manager_server_set_connection(server, connection); + + /* Interface */ + ethernet_object = ethernet_skeleton_new(); + interface_ethernet = G_DBUS_INTERFACE_SKELETON(ethernet_object); + + /* EAP over Ethernet Service */ + g_signal_connect(ethernet_object, "handle-enable-eap", + G_CALLBACK(handle_enable_eap), NULL); + g_signal_connect(ethernet_object, "handle-is-eap-supported", + G_CALLBACK(handle_is_eap_supported), NULL); + g_signal_connect(ethernet_object, "handle-set-eap-config", + G_CALLBACK(handle_set_eap_config), NULL); + + if (!g_dbus_interface_skeleton_export(interface_ethernet, connection, + NETCONFIG_ETHERNET_PATH, NULL)) { + ERR("Export NETCONFIG_ETHERNET_PATH for ethernet failed"); + } + + return; +} + +void ethernet_object_deinit(void) +{ + DBG("Deinit ethernet object."); + + g_object_unref(ethernet_object); +} diff --git a/src/main.c b/src/main.c index 6c4c648..ba0c6d5 100755 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ #include "signal-handler.h" #include "network-statistics.h" #include "network-dump.h" +#include "ethernet.h" static GMainLoop *main_loop = NULL; @@ -60,6 +61,7 @@ void _got_name_cb(void) statistics_object_create_and_init(); vpnsvc_create_and_init(); mptcp_object_create_and_init(); + ethernet_object_create_and_init(); register_gdbus_signal(); connman_register_agent(); @@ -76,6 +78,7 @@ static void _objects_deinit(void) statistics_object_deinit(); vpnsvc_destroy_deinit(); mptcp_object_deinit(); + ethernet_object_deinit(); } int main(int argc, char *argv[]) @@ -105,6 +108,12 @@ int main(int argc, char *argv[]) g_type_init(); #endif + /* + * TODO: Remove this temp change to start wpa_supplicant + * when ConnMan device some mechanism for EAP on Ethernet. + */ + __execute_supplicant(true); + main_loop = g_main_loop_new(NULL, FALSE); if (main_loop == NULL) { ERR("Couldn't create GMainLoop\n"); diff --git a/src/wifi-power.c b/src/wifi-power.c index 947716f..2226d3a 100755 --- a/src/wifi-power.c +++ b/src/wifi-power.c @@ -126,12 +126,18 @@ static void __technology_reply(GObject *source_object, GAsyncResult *res, gpoint netconfig_gdbus_pending_call_unref(); } -static int __execute_supplicant(gboolean enable) +int __execute_supplicant(gboolean enable) { + /* + * TODO: [EAP on Ethernet] Temporary blocked wpa_supp.sh stop + * untill ConnMan adds logic to trigger/control wpa_supplicant interface. + */ int rv = 0; const char *path = WLAN_SUPPLICANT_SCRIPT; char *const args_enable[] = { "/usr/bin/wpa_supp.sh", "start", NULL }; +#if 0 char *const args_disable[] = { "/usr/bin/wpa_supp.sh", "stop", NULL }; +#endif char *const envs[] = { NULL }; static gboolean enabled = FALSE; @@ -140,14 +146,17 @@ static int __execute_supplicant(gboolean enable) if (enable == TRUE) rv = netconfig_execute_file(path, args_enable, envs); +#if 0 else rv = netconfig_execute_file(path, args_disable, envs); +#endif if (rv < 0) return -EIO; DBG("wpa_supplicant %s", enable == TRUE ? "started" : "stopped"); - enabled = enable; + if (enable) + enabled = enable; return 0; } -- 2.34.1