]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / wpa_supplicant / wpa_gui-qt4 / networkconfig.cpp
1 /*
2  * wpa_gui - NetworkConfig class
3  * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include <QMessageBox>
16
17 #include "networkconfig.h"
18 #include "wpagui.h"
19
20 enum {
21     AUTH_NONE = 0,
22     AUTH_IEEE8021X = 1,
23     AUTH_WPA_PSK = 2,
24     AUTH_WPA_EAP = 3,
25     AUTH_WPA2_PSK = 4,
26     AUTH_WPA2_EAP = 5
27 };
28
29 #define WPA_GUI_KEY_DATA "[key is configured]"
30
31
32 NetworkConfig::NetworkConfig(QWidget *parent, const char *, bool, Qt::WFlags)
33         : QDialog(parent)
34 {
35         setupUi(this);
36
37         connect(authSelect, SIGNAL(activated(int)), this,
38                 SLOT(authChanged(int)));
39         connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
40         connect(addButton, SIGNAL(clicked()), this, SLOT(addNetwork()));
41         connect(encrSelect, SIGNAL(activated(const QString &)), this,
42                 SLOT(encrChanged(const QString &)));
43         connect(removeButton, SIGNAL(clicked()), this, SLOT(removeNetwork()));
44
45         wpagui = NULL;
46         new_network = false;
47 }
48
49
50 NetworkConfig::~NetworkConfig()
51 {
52 }
53
54
55 void NetworkConfig::languageChange()
56 {
57         retranslateUi(this);
58 }
59
60
61 void NetworkConfig::paramsFromScanResults(Q3ListViewItem *sel)
62 {
63         new_network = true;
64
65         /* SSID BSSID frequency signal flags */
66         setCaption(sel->text(0));
67         ssidEdit->setText(sel->text(0));
68
69         QString flags = sel->text(4);
70         int auth, encr = 0;
71         if (flags.find("[WPA2-EAP") >= 0)
72                 auth = AUTH_WPA2_EAP;
73         else if (flags.find("[WPA-EAP") >= 0)
74                 auth = AUTH_WPA_EAP;
75         else if (flags.find("[WPA2-PSK") >= 0)
76                 auth = AUTH_WPA2_PSK;
77         else if (flags.find("[WPA-PSK") >= 0)
78                 auth = AUTH_WPA_PSK;
79         else
80                 auth = AUTH_NONE;
81
82         if (flags.find("-CCMP") >= 0)
83                 encr = 1;
84         else if (flags.find("-TKIP") >= 0)
85                 encr = 0;
86         else if (flags.find("WEP") >= 0)
87                 encr = 1;
88         else
89                 encr = 0;
90
91         authSelect->setCurrentItem(auth);
92         authChanged(auth);
93         encrSelect->setCurrentItem(encr);
94
95         getEapCapa();
96 }
97
98
99 void NetworkConfig::authChanged(int sel)
100 {
101         pskEdit->setEnabled(sel == AUTH_WPA_PSK || sel == AUTH_WPA2_PSK);
102         bool eap = sel == AUTH_IEEE8021X || sel == AUTH_WPA_EAP ||
103                 sel == AUTH_WPA2_EAP;
104         eapSelect->setEnabled(eap);
105         identityEdit->setEnabled(eap);
106         passwordEdit->setEnabled(eap);
107         cacertEdit->setEnabled(eap);
108
109         while (encrSelect->count())
110                 encrSelect->removeItem(0);
111
112         if (sel == AUTH_NONE || sel == AUTH_IEEE8021X) {
113                 encrSelect->insertItem("None");
114                 encrSelect->insertItem("WEP");
115                 encrSelect->setCurrentItem(sel == AUTH_NONE ? 0 : 1);
116         } else {
117                 encrSelect->insertItem("TKIP");
118                 encrSelect->insertItem("CCMP");
119                 encrSelect->setCurrentItem((sel == AUTH_WPA2_PSK ||
120                                             sel == AUTH_WPA2_EAP) ? 1 : 0);
121         }
122
123         wepEnabled(sel == AUTH_IEEE8021X);
124 }
125
126
127 void NetworkConfig::addNetwork()
128 {
129         char reply[10], cmd[256];
130         size_t reply_len;
131         int id;
132         int psklen = pskEdit->text().length();
133         int auth = authSelect->currentItem();
134
135         if (auth == AUTH_WPA_PSK || auth == AUTH_WPA2_PSK) {
136                 if (psklen < 8 || psklen > 64) {
137                         QMessageBox::warning(this, "wpa_gui",
138                                              "WPA-PSK requires a passphrase "
139                                              "of 8 to 63 characters\n"
140                                              "or 64 hex digit PSK");
141                         return;
142                 }
143         }
144
145         if (wpagui == NULL)
146                 return;
147
148         memset(reply, 0, sizeof(reply));
149         reply_len = sizeof(reply) - 1;
150
151         if (new_network) {
152                 wpagui->ctrlRequest("ADD_NETWORK", reply, &reply_len);
153                 if (reply[0] == 'F') {
154                         QMessageBox::warning(this, "wpa_gui", "Failed to add "
155                                              "network to wpa_supplicant\n"
156                                              "configuration.");
157                         return;
158                 }
159                 id = atoi(reply);
160         } else
161                 id = edit_network_id;
162
163         setNetworkParam(id, "ssid", ssidEdit->text().ascii(), true);
164
165         const char *key_mgmt = NULL, *proto = NULL, *pairwise = NULL;
166         switch (auth) {
167         case AUTH_NONE:
168                 key_mgmt = "NONE";
169                 break;
170         case AUTH_IEEE8021X:
171                 key_mgmt = "IEEE8021X";
172                 break;
173         case AUTH_WPA_PSK:
174                 key_mgmt = "WPA-PSK";
175                 proto = "WPA";
176                 break;
177         case AUTH_WPA_EAP:
178                 key_mgmt = "WPA-EAP";
179                 proto = "WPA";
180                 break;
181         case AUTH_WPA2_PSK:
182                 key_mgmt = "WPA-PSK";
183                 proto = "WPA2";
184                 break;
185         case AUTH_WPA2_EAP:
186                 key_mgmt = "WPA-EAP";
187                 proto = "WPA2";
188                 break;
189         }
190
191         if (auth == AUTH_WPA_PSK || auth == AUTH_WPA_EAP ||
192             auth == AUTH_WPA2_PSK || auth == AUTH_WPA2_EAP) {
193                 int encr = encrSelect->currentItem();
194                 if (encr == 0)
195                         pairwise = "TKIP";
196                 else
197                         pairwise = "CCMP";
198         }
199
200         if (proto)
201                 setNetworkParam(id, "proto", proto, false);
202         if (key_mgmt)
203                 setNetworkParam(id, "key_mgmt", key_mgmt, false);
204         if (pairwise) {
205                 setNetworkParam(id, "pairwise", pairwise, false);
206                 setNetworkParam(id, "group", "TKIP CCMP WEP104 WEP40", false);
207         }
208         if (pskEdit->isEnabled() &&
209             strcmp(passwordEdit->text().ascii(), WPA_GUI_KEY_DATA) != 0)
210                 setNetworkParam(id, "psk", pskEdit->text().ascii(),
211                                 psklen != 64);
212         if (eapSelect->isEnabled())
213                 setNetworkParam(id, "eap", eapSelect->currentText().ascii(),
214                                 false);
215         if (identityEdit->isEnabled())
216                 setNetworkParam(id, "identity", identityEdit->text().ascii(),
217                                 true);
218         if (passwordEdit->isEnabled() &&
219             strcmp(passwordEdit->text().ascii(), WPA_GUI_KEY_DATA) != 0)
220                 setNetworkParam(id, "password", passwordEdit->text().ascii(),
221                                 true);
222         if (cacertEdit->isEnabled())
223                 setNetworkParam(id, "ca_cert", cacertEdit->text().ascii(),
224                                 true);
225         writeWepKey(id, wep0Edit, 0);
226         writeWepKey(id, wep1Edit, 1);
227         writeWepKey(id, wep2Edit, 2);
228         writeWepKey(id, wep3Edit, 3);
229
230         if (wep0Radio->isEnabled() && wep0Radio->isChecked())
231                 setNetworkParam(id, "wep_tx_keyidx", "0", false);
232         else if (wep1Radio->isEnabled() && wep1Radio->isChecked())
233                 setNetworkParam(id, "wep_tx_keyidx", "1", false);
234         else if (wep2Radio->isEnabled() && wep2Radio->isChecked())
235                 setNetworkParam(id, "wep_tx_keyidx", "2", false);
236         else if (wep3Radio->isEnabled() && wep3Radio->isChecked())
237                 setNetworkParam(id, "wep_tx_keyidx", "3", false);
238
239         snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %d", id);
240         reply_len = sizeof(reply);
241         wpagui->ctrlRequest(cmd, reply, &reply_len);
242         if (strncmp(reply, "OK", 2) != 0) {
243                 QMessageBox::warning(this, "wpa_gui", "Failed to enable "
244                                      "network in wpa_supplicant\n"
245                                      "configuration.");
246                 /* Network was added, so continue anyway */
247         }
248         wpagui->triggerUpdate();
249         wpagui->ctrlRequest("SAVE_CONFIG", reply, &reply_len);
250
251         close();
252 }
253
254
255 void NetworkConfig::setWpaGui(WpaGui *_wpagui)
256 {
257         wpagui = _wpagui;
258 }
259
260
261 int NetworkConfig::setNetworkParam(int id, const char *field,
262                                    const char *value, bool quote)
263 {
264         char reply[10], cmd[256];
265         size_t reply_len;
266         snprintf(cmd, sizeof(cmd), "SET_NETWORK %d %s %s%s%s",
267                  id, field, quote ? "\"" : "", value, quote ? "\"" : "");
268         reply_len = sizeof(reply);
269         wpagui->ctrlRequest(cmd, reply, &reply_len);
270         return strncmp(reply, "OK", 2) == 0 ? 0 : -1;
271 }
272
273
274 void NetworkConfig::encrChanged(const QString &sel)
275 {
276         wepEnabled(sel.find("WEP") == 0);
277 }
278
279
280 void NetworkConfig::wepEnabled(bool enabled)
281 {
282         wep0Edit->setEnabled(enabled);
283         wep1Edit->setEnabled(enabled);
284         wep2Edit->setEnabled(enabled);
285         wep3Edit->setEnabled(enabled);
286         wep0Radio->setEnabled(enabled);
287         wep1Radio->setEnabled(enabled);
288         wep2Radio->setEnabled(enabled);
289         wep3Radio->setEnabled(enabled);
290 }
291
292
293 void NetworkConfig::writeWepKey(int network_id, QLineEdit *edit, int id)
294 {
295         char buf[10];
296         bool hex;
297         const char *txt, *pos;
298         size_t len;
299
300         if (!edit->isEnabled() || edit->text().isEmpty())
301                 return;
302
303         /*
304          * Assume hex key if only hex characters are present and length matches
305          * with 40, 104, or 128-bit key
306          */
307         txt = edit->text().ascii();
308         if (strcmp(txt, WPA_GUI_KEY_DATA) == 0)
309                 return;
310         len = strlen(txt);
311         if (len == 0)
312                 return;
313         pos = txt;
314         hex = true;
315         while (*pos) {
316                 if (!((*pos >= '0' && *pos <= '9') ||
317                       (*pos >= 'a' && *pos <= 'f') ||
318                       (*pos >= 'A' && *pos <= 'F'))) {
319                         hex = false;
320                         break;
321                 }
322                 pos++;
323         }
324         if (hex && len != 10 && len != 26 && len != 32)
325                 hex = false;
326         snprintf(buf, sizeof(buf), "wep_key%d", id);
327         setNetworkParam(network_id, buf, txt, !hex);
328 }
329
330
331 static int key_value_isset(const char *reply, size_t reply_len)
332 {
333     return reply_len > 0 && (reply_len < 4 || memcmp(reply, "FAIL", 4) != 0);
334 }
335
336
337 void NetworkConfig::paramsFromConfig(int network_id)
338 {
339         int i, res;
340
341         edit_network_id = network_id;
342         getEapCapa();
343
344         char reply[1024], cmd[256], *pos;
345         size_t reply_len;
346
347         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d ssid", network_id);
348         reply_len = sizeof(reply) - 1;
349         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 &&
350             reply_len >= 2 && reply[0] == '"') {
351                 reply[reply_len] = '\0';
352                 pos = strchr(reply + 1, '"');
353                 if (pos)
354                         *pos = '\0';
355                 ssidEdit->setText(reply + 1);
356         }
357
358         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d proto", network_id);
359         reply_len = sizeof(reply) - 1;
360         int wpa = 0;
361         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) {
362                 reply[reply_len] = '\0';
363                 if (strstr(reply, "RSN") || strstr(reply, "WPA2"))
364                         wpa = 2;
365                 else if (strstr(reply, "WPA"))
366                         wpa = 1;
367         }
368
369         int auth = AUTH_NONE, encr = 0;
370         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d key_mgmt", network_id);
371         reply_len = sizeof(reply) - 1;
372         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) {
373                 reply[reply_len] = '\0';
374                 if (strstr(reply, "WPA-EAP"))
375                         auth = wpa & 2 ? AUTH_WPA2_EAP : AUTH_WPA_EAP;
376                 else if (strstr(reply, "WPA-PSK"))
377                         auth = wpa & 2 ? AUTH_WPA2_PSK : AUTH_WPA_PSK;
378                 else if (strstr(reply, "IEEE8021X")) {
379                         auth = AUTH_IEEE8021X;
380                         encr = 1;
381                 }
382         }
383
384         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d pairwise", network_id);
385         reply_len = sizeof(reply) - 1;
386         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) {
387                 reply[reply_len] = '\0';
388                 if (strstr(reply, "CCMP"))
389                         encr = 1;
390                 else if (strstr(reply, "TKIP"))
391                         encr = 0;
392                 else if (strstr(reply, "WEP"))
393                         encr = 1;
394                 else
395                         encr = 0;
396         }
397
398         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d psk", network_id);
399         reply_len = sizeof(reply) - 1;
400         res = wpagui->ctrlRequest(cmd, reply, &reply_len);
401         if (res >= 0 && reply_len >= 2 && reply[0] == '"') {
402                 reply[reply_len] = '\0';
403                 pos = strchr(reply + 1, '"');
404                 if (pos)
405                         *pos = '\0';
406                 pskEdit->setText(reply + 1);
407         } else if (res >= 0 && key_value_isset(reply, reply_len)) {
408                 pskEdit->setText(WPA_GUI_KEY_DATA);
409         }
410
411         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d identity", network_id);
412         reply_len = sizeof(reply) - 1;
413         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 &&
414             reply_len >= 2 && reply[0] == '"') {
415                 reply[reply_len] = '\0';
416                 pos = strchr(reply + 1, '"');
417                 if (pos)
418                         *pos = '\0';
419                 identityEdit->setText(reply + 1);
420         }
421
422         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d password", network_id);
423         reply_len = sizeof(reply) - 1;
424         res = wpagui->ctrlRequest(cmd, reply, &reply_len);
425         if (res >= 0 && reply_len >= 2 && reply[0] == '"') {
426                 reply[reply_len] = '\0';
427                 pos = strchr(reply + 1, '"');
428                 if (pos)
429                         *pos = '\0';
430                 passwordEdit->setText(reply + 1);
431         } else if (res >= 0 && key_value_isset(reply, reply_len)) {
432                 passwordEdit->setText(WPA_GUI_KEY_DATA);
433         }
434
435         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d ca_cert", network_id);
436         reply_len = sizeof(reply) - 1;
437         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 &&
438             reply_len >= 2 && reply[0] == '"') {
439                 reply[reply_len] = '\0';
440                 pos = strchr(reply + 1, '"');
441                 if (pos)
442                         *pos = '\0';
443                 cacertEdit->setText(reply + 1);
444         }
445
446         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d eap", network_id);
447         reply_len = sizeof(reply) - 1;
448         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 &&
449             reply_len >= 1) {
450                 reply[reply_len] = '\0';
451                 for (i = 0; i < eapSelect->count(); i++) {
452                         if (eapSelect->text(i).compare(reply) == 0) {
453                                 eapSelect->setCurrentItem(i);
454                                 break;
455                         }
456                 }
457         }
458
459         for (i = 0; i < 4; i++) {
460                 QLineEdit *wepEdit;
461                 switch (i) {
462                 default:
463                 case 0:
464                         wepEdit = wep0Edit;
465                         break;
466                 case 1:
467                         wepEdit = wep1Edit;
468                         break;
469                 case 2:
470                         wepEdit = wep2Edit;
471                         break;
472                 case 3:
473                         wepEdit = wep3Edit;
474                         break;
475                 }
476                 snprintf(cmd, sizeof(cmd), "GET_NETWORK %d wep_key%d",
477                          network_id, i);
478                 reply_len = sizeof(reply) - 1;
479                 res = wpagui->ctrlRequest(cmd, reply, &reply_len);
480                 if (res >= 0 && reply_len >= 2 && reply[0] == '"') {
481                         reply[reply_len] = '\0';
482                         pos = strchr(reply + 1, '"');
483                         if (pos)
484                                 *pos = '\0';
485                         if (auth == AUTH_NONE || auth == AUTH_IEEE8021X)
486                                 encr = 1;
487
488                         wepEdit->setText(reply + 1);
489                 } else if (res >= 0 && key_value_isset(reply, reply_len)) {
490                         if (auth == AUTH_NONE || auth == AUTH_IEEE8021X)
491                                 encr = 1;
492                         wepEdit->setText(WPA_GUI_KEY_DATA);
493                 }
494         }
495
496         snprintf(cmd, sizeof(cmd), "GET_NETWORK %d wep_tx_keyidx", network_id);
497         reply_len = sizeof(reply) - 1;
498         if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && reply_len >= 1)
499         {
500                 reply[reply_len] = '\0';
501                 switch (atoi(reply)) {
502                 case 0:
503                         wep0Radio->setChecked(true);
504                         break;
505                 case 1:
506                         wep1Radio->setChecked(true);
507                         break;
508                 case 2:
509                         wep2Radio->setChecked(true);
510                         break;
511                 case 3:
512                         wep3Radio->setChecked(true);
513                         break;
514                 }
515         }
516
517         authSelect->setCurrentItem(auth);
518         authChanged(auth);
519         encrSelect->setCurrentItem(encr);
520         if (auth == AUTH_NONE || auth == AUTH_IEEE8021X)
521                 wepEnabled(encr == 1);
522
523         removeButton->setEnabled(true);
524         addButton->setText("Save");
525 }
526
527
528 void NetworkConfig::removeNetwork()
529 {
530         char reply[10], cmd[256];
531         size_t reply_len;
532
533         if (QMessageBox::information(this, "wpa_gui",
534                                      "This will permanently remove the "
535                                      "network\n"
536                                      "from the configuration. Do you really "
537                                      "want\n"
538                                      "to remove this network?", "Yes", "No")
539             != 0)
540                 return;
541
542         snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %d", edit_network_id);
543         reply_len = sizeof(reply);
544         wpagui->ctrlRequest(cmd, reply, &reply_len);
545         if (strncmp(reply, "OK", 2) != 0) {
546                 QMessageBox::warning(this, "wpa_gui",
547                                      "Failed to remove network from "
548                                      "wpa_supplicant\n"
549                                      "configuration.");
550         } else {
551                 wpagui->triggerUpdate();
552                 wpagui->ctrlRequest("SAVE_CONFIG", reply, &reply_len);
553         }
554
555         close();
556 }
557
558
559 void NetworkConfig::newNetwork()
560 {
561         new_network = true;
562         getEapCapa();
563 }
564
565
566 void NetworkConfig::getEapCapa()
567 {
568         char reply[256];
569         size_t reply_len;
570
571         if (wpagui == NULL)
572                 return;
573
574         reply_len = sizeof(reply) - 1;
575         if (wpagui->ctrlRequest("GET_CAPABILITY eap", reply, &reply_len) < 0)
576                 return;
577         reply[reply_len] = '\0';
578
579         QString res(reply);
580         QStringList types = QStringList::split(QChar(' '), res);
581         eapSelect->insertStringList(types);
582 }