GCC Code Coverage Report


Directory: ./
File: panels/network/connection-editor/ce-page-security.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 258 0.0%
Functions: 0 20 0.0%
Branches: 0 193 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2012 Red Hat, Inc
4 *
5 * Licensed under the GNU General Public License Version 2
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include "config.h"
23
24 #include <glib/gi18n.h>
25
26 #include <NetworkManager.h>
27
28 #include "ce-page.h"
29 #include "ce-page-security.h"
30 #include "nma-ws.h"
31
32 struct _CEPageSecurity
33 {
34 AdwBin parent;
35
36 GtkBox *box;
37 GtkComboBox *security_combo;
38 GtkLabel *security_label;
39
40 NMConnection *connection;
41 const gchar *security_setting;
42 GtkSizeGroup *group;
43 gboolean adhoc;
44 };
45
46 static void ce_page_iface_init (CEPageInterface *);
47
48 G_DEFINE_TYPE_WITH_CODE (CEPageSecurity, ce_page_security, ADW_TYPE_BIN,
49 G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init))
50
51 enum {
52 S_NAME_COLUMN,
53 S_SEC_COLUMN,
54 S_ADHOC_VALID_COLUMN
55 };
56
57 static gboolean
58 find_proto (NMSettingWirelessSecurity *sec, const char *item)
59 {
60 guint32 i;
61
62 for (i = 0; i < nm_setting_wireless_security_get_num_protos (sec); i++) {
63 if (!strcmp (item, nm_setting_wireless_security_get_proto (sec, i)))
64 return TRUE;
65 }
66 return FALSE;
67 }
68
69 static NMUtilsSecurityType
70 get_default_type_for_security (NMSettingWirelessSecurity *sec)
71 {
72 const char *key_mgmt, *auth_alg;
73
74 g_return_val_if_fail (sec != NULL, NMU_SEC_NONE);
75
76 key_mgmt = nm_setting_wireless_security_get_key_mgmt (sec);
77 auth_alg = nm_setting_wireless_security_get_auth_alg (sec);
78
79 /* No IEEE 802.1x */
80 if (!strcmp (key_mgmt, "none"))
81 return NMU_SEC_STATIC_WEP;
82
83 if (!strcmp (key_mgmt, "ieee8021x")) {
84 if (auth_alg && !strcmp (auth_alg, "leap"))
85 return NMU_SEC_LEAP;
86 return NMU_SEC_DYNAMIC_WEP;
87 }
88
89 #if NM_CHECK_VERSION(1,24,0)
90 if (!strcmp (key_mgmt, "owe")) {
91 return NMU_SEC_OWE;
92 }
93 #endif
94
95 #if NM_CHECK_VERSION(1,20,6)
96 if (!strcmp (key_mgmt, "sae")) {
97 return NMU_SEC_SAE;
98 }
99 #endif
100
101 if ( !strcmp (key_mgmt, "wpa-psk")) {
102 if (find_proto (sec, "rsn"))
103 return NMU_SEC_WPA2_PSK;
104 else if (find_proto (sec, "wpa"))
105 return NMU_SEC_WPA_PSK;
106 else
107 return NMU_SEC_WPA_PSK;
108 }
109
110 if (!strcmp (key_mgmt, "wpa-eap")) {
111 if (find_proto (sec, "rsn"))
112 return NMU_SEC_WPA2_ENTERPRISE;
113 else if (find_proto (sec, "wpa"))
114 return NMU_SEC_WPA_ENTERPRISE;
115 else
116 return NMU_SEC_WPA_ENTERPRISE;
117 }
118
119 return NMU_SEC_INVALID;
120 }
121
122 static NMAWs *
123 security_combo_get_active (CEPageSecurity *self)
124 {
125 GtkTreeIter iter;
126 GtkTreeModel *model;
127 NMAWs *sec;
128
129 model = gtk_combo_box_get_model (self->security_combo);
130 if (!gtk_combo_box_get_active_iter (self->security_combo, &iter))
131 return NULL;
132 gtk_tree_model_get (model, &iter, S_SEC_COLUMN, &sec, -1);
133
134 return sec;
135 }
136
137 static void
138 wsec_size_group_clear (GtkSizeGroup *group)
139 {
140 GSList *children;
141 GSList *iter;
142
143 g_return_if_fail (group != NULL);
144
145 children = gtk_size_group_get_widgets (group);
146 for (iter = children; iter; iter = g_slist_next (iter))
147 gtk_size_group_remove_widget (group, GTK_WIDGET (iter->data));
148 }
149
150 static void
151 security_combo_changed (CEPageSecurity *self)
152 {
153 NMAWs *sec;
154 GtkWidget *child;
155
156 wsec_size_group_clear (self->group);
157
158 while ((child = gtk_widget_get_first_child (GTK_WIDGET (self->box))) != NULL)
159 gtk_box_remove (self->box, child);
160
161 sec = security_combo_get_active (self);
162 if (sec) {
163 if (gtk_widget_get_parent (GTK_WIDGET (sec)))
164 gtk_box_remove (self->box, GTK_WIDGET (sec));
165
166 gtk_size_group_add_widget (self->group, GTK_WIDGET (self->security_label));
167 nma_ws_add_to_size_group (sec, self->group);
168
169 gtk_box_append (self->box, g_object_ref (GTK_WIDGET (sec)));
170 g_object_unref (sec);
171 }
172
173 ce_page_changed (CE_PAGE (self));
174 }
175
176 static void
177 security_item_changed_cb (CEPageSecurity *self)
178 {
179 ce_page_changed (CE_PAGE (self));
180 }
181
182 static void
183 add_security_item (CEPageSecurity *self,
184 NMAWs *sec,
185 GtkListStore *model,
186 GtkTreeIter *iter,
187 const char *text,
188 gboolean adhoc_valid)
189 {
190 if (G_IS_INITIALLY_UNOWNED (sec))
191 g_object_ref_sink (sec);
192 g_signal_connect_object (sec, "ws-changed", G_CALLBACK (security_item_changed_cb), self, G_CONNECT_SWAPPED);
193 gtk_list_store_append (model, iter);
194 gtk_list_store_set (model, iter,
195 S_NAME_COLUMN, text,
196 S_SEC_COLUMN, sec,
197 S_ADHOC_VALID_COLUMN, adhoc_valid,
198 -1);
199 g_object_unref (sec);
200 }
201
202 static void
203 set_sensitive (GtkCellLayout *cell_layout,
204 GtkCellRenderer *cell,
205 GtkTreeModel *tree_model,
206 GtkTreeIter *iter,
207 gpointer data)
208 {
209 gboolean *adhoc = data;
210 gboolean sensitive = TRUE, adhoc_valid = TRUE;
211
212 gtk_tree_model_get (tree_model, iter, S_ADHOC_VALID_COLUMN, &adhoc_valid, -1);
213 if (*adhoc && !adhoc_valid)
214 sensitive = FALSE;
215
216 g_object_set (cell, "sensitive", sensitive, NULL);
217 }
218
219 static void
220 finish_setup (CEPageSecurity *self)
221 {
222 NMSettingWireless *sw;
223 NMSettingWirelessSecurity *sws;
224 gboolean is_adhoc = FALSE;
225 g_autoptr(GtkListStore) sec_model = NULL;
226 GtkTreeIter iter;
227 const gchar *mode;
228 guint32 dev_caps = 0;
229 NMUtilsSecurityType default_type = NMU_SEC_NONE;
230 int active = -1;
231 int item = 0;
232 GtkCellRenderer *renderer;
233
234 sw = nm_connection_get_setting_wireless (self->connection);
235 g_assert (sw);
236
237 self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
238
239 dev_caps = NM_WIFI_DEVICE_CAP_CIPHER_WEP40
240 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104
241 | NM_WIFI_DEVICE_CAP_CIPHER_TKIP
242 | NM_WIFI_DEVICE_CAP_CIPHER_CCMP
243 | NM_WIFI_DEVICE_CAP_WPA
244 | NM_WIFI_DEVICE_CAP_RSN;
245
246 mode = nm_setting_wireless_get_mode (sw);
247 if (mode && !strcmp (mode, "adhoc"))
248 is_adhoc = TRUE;
249 self->adhoc = is_adhoc;
250
251 sws = nm_connection_get_setting_wireless_security (self->connection);
252 if (sws)
253 default_type = get_default_type_for_security (sws);
254
255 sec_model = gtk_list_store_new (3, G_TYPE_STRING, NMA_TYPE_WS, G_TYPE_BOOLEAN);
256
257 if (nm_utils_security_valid (NMU_SEC_NONE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
258 gtk_list_store_insert_with_values (sec_model, &iter, -1,
259 S_NAME_COLUMN, C_("Wi-Fi/Ethernet security", "None"),
260 S_ADHOC_VALID_COLUMN, TRUE,
261 -1);
262 if (default_type == NMU_SEC_NONE)
263 active = item;
264 item++;
265 }
266
267 #if NM_CHECK_VERSION(1,24,0)
268 if (nm_utils_security_valid (NMU_SEC_OWE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
269 gtk_list_store_insert_with_values (sec_model, &iter, -1,
270 S_NAME_COLUMN, _("Enhanced Open"),
271 S_ADHOC_VALID_COLUMN, FALSE,
272 -1);
273 if (active < 0 && default_type == NMU_SEC_OWE)
274 active = item;
275 item++;
276 }
277 #endif
278
279 if (nm_utils_security_valid (NMU_SEC_STATIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
280 NMAWsWepKey *ws_wep;
281 NMWepKeyType wep_type = NM_WEP_KEY_TYPE_KEY;
282
283 if (default_type == NMU_SEC_STATIC_WEP) {
284 sws = nm_connection_get_setting_wireless_security (self->connection);
285 if (sws)
286 wep_type = nm_setting_wireless_security_get_wep_key_type (sws);
287 if (wep_type == NM_WEP_KEY_TYPE_UNKNOWN)
288 wep_type = NM_WEP_KEY_TYPE_KEY;
289 }
290
291 ws_wep = nma_ws_wep_key_new (self->connection, NM_WEP_KEY_TYPE_KEY, FALSE, FALSE);
292 if (ws_wep) {
293 add_security_item (self, NMA_WS (ws_wep), sec_model,
294 &iter, _("WEP 40/128-bit Key (Hex or ASCII)"),
295 TRUE);
296 if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_KEY))
297 active = item;
298 item++;
299 }
300
301 ws_wep = nma_ws_wep_key_new (self->connection, NM_WEP_KEY_TYPE_PASSPHRASE, FALSE, FALSE);
302 if (ws_wep) {
303 add_security_item (self, NMA_WS (ws_wep), sec_model,
304 &iter, _("WEP 128-bit Passphrase"), TRUE);
305 if ((active < 0) && (default_type == NMU_SEC_STATIC_WEP) && (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE))
306 active = item;
307 item++;
308 }
309 }
310
311 if (nm_utils_security_valid (NMU_SEC_LEAP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
312 NMAWsLeap *ws_leap;
313
314 ws_leap = nma_ws_leap_new (self->connection, FALSE);
315 if (ws_leap) {
316 add_security_item (self, NMA_WS (ws_leap), sec_model,
317 &iter, _("LEAP"), FALSE);
318 if ((active < 0) && (default_type == NMU_SEC_LEAP))
319 active = item;
320 item++;
321 }
322 }
323
324 if (nm_utils_security_valid (NMU_SEC_DYNAMIC_WEP, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
325 NMAWsDynamicWep *ws_dynamic_wep;
326
327 ws_dynamic_wep = nma_ws_dynamic_wep_new (self->connection, TRUE, FALSE);
328 if (ws_dynamic_wep) {
329 add_security_item (self, NMA_WS (ws_dynamic_wep), sec_model,
330 &iter, _("Dynamic WEP (802.1x)"), FALSE);
331 if ((active < 0) && (default_type == NMU_SEC_DYNAMIC_WEP))
332 active = item;
333 item++;
334 }
335 }
336
337 if (nm_utils_security_valid (NMU_SEC_WPA_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
338 nm_utils_security_valid (NMU_SEC_WPA2_PSK, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
339 NMAWsWpaPsk *ws_wpa_psk;
340
341 ws_wpa_psk = nma_ws_wpa_psk_new (self->connection, FALSE);
342 if (ws_wpa_psk) {
343 add_security_item (self, NMA_WS (ws_wpa_psk), sec_model,
344 &iter, _("WPA & WPA2 Personal"), FALSE);
345 if ((active < 0) && ((default_type == NMU_SEC_WPA_PSK) || (default_type == NMU_SEC_WPA2_PSK)))
346 active = item;
347 item++;
348 }
349 }
350
351 if (nm_utils_security_valid (NMU_SEC_WPA_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0) ||
352 nm_utils_security_valid (NMU_SEC_WPA2_ENTERPRISE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
353 NMAWsWpaEap *ws_wpa_eap;
354
355 ws_wpa_eap = nma_ws_wpa_eap_new (self->connection, TRUE, FALSE, NULL);
356 if (ws_wpa_eap) {
357 add_security_item (self, NMA_WS (ws_wpa_eap), sec_model,
358 &iter, _("WPA & WPA2 Enterprise"), FALSE);
359 if ((active < 0) && ((default_type == NMU_SEC_WPA_ENTERPRISE) || (default_type == NMU_SEC_WPA2_ENTERPRISE)))
360 active = item;
361 item++;
362 }
363 }
364
365 #if NM_CHECK_VERSION(1,20,6)
366 if (nm_utils_security_valid (NMU_SEC_SAE, dev_caps, FALSE, is_adhoc, 0, 0, 0)) {
367 NMAWsSae *ws_sae;
368
369 ws_sae = nma_ws_sae_new (self->connection, FALSE);
370 if (ws_sae) {
371 add_security_item (self, NMA_WS (ws_sae), sec_model,
372 &iter, _("WPA3 Personal"), FALSE);
373 if ((active < 0) && ((default_type == NMU_SEC_SAE)))
374 active = item;
375 item++;
376 }
377 }
378 #endif
379
380 gtk_combo_box_set_model (self->security_combo, GTK_TREE_MODEL (sec_model));
381 gtk_cell_layout_clear (GTK_CELL_LAYOUT (self->security_combo));
382
383 renderer = gtk_cell_renderer_text_new ();
384 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->security_combo), renderer, TRUE);
385 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self->security_combo), renderer, "text", S_NAME_COLUMN, NULL);
386 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (self->security_combo), renderer, set_sensitive, &self->adhoc, NULL);
387
388 gtk_combo_box_set_active (self->security_combo, active < 0 ? 0 : (guint32) active);
389
390 security_combo_changed (self);
391 g_signal_connect_object (self->security_combo, "changed",
392 G_CALLBACK (security_combo_changed), self, G_CONNECT_SWAPPED);
393 }
394
395 static void
396 ce_page_security_dispose (GObject *object)
397 {
398 CEPageSecurity *self = CE_PAGE_SECURITY (object);
399
400 g_clear_object (&self->connection);
401 g_clear_object (&self->group);
402
403 G_OBJECT_CLASS (ce_page_security_parent_class)->dispose (object);
404 }
405
406 static const gchar *
407 ce_page_security_get_security_setting (CEPage *page)
408 {
409 return CE_PAGE_SECURITY (page)->security_setting;
410 }
411
412 static const gchar *
413 ce_page_security_get_title (CEPage *page)
414 {
415 return _("Security");
416 }
417
418 static gboolean
419 ce_page_security_validate (CEPage *page,
420 NMConnection *connection,
421 GError **error)
422 {
423 CEPageSecurity *self = CE_PAGE_SECURITY (page);
424 NMSettingWireless *sw;
425 NMAWs *sec;
426 gboolean valid = FALSE;
427 const char *mode;
428
429 sw = nm_connection_get_setting_wireless (connection);
430
431 mode = nm_setting_wireless_get_mode (sw);
432 if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0)
433 CE_PAGE_SECURITY (self)->adhoc = TRUE;
434 else
435 CE_PAGE_SECURITY (self)->adhoc = FALSE;
436
437 sec = security_combo_get_active (CE_PAGE_SECURITY (self));
438 if (sec) {
439 GBytes *ssid = nm_setting_wireless_get_ssid (sw);
440
441 if (ssid) {
442 /* FIXME: get failed property and error out of wifi security objects */
443 valid = nma_ws_validate (sec, error);
444 if (valid)
445 nma_ws_fill_connection (sec, connection);
446 } else {
447 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING, "Missing SSID");
448 valid = FALSE;
449 }
450
451 if (self->adhoc) {
452 if (!nma_ws_adhoc_compatible (sec)) {
453 if (valid)
454 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, "Security not compatible with Ad-Hoc mode");
455 valid = FALSE;
456 }
457 }
458 g_object_unref (sec);
459 } else {
460
461 if (gtk_combo_box_get_active ((CE_PAGE_SECURITY (self))->security_combo) == 0) {
462 /* No security, unencrypted */
463 nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
464 nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
465 valid = TRUE;
466 } else {
467 /* owe case:
468 * fill the connection manually until libnma implements OWE wireless security
469 */
470 NMSetting *sws;
471
472 sws = nm_setting_wireless_security_new ();
473 g_object_set (sws, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "owe", NULL);
474 nm_connection_add_setting (connection, sws);
475 nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X);
476 valid = TRUE;
477 }
478
479 }
480
481 return valid;
482 }
483
484 static void
485 ce_page_security_init (CEPageSecurity *self)
486 {
487 gtk_widget_init_template (GTK_WIDGET (self));
488 }
489
490 static void
491 ce_page_security_class_init (CEPageSecurityClass *klass)
492 {
493 GObjectClass *object_class = G_OBJECT_CLASS (klass);
494 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
495
496 object_class->dispose = ce_page_security_dispose;
497
498 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/security-page.ui");
499
500 gtk_widget_class_bind_template_child (widget_class, CEPageSecurity, box);
501 gtk_widget_class_bind_template_child (widget_class, CEPageSecurity, security_label);
502 gtk_widget_class_bind_template_child (widget_class, CEPageSecurity, security_combo);
503 }
504
505 static void
506 ce_page_iface_init (CEPageInterface *iface)
507 {
508 iface->get_security_setting = ce_page_security_get_security_setting;
509 iface->get_title = ce_page_security_get_title;
510 iface->validate = ce_page_security_validate;
511 }
512
513 CEPageSecurity *
514 ce_page_security_new (NMConnection *connection)
515 {
516 CEPageSecurity *self;
517 NMUtilsSecurityType default_type = NMU_SEC_NONE;
518 NMSettingWirelessSecurity *sws;
519
520 self = CE_PAGE_SECURITY (g_object_new (ce_page_security_get_type (), NULL));
521
522 self->connection = g_object_ref (connection);
523
524 sws = nm_connection_get_setting_wireless_security (connection);
525 if (sws)
526 default_type = get_default_type_for_security (sws);
527
528 if (default_type == NMU_SEC_STATIC_WEP ||
529 default_type == NMU_SEC_LEAP ||
530 default_type == NMU_SEC_WPA_PSK ||
531 #if NM_CHECK_VERSION(1,20,6)
532 default_type == NMU_SEC_SAE ||
533 #endif
534 #if NM_CHECK_VERSION(1,24,0)
535 default_type == NMU_SEC_OWE ||
536 #endif
537 default_type == NMU_SEC_WPA2_PSK) {
538 self->security_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
539 }
540
541 if (default_type == NMU_SEC_DYNAMIC_WEP ||
542 default_type == NMU_SEC_WPA_ENTERPRISE ||
543 default_type == NMU_SEC_WPA2_ENTERPRISE) {
544 self->security_setting = NM_SETTING_802_1X_SETTING_NAME;
545 }
546
547 g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL);
548
549 return self;
550 }
551