[net-config] Added support for EAPoL connection.
[platform/core/connectivity/net-config.git] / src / ethernet.c
1 /*
2  * Network Configuration - EAPoL Service Module
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <gio/gunixfdlist.h>
24
25 #include "ethernet.h"
26 #include "netdbus.h"
27 #include "util.h"
28 #include "log.h"
29 #include "wifi-power.h"
30 #include "netsupplicant.h"
31
32 #define EAPOL_STORAGEDIR        "/opt/usr/data/network/"
33 #define ETH_IFNAME              "eth0"
34
35 #define CONNMAN_CONFIG_FIELD_EAP_METHOD         "EAP"
36 #define CONNMAN_CONFIG_FIELD_IDENTITY           "Identity"
37 #define CONNMAN_CONFIG_FIELD_PASSPHRASE         "Passphrase"
38 #define CONNMAN_CONFIG_FIELD_ANONYMOUS_IDENTITY "AnonymousIdentity"
39 #define CONNMAN_CONFIG_FIELD_CA_CERT_FILE       "CACertFile"
40 #define CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE   "ClientCertFile"
41 #define CONNMAN_CONFIG_FIELD_PVT_KEY_FILE       "PrivateKeyFile"
42 #define CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE "PrivateKeyPassphrase"
43 #define CONNMAN_CONFIG_FIELD_PAC_FILE           "PacFile"
44 #define CONNMAN_CONFIG_FIELD_PHASE2             "Phase2"
45 #define CONNMAN_CONFIG_FIELD_PHASE1             "Phase1"
46
47 static Ethernet *ethernet_object = NULL;
48 static gboolean g_eap_supported = FALSE;
49
50 Ethernet *get_ethernet_object(void)
51 {
52         return ethernet_object;
53 }
54
55 static gboolean __netconfig_set_eap_config_file(GVariant *fields)
56 {
57         GVariantIter *iter;
58         gchar *field, *value;
59         gchar *filename = NULL;
60         FILE *fp = NULL;
61         int err = 0;
62
63         /* create eapol conf file */
64         filename = g_strdup_printf("%s/%s-eapol.conf", EAPOL_STORAGEDIR, ETH_IFNAME);
65         if (!filename) {
66                 ERR("Failed to allocate memory.");
67                 err = -ENOMEM;
68                 goto out;
69         }
70
71         fp = fopen(filename, "w");
72         if (!fp) {
73                 ERR("Failed to open %s", filename);
74                 err = -EIO;
75                 goto out;
76         }
77
78         /* update eapol conf file */
79         fprintf (fp, "network={\n");
80         fprintf (fp, "key_mgmt=WPA-EAP\n");
81
82         g_variant_get(fields, "a{ss}", &iter);
83         while (g_variant_iter_loop(iter, "{ss}", &field, &value)) {
84                 if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_EAP_METHOD) == 0) {
85                         DBG("field: %s, value: %s", field, value);
86
87                         if (value != NULL)
88                                 fprintf (fp, "eap=%s\n", value);
89                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_IDENTITY) == 0) {
90                         DBG("field: %s, value: %s", field, value);
91
92                         if (value != NULL)
93                                 fprintf (fp, "identity=\"%s\"\n", value);
94                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_ANONYMOUS_IDENTITY) == 0) {
95                         DBG("field: %s, value: %s", field, value);
96
97                         if (value != NULL)
98                                 fprintf (fp, "anonymous_identity=\"%s\"\n", value);
99                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PASSPHRASE) == 0) {
100                         DBG("field: %s, value: %s", field, value);
101
102                         if (value != NULL)
103                                 fprintf (fp, "password=\"%s\"\n", value);
104                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CA_CERT_FILE) == 0) {
105                         DBG("field: %s, value: %s", field, value);
106
107                         if (value != NULL)
108                                 fprintf (fp, "ca_cert=\"%s\"\n", value);
109                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_CLIENT_CERT_FILE) == 0) {
110                         DBG("field: %s, value: %s", field, value);
111
112                         if (value != NULL)
113                                 fprintf (fp, "client_cert=\"%s\"\n", value);
114                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_FILE) == 0) {
115                         DBG("field: %s, value: %s", field, value);
116
117                         if (value != NULL)
118                                 fprintf (fp, "private_key=\"%s\"\n", value);
119                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PVT_KEY_PASSPHRASE) == 0) {
120                         DBG("field: %s, value: %s", field, value);
121
122                         if (value != NULL)
123                                 fprintf (fp, "private_key_passwd=\"%s\"\n", value);
124                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PAC_FILE) == 0) {
125                         DBG("field: %s, value: %s", field, value);
126
127                         if (value != NULL)
128                                 fprintf (fp, "pac_file=\"%s\"\n", value);
129                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE2) == 0) {
130                         DBG("field: %s, value: %s", field, value);
131
132                         if (value != NULL) {
133                                 char str[50] = {0,};
134                                 sprintf(str, "auth=%s", value);
135                                 fprintf (fp, "phase2=\"%s\"\n", str);
136                         }
137                 } else if (g_strcmp0(field, CONNMAN_CONFIG_FIELD_PHASE1) == 0) {
138                         DBG("field: %s, value: %s", field, value);
139
140                         if (value != NULL) {
141                                 int peap_version;
142                                 char str[50] = {0,};
143                                 if ((g_strcmp0(value, "VERSION_AUTO") == 0) ||
144                                                 (g_strcmp0(value, "VERSION_0") == 0))
145                                         peap_version = 0;
146                                 else
147                                         peap_version = 1;
148                                 sprintf(str, "peapver=%d", peap_version);
149                                 fprintf (fp, "phase1=\"%s\"\n", str);
150                         }
151                 }
152         }
153
154         fprintf (fp, "}");      /* closing of conf file */
155         fflush(fp);
156 out:
157         g_free(filename);
158         fclose(fp);
159         fp = NULL;
160
161         return err;
162 }
163
164 /*********************
165  * Handler Functions *
166  ********************/
167
168 gboolean handle_enable_eap(Ethernet *object, GDBusMethodInvocation *invocation,
169                            const gchar *service, gboolean enable)
170 {
171         g_return_val_if_fail(object != NULL, TRUE);
172
173         DBG("%s EAPoL", enable ? "enable" : "disable");
174
175         if (netconfig_is_ethernet_profile(service) != TRUE) {
176                 netconfig_error_dbus_method_return(invocation, NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService");
177                 return TRUE;
178         }
179
180         /* TODO: Execute WPA Supplicant if not running */
181         __execute_supplicant(enable);
182
183         /* TODO: Make below variable interface specific and set
184         connMan profile associated with this interface as EAP enabled.
185         */
186         g_eap_supported = enable;
187
188         if (enable == false) {
189                 gboolean use_eapol = false;
190                 GVariant *params = g_variant_new("(sv)", "UseEapol", g_variant_new_boolean(use_eapol));
191
192                 GVariant *message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, service,
193                                 CONNMAN_SERVICE_INTERFACE, "SetProperty", params);
194                 if (message == NULL)
195                         ERR("Failed to reset EAPoL property");
196
197                 g_variant_unref(message);
198         }
199
200         ethernet_complete_enable_eap(object, invocation);
201         return TRUE;
202 }
203
204 gboolean handle_is_eap_supported(Ethernet *object, GDBusMethodInvocation *invocation)
205 {
206         g_return_val_if_fail(object != NULL, TRUE);
207
208         DBG("handle_is_eap_supported");
209         gboolean value = FALSE;
210
211         value = g_eap_supported;
212
213         ethernet_complete_is_eap_supported(object, invocation, value);
214         return TRUE;
215 }
216
217 gboolean handle_set_eap_config(Ethernet *object, GDBusMethodInvocation *invocation,
218                         const gchar *service, GVariant *fields)
219 {
220         g_return_val_if_fail(object != NULL, TRUE);
221
222         GVariant *message = NULL;
223         GVariant *params = NULL;
224         gboolean use_eapol = true;
225
226         DBG("handle_set_eap_config for service [%s]", service);
227
228         if (netconfig_is_ethernet_profile(service) != TRUE) {
229                 netconfig_error_dbus_method_return(invocation, NETCONFIG_ERROR_WRONG_PROFILE, "InvalidService");
230                 return TRUE;
231         }
232
233         if (g_eap_supported == FALSE) {
234                 netconfig_error_dbus_method_return(invocation,
235                                                    NETCONFIG_ERROR_INTERNAL,
236                                                    "EapNotEnabled");
237                 return TRUE;
238         }
239
240         /** Create conf file */
241         int err = __netconfig_set_eap_config_file(fields);
242         if (err < 0) {
243                 ERR("Failed to save eapol conf file.");
244                 netconfig_error_dbus_method_return(invocation, NETCONFIG_ERROR_INTERNAL, "InternalError");
245                 return TRUE;
246         }
247
248         params = g_variant_new("(sv)", "UseEapol", g_variant_new_boolean(use_eapol));
249
250         message = netconfig_invoke_dbus_method(CONNMAN_SERVICE, service,
251                         CONNMAN_SERVICE_INTERFACE, "SetProperty", params);
252         if (message == NULL)
253                 ERR("Failed to Set EAPoL property");
254
255         g_variant_unref(message);
256
257         ethernet_complete_set_eap_config(object, invocation);
258         return TRUE;
259 }
260
261 /*****************************
262  * Initializations Functions *
263  ****************************/
264 void ethernet_object_create_and_init(void)
265 {
266         DBG("Create ethernet object.");
267         GDBusInterfaceSkeleton *interface_ethernet = NULL;
268         GDBusConnection *connection = NULL;
269         GDBusObjectManagerServer *server = netdbus_get_ethernet_manager();
270         if (server == NULL)
271                 return;
272
273         connection = netdbus_get_connection();
274         g_dbus_object_manager_server_set_connection(server, connection);
275
276         /* Interface */
277         ethernet_object = ethernet_skeleton_new();
278         interface_ethernet = G_DBUS_INTERFACE_SKELETON(ethernet_object);
279
280         /* EAP over Ethernet Service */
281         g_signal_connect(ethernet_object, "handle-enable-eap",
282                         G_CALLBACK(handle_enable_eap), NULL);
283         g_signal_connect(ethernet_object, "handle-is-eap-supported",
284                         G_CALLBACK(handle_is_eap_supported), NULL);
285         g_signal_connect(ethernet_object, "handle-set-eap-config",
286                         G_CALLBACK(handle_set_eap_config), NULL);
287
288         if (!g_dbus_interface_skeleton_export(interface_ethernet, connection,
289                         NETCONFIG_ETHERNET_PATH, NULL)) {
290                 ERR("Export NETCONFIG_ETHERNET_PATH for ethernet failed");
291         }
292
293         return;
294 }
295
296 void ethernet_object_deinit(void)
297 {
298         DBG("Deinit ethernet object.");
299
300         g_object_unref(ethernet_object);
301 }