2 * wpa_gui - NetworkConfig class
3 * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include <QMessageBox>
17 #include "networkconfig.h"
29 #define WPA_GUI_KEY_DATA "[key is configured]"
32 NetworkConfig::NetworkConfig(QWidget
*parent
, const char *, bool, Qt::WFlags
)
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()));
50 NetworkConfig::~NetworkConfig()
55 void NetworkConfig::languageChange()
61 void NetworkConfig::paramsFromScanResults(QTreeWidgetItem
*sel
)
65 /* SSID BSSID frequency signal flags */
66 setWindowTitle(sel
->text(0));
67 ssidEdit
->setText(sel
->text(0));
69 QString flags
= sel
->text(4);
71 if (flags
.indexOf("[WPA2-EAP") >= 0)
73 else if (flags
.indexOf("[WPA-EAP") >= 0)
75 else if (flags
.indexOf("[WPA2-PSK") >= 0)
77 else if (flags
.indexOf("[WPA-PSK") >= 0)
82 if (flags
.indexOf("-CCMP") >= 0)
84 else if (flags
.indexOf("-TKIP") >= 0)
86 else if (flags
.indexOf("WEP") >= 0)
91 authSelect
->setCurrentIndex(auth
);
93 encrSelect
->setCurrentIndex(encr
);
95 wepEnabled(auth
== AUTH_NONE
&& encr
== 1);
101 void NetworkConfig::authChanged(int sel
)
103 pskEdit
->setEnabled(sel
== AUTH_WPA_PSK
|| sel
== AUTH_WPA2_PSK
);
104 bool eap
= sel
== AUTH_IEEE8021X
|| sel
== AUTH_WPA_EAP
||
105 sel
== AUTH_WPA2_EAP
;
106 eapSelect
->setEnabled(eap
);
107 identityEdit
->setEnabled(eap
);
108 passwordEdit
->setEnabled(eap
);
109 cacertEdit
->setEnabled(eap
);
111 while (encrSelect
->count())
112 encrSelect
->removeItem(0);
114 if (sel
== AUTH_NONE
|| sel
== AUTH_IEEE8021X
) {
115 encrSelect
->addItem("None");
116 encrSelect
->addItem("WEP");
117 encrSelect
->setCurrentIndex(sel
== AUTH_NONE
? 0 : 1);
119 encrSelect
->addItem("TKIP");
120 encrSelect
->addItem("CCMP");
121 encrSelect
->setCurrentIndex((sel
== AUTH_WPA2_PSK
||
122 sel
== AUTH_WPA2_EAP
) ? 1 : 0);
125 wepEnabled(sel
== AUTH_IEEE8021X
);
129 void NetworkConfig::addNetwork()
131 char reply
[10], cmd
[256];
134 int psklen
= pskEdit
->text().length();
135 int auth
= authSelect
->currentIndex();
137 if (auth
== AUTH_WPA_PSK
|| auth
== AUTH_WPA2_PSK
) {
138 if (psklen
< 8 || psklen
> 64) {
139 QMessageBox::warning(this, "WPA Pre-Shared Key Error",
140 "WPA-PSK requires a passphrase "
141 "of 8 to 63 characters\n"
142 "or 64 hex digit PSK");
148 if (idstrEdit
->isEnabled() && !idstrEdit
->text().isEmpty()) {
149 QRegExp
rx("^(\\w|-)+$");
150 if (rx
.indexIn(idstrEdit
->text()) < 0) {
151 QMessageBox::warning(this, "Network ID Error",
152 "Network ID String contains "
153 "non-word characters.\n"
154 "It must be a simple string, "
155 "without spaces, containing\n"
156 "only characters in this range: "
158 idstrEdit
->setFocus();
166 memset(reply
, 0, sizeof(reply
));
167 reply_len
= sizeof(reply
) - 1;
170 wpagui
->ctrlRequest("ADD_NETWORK", reply
, &reply_len
);
171 if (reply
[0] == 'F') {
172 QMessageBox::warning(this, "wpa_gui", "Failed to add "
173 "network to wpa_supplicant\n"
179 id
= edit_network_id
;
181 setNetworkParam(id
, "ssid", ssidEdit
->text().toAscii().constData(),
184 const char *key_mgmt
= NULL
, *proto
= NULL
, *pairwise
= NULL
;
190 key_mgmt
= "IEEE8021X";
193 key_mgmt
= "WPA-PSK";
197 key_mgmt
= "WPA-EAP";
201 key_mgmt
= "WPA-PSK";
205 key_mgmt
= "WPA-EAP";
210 if (auth
== AUTH_WPA_PSK
|| auth
== AUTH_WPA_EAP
||
211 auth
== AUTH_WPA2_PSK
|| auth
== AUTH_WPA2_EAP
) {
212 int encr
= encrSelect
->currentIndex();
220 setNetworkParam(id
, "proto", proto
, false);
222 setNetworkParam(id
, "key_mgmt", key_mgmt
, false);
224 setNetworkParam(id
, "pairwise", pairwise
, false);
225 setNetworkParam(id
, "group", "TKIP CCMP WEP104 WEP40", false);
227 if (pskEdit
->isEnabled() &&
228 strcmp(passwordEdit
->text().toAscii().constData(),
229 WPA_GUI_KEY_DATA
) != 0)
230 setNetworkParam(id
, "psk",
231 pskEdit
->text().toAscii().constData(),
233 if (eapSelect
->isEnabled())
234 setNetworkParam(id
, "eap",
235 eapSelect
->currentText().toAscii().constData(),
237 if (identityEdit
->isEnabled())
238 setNetworkParam(id
, "identity",
239 identityEdit
->text().toAscii().constData(),
241 if (passwordEdit
->isEnabled() &&
242 strcmp(passwordEdit
->text().toAscii().constData(),
243 WPA_GUI_KEY_DATA
) != 0)
244 setNetworkParam(id
, "password",
245 passwordEdit
->text().toAscii().constData(),
247 if (cacertEdit
->isEnabled())
248 setNetworkParam(id
, "ca_cert",
249 cacertEdit
->text().toAscii().constData(),
251 writeWepKey(id
, wep0Edit
, 0);
252 writeWepKey(id
, wep1Edit
, 1);
253 writeWepKey(id
, wep2Edit
, 2);
254 writeWepKey(id
, wep3Edit
, 3);
256 if (wep0Radio
->isEnabled() && wep0Radio
->isChecked())
257 setNetworkParam(id
, "wep_tx_keyidx", "0", false);
258 else if (wep1Radio
->isEnabled() && wep1Radio
->isChecked())
259 setNetworkParam(id
, "wep_tx_keyidx", "1", false);
260 else if (wep2Radio
->isEnabled() && wep2Radio
->isChecked())
261 setNetworkParam(id
, "wep_tx_keyidx", "2", false);
262 else if (wep3Radio
->isEnabled() && wep3Radio
->isChecked())
263 setNetworkParam(id
, "wep_tx_keyidx", "3", false);
265 if (idstrEdit
->isEnabled())
266 setNetworkParam(id
, "id_str",
267 idstrEdit
->text().toAscii().constData(),
270 if (prioritySpinBox
->isEnabled()) {
272 prio
= prio
.setNum(prioritySpinBox
->value());
273 setNetworkParam(id
, "priority", prio
.toAscii().constData(),
277 snprintf(cmd
, sizeof(cmd
), "ENABLE_NETWORK %d", id
);
278 reply_len
= sizeof(reply
);
279 wpagui
->ctrlRequest(cmd
, reply
, &reply_len
);
280 if (strncmp(reply
, "OK", 2) != 0) {
281 QMessageBox::warning(this, "wpa_gui", "Failed to enable "
282 "network in wpa_supplicant\n"
284 /* Network was added, so continue anyway */
286 wpagui
->triggerUpdate();
287 wpagui
->ctrlRequest("SAVE_CONFIG", reply
, &reply_len
);
293 void NetworkConfig::setWpaGui(WpaGui
*_wpagui
)
299 int NetworkConfig::setNetworkParam(int id
, const char *field
,
300 const char *value
, bool quote
)
302 char reply
[10], cmd
[256];
304 snprintf(cmd
, sizeof(cmd
), "SET_NETWORK %d %s %s%s%s",
305 id
, field
, quote
? "\"" : "", value
, quote
? "\"" : "");
306 reply_len
= sizeof(reply
);
307 wpagui
->ctrlRequest(cmd
, reply
, &reply_len
);
308 return strncmp(reply
, "OK", 2) == 0 ? 0 : -1;
312 void NetworkConfig::encrChanged(const QString
&sel
)
314 wepEnabled(sel
.indexOf("WEP") == 0);
318 void NetworkConfig::wepEnabled(bool enabled
)
320 wep0Edit
->setEnabled(enabled
);
321 wep1Edit
->setEnabled(enabled
);
322 wep2Edit
->setEnabled(enabled
);
323 wep3Edit
->setEnabled(enabled
);
324 wep0Radio
->setEnabled(enabled
);
325 wep1Radio
->setEnabled(enabled
);
326 wep2Radio
->setEnabled(enabled
);
327 wep3Radio
->setEnabled(enabled
);
331 void NetworkConfig::writeWepKey(int network_id
, QLineEdit
*edit
, int id
)
335 const char *txt
, *pos
;
338 if (!edit
->isEnabled() || edit
->text().isEmpty())
342 * Assume hex key if only hex characters are present and length matches
343 * with 40, 104, or 128-bit key
345 txt
= edit
->text().toAscii().constData();
346 if (strcmp(txt
, WPA_GUI_KEY_DATA
) == 0)
354 if (!((*pos
>= '0' && *pos
<= '9') ||
355 (*pos
>= 'a' && *pos
<= 'f') ||
356 (*pos
>= 'A' && *pos
<= 'F'))) {
362 if (hex
&& len
!= 10 && len
!= 26 && len
!= 32)
364 snprintf(buf
, sizeof(buf
), "wep_key%d", id
);
365 setNetworkParam(network_id
, buf
, txt
, !hex
);
369 static int key_value_isset(const char *reply
, size_t reply_len
)
371 return reply_len
> 0 && (reply_len
< 4 || memcmp(reply
, "FAIL", 4) != 0);
375 void NetworkConfig::paramsFromConfig(int network_id
)
379 edit_network_id
= network_id
;
382 char reply
[1024], cmd
[256], *pos
;
385 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d ssid", network_id
);
386 reply_len
= sizeof(reply
) - 1;
387 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0 &&
388 reply_len
>= 2 && reply
[0] == '"') {
389 reply
[reply_len
] = '\0';
390 pos
= strchr(reply
+ 1, '"');
393 ssidEdit
->setText(reply
+ 1);
396 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d proto", network_id
);
397 reply_len
= sizeof(reply
) - 1;
399 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0) {
400 reply
[reply_len
] = '\0';
401 if (strstr(reply
, "RSN") || strstr(reply
, "WPA2"))
403 else if (strstr(reply
, "WPA"))
407 int auth
= AUTH_NONE
, encr
= 0;
408 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d key_mgmt", network_id
);
409 reply_len
= sizeof(reply
) - 1;
410 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0) {
411 reply
[reply_len
] = '\0';
412 if (strstr(reply
, "WPA-EAP"))
413 auth
= wpa
& 2 ? AUTH_WPA2_EAP
: AUTH_WPA_EAP
;
414 else if (strstr(reply
, "WPA-PSK"))
415 auth
= wpa
& 2 ? AUTH_WPA2_PSK
: AUTH_WPA_PSK
;
416 else if (strstr(reply
, "IEEE8021X")) {
417 auth
= AUTH_IEEE8021X
;
422 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d pairwise", network_id
);
423 reply_len
= sizeof(reply
) - 1;
424 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0) {
425 reply
[reply_len
] = '\0';
426 if (strstr(reply
, "CCMP") && auth
!= AUTH_NONE
)
428 else if (strstr(reply
, "TKIP"))
430 else if (strstr(reply
, "WEP"))
436 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d psk", network_id
);
437 reply_len
= sizeof(reply
) - 1;
438 res
= wpagui
->ctrlRequest(cmd
, reply
, &reply_len
);
439 if (res
>= 0 && reply_len
>= 2 && reply
[0] == '"') {
440 reply
[reply_len
] = '\0';
441 pos
= strchr(reply
+ 1, '"');
444 pskEdit
->setText(reply
+ 1);
445 } else if (res
>= 0 && key_value_isset(reply
, reply_len
)) {
446 pskEdit
->setText(WPA_GUI_KEY_DATA
);
449 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d identity", network_id
);
450 reply_len
= sizeof(reply
) - 1;
451 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0 &&
452 reply_len
>= 2 && reply
[0] == '"') {
453 reply
[reply_len
] = '\0';
454 pos
= strchr(reply
+ 1, '"');
457 identityEdit
->setText(reply
+ 1);
460 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d password", network_id
);
461 reply_len
= sizeof(reply
) - 1;
462 res
= wpagui
->ctrlRequest(cmd
, reply
, &reply_len
);
463 if (res
>= 0 && reply_len
>= 2 && reply
[0] == '"') {
464 reply
[reply_len
] = '\0';
465 pos
= strchr(reply
+ 1, '"');
468 passwordEdit
->setText(reply
+ 1);
469 } else if (res
>= 0 && key_value_isset(reply
, reply_len
)) {
470 passwordEdit
->setText(WPA_GUI_KEY_DATA
);
473 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d ca_cert", network_id
);
474 reply_len
= sizeof(reply
) - 1;
475 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0 &&
476 reply_len
>= 2 && reply
[0] == '"') {
477 reply
[reply_len
] = '\0';
478 pos
= strchr(reply
+ 1, '"');
481 cacertEdit
->setText(reply
+ 1);
484 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d eap", network_id
);
485 reply_len
= sizeof(reply
) - 1;
486 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0 &&
488 reply
[reply_len
] = '\0';
489 for (i
= 0; i
< eapSelect
->count(); i
++) {
490 if (eapSelect
->itemText(i
).compare(reply
) == 0) {
491 eapSelect
->setCurrentIndex(i
);
497 for (i
= 0; i
< 4; i
++) {
514 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d wep_key%d",
516 reply_len
= sizeof(reply
) - 1;
517 res
= wpagui
->ctrlRequest(cmd
, reply
, &reply_len
);
518 if (res
>= 0 && reply_len
>= 2 && reply
[0] == '"') {
519 reply
[reply_len
] = '\0';
520 pos
= strchr(reply
+ 1, '"');
523 if (auth
== AUTH_NONE
|| auth
== AUTH_IEEE8021X
)
526 wepEdit
->setText(reply
+ 1);
527 } else if (res
>= 0 && key_value_isset(reply
, reply_len
)) {
528 if (auth
== AUTH_NONE
|| auth
== AUTH_IEEE8021X
)
530 wepEdit
->setText(WPA_GUI_KEY_DATA
);
534 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d wep_tx_keyidx", network_id
);
535 reply_len
= sizeof(reply
) - 1;
536 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0 && reply_len
>= 1)
538 reply
[reply_len
] = '\0';
539 switch (atoi(reply
)) {
541 wep0Radio
->setChecked(true);
544 wep1Radio
->setChecked(true);
547 wep2Radio
->setChecked(true);
550 wep3Radio
->setChecked(true);
555 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d id_str", network_id
);
556 reply_len
= sizeof(reply
) - 1;
557 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0 &&
558 reply_len
>= 2 && reply
[0] == '"') {
559 reply
[reply_len
] = '\0';
560 pos
= strchr(reply
+ 1, '"');
563 idstrEdit
->setText(reply
+ 1);
566 snprintf(cmd
, sizeof(cmd
), "GET_NETWORK %d priority", network_id
);
567 reply_len
= sizeof(reply
) - 1;
568 if (wpagui
->ctrlRequest(cmd
, reply
, &reply_len
) >= 0 && reply_len
>= 1)
570 reply
[reply_len
] = '\0';
571 prioritySpinBox
->setValue(atoi(reply
));
574 authSelect
->setCurrentIndex(auth
);
576 encrSelect
->setCurrentIndex(encr
);
577 if (auth
== AUTH_NONE
|| auth
== AUTH_IEEE8021X
)
578 wepEnabled(encr
== 1);
580 removeButton
->setEnabled(true);
581 addButton
->setText("Save");
585 void NetworkConfig::removeNetwork()
587 char reply
[10], cmd
[256];
590 if (QMessageBox::information(this, "wpa_gui",
591 "This will permanently remove the "
593 "from the configuration. Do you really "
595 "to remove this network?", "Yes", "No")
599 snprintf(cmd
, sizeof(cmd
), "REMOVE_NETWORK %d", edit_network_id
);
600 reply_len
= sizeof(reply
);
601 wpagui
->ctrlRequest(cmd
, reply
, &reply_len
);
602 if (strncmp(reply
, "OK", 2) != 0) {
603 QMessageBox::warning(this, "wpa_gui",
604 "Failed to remove network from "
608 wpagui
->triggerUpdate();
609 wpagui
->ctrlRequest("SAVE_CONFIG", reply
, &reply_len
);
616 void NetworkConfig::newNetwork()
623 void NetworkConfig::getEapCapa()
631 reply_len
= sizeof(reply
) - 1;
632 if (wpagui
->ctrlRequest("GET_CAPABILITY eap", reply
, &reply_len
) < 0)
634 reply
[reply_len
] = '\0';
637 QStringList types
= res
.split(QChar(' '));
638 eapSelect
->insertItems(-1, types
);