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