WPS: Added callback for failure-after-M2/M2D
[mech_eap.git] / wpa_supplicant / wpa_gui-qt4 / networkconfig.cpp
index e4f1096..8d5d23b 100644 (file)
@@ -12,6 +12,7 @@
  * See README and COPYING for more details.
  */
 
+#include <cstdio>
 #include <QMessageBox>
 
 #include "networkconfig.h"
@@ -41,6 +42,9 @@ NetworkConfig::NetworkConfig(QWidget *parent, const char *, bool, Qt::WFlags)
        connect(encrSelect, SIGNAL(activated(const QString &)), this,
                SLOT(encrChanged(const QString &)));
        connect(removeButton, SIGNAL(clicked()), this, SLOT(removeNetwork()));
+       connect(eapSelect, SIGNAL(activated(int)), this,
+               SLOT(eapChanged(int)));
+       connect(useWpsButton, SIGNAL(clicked()), this, SLOT(useWps()));
 
        wpagui = NULL;
        new_network = false;
@@ -95,6 +99,10 @@ void NetworkConfig::paramsFromScanResults(QTreeWidgetItem *sel)
        wepEnabled(auth == AUTH_NONE && encr == 1);
 
        getEapCapa();
+
+       if (flags.indexOf("[WPS") >= 0)
+               useWpsButton->setEnabled(true);
+       bssid = sel->text(1);
 }
 
 
@@ -107,6 +115,9 @@ void NetworkConfig::authChanged(int sel)
        identityEdit->setEnabled(eap);
        passwordEdit->setEnabled(eap);
        cacertEdit->setEnabled(eap);
+       phase2Select->setEnabled(eap);
+       if (eap)
+               eapChanged(eapSelect->currentIndex());
 
        while (encrSelect->count())
                encrSelect->removeItem(0);
@@ -126,6 +137,48 @@ void NetworkConfig::authChanged(int sel)
 }
 
 
+void NetworkConfig::eapChanged(int sel)
+{
+       QString prev_val = phase2Select->currentText();
+       while (phase2Select->count())
+               phase2Select->removeItem(0);
+
+       QStringList inner;
+       inner << "PEAP" << "TTLS" << "FAST";
+       if (!inner.contains(eapSelect->itemText(sel)))
+               return;
+
+       phase2Select->addItem("[ any ]");
+
+       /* Add special cases based on outer method */
+       if (eapSelect->currentText().compare("TTLS") == 0) {
+               phase2Select->addItem("PAP");
+               phase2Select->addItem("CHAP");
+               phase2Select->addItem("MSCHAP");
+               phase2Select->addItem("MSCHAPv2");
+       } else if (eapSelect->currentText().compare("FAST") == 0)
+               phase2Select->addItem("GTC(auth) + MSCHAPv2(prov)");
+
+       /* Add all enabled EAP methods that can be used in the tunnel */
+       int i;
+       QStringList allowed;
+       allowed << "MSCHAPV2" << "MD5" << "GTC" << "TLS" << "OTP" << "SIM"
+               << "AKA";
+       for (i = 0; i < eapSelect->count(); i++) {
+               if (allowed.contains(eapSelect->itemText(i))) {
+                       phase2Select->addItem("EAP-" + eapSelect->itemText(i));
+               }
+       }
+
+       for (i = 0; i < phase2Select->count(); i++) {
+               if (phase2Select->itemText(i).compare(prev_val) == 0) {
+                       phase2Select->setCurrentIndex(i);
+                       break;
+               }
+       }
+}
+
+
 void NetworkConfig::addNetwork()
 {
        char reply[10], cmd[256];
@@ -225,29 +278,87 @@ void NetworkConfig::addNetwork()
                setNetworkParam(id, "group", "TKIP CCMP WEP104 WEP40", false);
        }
        if (pskEdit->isEnabled() &&
-           strcmp(passwordEdit->text().toAscii().constData(),
+           strcmp(pskEdit->text().toAscii().constData(),
                   WPA_GUI_KEY_DATA) != 0)
                setNetworkParam(id, "psk",
                                pskEdit->text().toAscii().constData(),
                                psklen != 64);
-       if (eapSelect->isEnabled())
-               setNetworkParam(id, "eap",
-                               eapSelect->currentText().toAscii().constData(),
-                               false);
-       if (identityEdit->isEnabled())
+       if (eapSelect->isEnabled()) {
+               const char *eap =
+                       eapSelect->currentText().toAscii().constData();
+               setNetworkParam(id, "eap", eap, false);
+               if (strcmp(eap, "SIM") == 0 || strcmp(eap, "AKA") == 0)
+                       setNetworkParam(id, "pcsc", "", true);
+               else
+                       setNetworkParam(id, "pcsc", "NULL", false);
+       }
+       if (phase2Select->isEnabled()) {
+               QString eap = eapSelect->currentText();
+               QString inner = phase2Select->currentText();
+               char phase2[32];
+               phase2[0] = '\0';
+               if (eap.compare("PEAP") == 0) {
+                       if (inner.startsWith("EAP-"))
+                               snprintf(phase2, sizeof(phase2), "auth=%s",
+                                        inner.right(inner.size() - 4).
+                                        toAscii().constData());
+               } else if (eap.compare("TTLS") == 0) {
+                       if (inner.startsWith("EAP-"))
+                               snprintf(phase2, sizeof(phase2), "autheap=%s",
+                                        inner.right(inner.size() - 4).
+                                        toAscii().constData());
+                       else
+                               snprintf(phase2, sizeof(phase2), "auth=%s",
+                                        inner.toAscii().constData());
+               } else if (eap.compare("FAST") == 0) {
+                       const char *provisioning = NULL;
+                       if (inner.startsWith("EAP-")) {
+                               snprintf(phase2, sizeof(phase2), "auth=%s",
+                                        inner.right(inner.size() - 4).
+                                        toAscii().constData());
+                               provisioning = "fast_provisioning=2";
+                       } else if (inner.compare("GTC(auth) + MSCHAPv2(prov)")
+                                  == 0) {
+                               snprintf(phase2, sizeof(phase2),
+                                        "auth=GTC auth=MSCHAPV2");
+                               provisioning = "fast_provisioning=1";
+                       } else
+                               provisioning = "fast_provisioning=3";
+                       if (provisioning) {
+                               char blob[32];
+                               setNetworkParam(id, "phase1", provisioning,
+                                               true);
+                               snprintf(blob, sizeof(blob),
+                                        "blob://fast-pac-%d", id);
+                               setNetworkParam(id, "pac_file", blob, true);
+                       }
+               }
+               if (phase2[0])
+                       setNetworkParam(id, "phase2", phase2, true);
+               else
+                       setNetworkParam(id, "phase2", "NULL", false);
+       } else
+               setNetworkParam(id, "phase2", "NULL", false);
+       if (identityEdit->isEnabled() && identityEdit->text().length() > 0)
                setNetworkParam(id, "identity",
                                identityEdit->text().toAscii().constData(),
                                true);
-       if (passwordEdit->isEnabled() &&
+       else
+               setNetworkParam(id, "identity", "NULL", false);
+       if (passwordEdit->isEnabled() && passwordEdit->text().length() > 0 &&
            strcmp(passwordEdit->text().toAscii().constData(),
                   WPA_GUI_KEY_DATA) != 0)
                setNetworkParam(id, "password",
                                passwordEdit->text().toAscii().constData(),
                                true);
-       if (cacertEdit->isEnabled())
+       else if (passwordEdit->text().length() == 0)
+               setNetworkParam(id, "password", "NULL", false);
+       if (cacertEdit->isEnabled() && cacertEdit->text().length() > 0)
                setNetworkParam(id, "ca_cert",
                                cacertEdit->text().toAscii().constData(),
                                true);
+       else
+               setNetworkParam(id, "ca_cert", "NULL", false);
        writeWepKey(id, wep0Edit, 0);
        writeWepKey(id, wep1Edit, 1);
        writeWepKey(id, wep2Edit, 2);
@@ -262,10 +373,12 @@ void NetworkConfig::addNetwork()
        else if (wep3Radio->isEnabled() && wep3Radio->isChecked())
                setNetworkParam(id, "wep_tx_keyidx", "3", false);
 
-       if (idstrEdit->isEnabled())
+       if (idstrEdit->isEnabled() && idstrEdit->text().length() > 0)
                setNetworkParam(id, "id_str",
                                idstrEdit->text().toAscii().constData(),
                                true);
+       else
+               setNetworkParam(id, "id_str", "NULL", false);
 
        if (prioritySpinBox->isEnabled()) {
                QString prio;
@@ -481,6 +594,7 @@ void NetworkConfig::paramsFromConfig(int network_id)
                cacertEdit->setText(reply + 1);
        }
 
+       enum { NO_INNER, PEAP_INNER, TTLS_INNER, FAST_INNER } eap = NO_INNER;
        snprintf(cmd, sizeof(cmd), "GET_NETWORK %d eap", network_id);
        reply_len = sizeof(reply) - 1;
        if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 &&
@@ -489,11 +603,71 @@ void NetworkConfig::paramsFromConfig(int network_id)
                for (i = 0; i < eapSelect->count(); i++) {
                        if (eapSelect->itemText(i).compare(reply) == 0) {
                                eapSelect->setCurrentIndex(i);
+                               if (strcmp(reply, "PEAP") == 0)
+                                       eap = PEAP_INNER;
+                               else if (strcmp(reply, "TTLS") == 0)
+                                       eap = TTLS_INNER;
+                               else if (strcmp(reply, "FAST") == 0)
+                                       eap = FAST_INNER;
                                break;
                        }
                }
        }
 
+       if (eap != NO_INNER) {
+               snprintf(cmd, sizeof(cmd), "GET_NETWORK %d phase2",
+                        network_id);
+               reply_len = sizeof(reply) - 1;
+               if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 &&
+                   reply_len >= 1) {
+                       reply[reply_len] = '\0';
+                       eapChanged(eapSelect->currentIndex());
+               } else
+                       eap = NO_INNER;
+       }
+
+       char *val;
+       val = reply + 1;
+       while (*(val + 1))
+               val++;
+       if (*val == '"')
+               *val = '\0';
+
+       switch (eap) {
+       case PEAP_INNER:
+               if (strncmp(reply, "\"auth=", 6))
+                       break;
+               val = reply + 2;
+               memcpy(val, "EAP-", 4);
+               break;
+       case TTLS_INNER:
+               if (strncmp(reply, "\"autheap=", 9) == 0) {
+                       val = reply + 5;
+                       memcpy(val, "EAP-", 4);
+               } else if (strncmp(reply, "\"auth=", 6) == 0)
+                       val = reply + 6;
+               break;
+       case FAST_INNER:
+               if (strncmp(reply, "\"auth=", 6))
+                       break;
+               if (strcmp(reply + 6, "GTC auth=MSCHAPV2") == 0) {
+                       val = "GTC(auth) + MSCHAPv2(prov)";
+                       break;
+               }
+               val = reply + 2;
+               memcpy(val, "EAP-", 4);
+               break;
+       case NO_INNER:
+               break;
+       }
+
+       for (i = 0; i < phase2Select->count(); i++) {
+               if (phase2Select->itemText(i).compare(val) == 0) {
+                       phase2Select->setCurrentIndex(i);
+                       break;
+               }
+       }
+
        for (i = 0; i < 4; i++) {
                QLineEdit *wepEdit;
                switch (i) {
@@ -637,3 +811,13 @@ void NetworkConfig::getEapCapa()
        QStringList types = res.split(QChar(' '));
        eapSelect->insertItems(-1, types);
 }
+
+
+void NetworkConfig::useWps()
+{
+       if (wpagui == NULL)
+               return;
+       wpagui->setBssFromScan(bssid);
+       wpagui->wpsDialog();
+       close();
+}