eapol_test: Add a new operation mode for control interface use
authorJouni Malinen <j@w1.fi>
Thu, 20 Aug 2015 21:21:20 +0000 (00:21 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 20 Aug 2015 21:48:29 +0000 (00:48 +0300)
The -T<ctrl_iface> command line argument can now be used to start
eapol_test in mode where the configuration file is not needed and the
authentication operations are started through the control interface.
Network profile is also managed through the control interface in this
case. This can be used to provide more control for scripted RADIUS
authentication server testing.

Signed-off-by: Jouni Malinen <j@w1.fi>
wpa_supplicant/eapol_test.c

index efb069d..dce7d1f 100644 (file)
@@ -76,6 +76,9 @@ struct eapol_test_data {
 
        const char *pcsc_reader;
        const char *pcsc_pin;
+
+       unsigned int ctrl_iface:1;
+       unsigned int id_req_sent:1;
 };
 
 static struct eapol_test_data eapol_test;
@@ -329,7 +332,11 @@ eapol_test_get_config_blob(void *ctx, const char *name)
 
 static void eapol_test_eapol_done_cb(void *ctx)
 {
+       struct eapol_test_data *e = ctx;
+
        printf("WPA: EAPOL processing complete\n");
+       wpa_supplicant_cancel_auth_timeout(e->wpa_s);
+       wpa_supplicant_set_state(e->wpa_s, WPA_COMPLETED);
 }
 
 
@@ -407,6 +414,9 @@ static void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
 {
        struct eapol_test_data *e = ctx;
        printf("eapol_sm_cb: result=%d\n", result);
+       e->id_req_sent = 0;
+       if (e->ctrl_iface)
+               return;
        e->eapol_test_num_reauths--;
        if (e->eapol_test_num_reauths < 0)
                eloop_terminate();
@@ -552,11 +562,21 @@ static void eapol_test_set_anon_id(void *ctx, const u8 *id, size_t len)
 }
 
 
+static enum wpa_states eapol_test_get_state(void *ctx)
+{
+       struct eapol_test_data *e = ctx;
+       struct wpa_supplicant *wpa_s = e->wpa_s;
+
+       return wpa_s->wpa_state;
+}
+
+
 static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
                      struct wpa_ssid *ssid)
 {
        struct eapol_config eapol_conf;
        struct eapol_ctx *ctx;
+       struct wpa_sm_ctx *wctx;
 
        ctx = os_zalloc(sizeof(*ctx));
        if (ctx == NULL) {
@@ -590,6 +610,25 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
                return -1;
        }
 
+       wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
+       wctx = os_zalloc(sizeof(*wctx));
+       if (wctx == NULL) {
+               os_free(ctx);
+               return -1;
+       }
+       wctx->ctx = e;
+       wctx->msg_ctx = wpa_s;
+       wctx->get_state = eapol_test_get_state;
+       wpa_s->wpa = wpa_sm_init(wctx);
+       if (!wpa_s->wpa) {
+               os_free(ctx);
+               os_free(wctx);
+               return -1;
+       }
+
+       if (!ssid)
+               return 0;
+
        wpa_s->current_ssid = ssid;
        os_memset(&eapol_conf, 0, sizeof(eapol_conf));
        eapol_conf.accept_802_1x_keys = 1;
@@ -614,6 +653,8 @@ static void test_eapol_clean(struct eapol_test_data *e,
 {
        struct extra_radius_attr *p, *prev;
 
+       wpa_sm_deinit(wpa_s->wpa);
+       wpa_s->wpa = NULL;
        radius_client_deinit(e->radius);
        wpabuf_free(e->last_eap_radius);
        radius_msg_free(e->last_recv_radius);
@@ -757,6 +798,8 @@ static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
                break;
        case EAP_CODE_FAILURE:
                os_strlcpy(buf, "EAP Failure", sizeof(buf));
+               if (e->ctrl_iface)
+                       break;
                eloop_terminate();
                break;
        default:
@@ -901,13 +944,52 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
        if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
             e->eapol_test_num_reauths < 0) ||
            hdr->code == RADIUS_CODE_ACCESS_REJECT) {
-               eloop_terminate();
+               if (!e->ctrl_iface)
+                       eloop_terminate();
        }
 
        return RADIUS_RX_QUEUED;
 }
 
 
+static int driver_get_ssid(void *priv, u8 *ssid)
+{
+       ssid[0] = 0;
+       return 0;
+}
+
+
+static int driver_get_bssid(void *priv, u8 *bssid)
+{
+       struct eapol_test_data *e = priv;
+
+       if (e->ctrl_iface && !e->id_req_sent) {
+               eloop_register_timeout(0, 0, send_eap_request_identity,
+                                      e->wpa_s, NULL);
+               e->id_req_sent = 1;
+       }
+
+       os_memset(bssid, 0, ETH_ALEN);
+       bssid[5] = 1;
+       return 0;
+}
+
+
+static int driver_get_capa(void *priv, struct wpa_driver_capa *capa)
+{
+       os_memset(capa, 0, sizeof(*capa));
+       capa->flags = WPA_DRIVER_FLAGS_WIRED;
+       return 0;
+}
+
+
+struct wpa_driver_ops eapol_test_drv_ops = {
+       .name = "test",
+       .get_ssid = driver_get_ssid,
+       .get_bssid = driver_get_bssid,
+       .get_capa = driver_get_capa,
+};
+
 static void wpa_init_conf(struct eapol_test_data *e,
                          struct wpa_supplicant *wpa_s, const char *authsrv,
                          int port, const char *secret,
@@ -916,6 +998,8 @@ static void wpa_init_conf(struct eapol_test_data *e,
        struct hostapd_radius_server *as;
        int res;
 
+       wpa_s->driver = &eapol_test_drv_ops;
+       wpa_s->drv_priv = e;
        wpa_s->bssid[5] = 1;
        os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN);
        e->own_ip_addr.s_addr = htonl((127 << 24) | 1);
@@ -1161,7 +1245,7 @@ static void usage(void)
               "           [-M<client MAC address>] [-o<server cert file] \\\n"
               "           [-N<attr spec>] [-R<PC/SC reader>] "
               "[-P<PC/SC PIN>] \\\n"
-              "           [-A<client IP>] [-i<ifname>]\n"
+              "           [-A<client IP>] [-i<ifname>] [-T<ctrl_iface>]\n"
               "eapol_test scard\n"
               "eapol_test sim <PIN> <num triplets> [debug]\n"
               "\n");
@@ -1217,6 +1301,7 @@ int main(int argc, char *argv[])
        char *pos;
        struct extra_radius_attr *p = NULL, *p1;
        const char *ifname = "test";
+       const char *ctrl_iface = NULL;
 
        if (os_program_init())
                return -1;
@@ -1232,7 +1317,7 @@ int main(int argc, char *argv[])
        wpa_debug_show_keys = 1;
 
        for (;;) {
-               c = getopt(argc, argv, "a:A:c:C:ei:M:nN:o:p:P:r:R:s:St:W");
+               c = getopt(argc, argv, "a:A:c:C:ei:M:nN:o:p:P:r:R:s:St:T:W");
                if (c < 0)
                        break;
                switch (c) {
@@ -1294,6 +1379,10 @@ int main(int argc, char *argv[])
                case 't':
                        timeout = atoi(optarg);
                        break;
+               case 'T':
+                       ctrl_iface = optarg;
+                       eapol_test.ctrl_iface = 1;
+                       break;
                case 'W':
                        wait_for_monitor++;
                        break;
@@ -1340,7 +1429,7 @@ int main(int argc, char *argv[])
                                          &argv[optind + 1]);
        }
 
-       if (conf == NULL) {
+       if (conf == NULL && !ctrl_iface) {
                usage();
                printf("Configuration file is required.\n");
                return -1;
@@ -1362,12 +1451,15 @@ int main(int argc, char *argv[])
        eapol_test.wpa_s = &wpa_s;
        dl_list_init(&wpa_s.bss);
        dl_list_init(&wpa_s.bss_id);
-       wpa_s.conf = wpa_config_read(conf, NULL);
+       if (conf)
+               wpa_s.conf = wpa_config_read(conf, NULL);
+       else
+               wpa_s.conf = wpa_config_alloc_empty(ctrl_iface, NULL);
        if (wpa_s.conf == NULL) {
                printf("Failed to parse configuration file '%s'.\n", conf);
                return -1;
        }
-       if (wpa_s.conf->ssid == NULL) {
+       if (!ctrl_iface && wpa_s.conf->ssid == NULL) {
                printf("No networks defined.\n");
                return -1;
        }
@@ -1391,7 +1483,8 @@ int main(int argc, char *argv[])
                       wpa_s.conf->ctrl_interface);
                return -1;
        }
-       if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
+       if (wpa_s.conf->ssid &&
+           wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
                return -1;
 
        if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid))
@@ -1403,9 +1496,12 @@ int main(int argc, char *argv[])
        if (wait_for_monitor)
                wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);
 
-       eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test,
-                              NULL);
-       eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL);
+       if (!ctrl_iface) {
+               eloop_register_timeout(timeout, 0, eapol_test_timeout,
+                                      &eapol_test, NULL);
+               eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s,
+                                      NULL);
+       }
        eloop_register_signal_terminate(eapol_test_terminate, &wpa_s);
        eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s);
        eloop_run();