--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <gio/gunixfdlist.h>
+
+#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);
+}