eapol_test: Add a new operation mode for control interface use

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>
This commit is contained in:
Jouni Malinen 2015-08-21 00:21:20 +03:00
parent 3b3677b3bc
commit 048d084d45

View file

@ -76,6 +76,9 @@ struct eapol_test_data {
const char *pcsc_reader; const char *pcsc_reader;
const char *pcsc_pin; const char *pcsc_pin;
unsigned int ctrl_iface:1;
unsigned int id_req_sent:1;
}; };
static struct eapol_test_data eapol_test; 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) static void eapol_test_eapol_done_cb(void *ctx)
{ {
struct eapol_test_data *e = ctx;
printf("WPA: EAPOL processing complete\n"); 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; struct eapol_test_data *e = ctx;
printf("eapol_sm_cb: result=%d\n", result); printf("eapol_sm_cb: result=%d\n", result);
e->id_req_sent = 0;
if (e->ctrl_iface)
return;
e->eapol_test_num_reauths--; e->eapol_test_num_reauths--;
if (e->eapol_test_num_reauths < 0) if (e->eapol_test_num_reauths < 0)
eloop_terminate(); 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, static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid) struct wpa_ssid *ssid)
{ {
struct eapol_config eapol_conf; struct eapol_config eapol_conf;
struct eapol_ctx *ctx; struct eapol_ctx *ctx;
struct wpa_sm_ctx *wctx;
ctx = os_zalloc(sizeof(*ctx)); ctx = os_zalloc(sizeof(*ctx));
if (ctx == NULL) { if (ctx == NULL) {
@ -590,6 +610,25 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
return -1; 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; wpa_s->current_ssid = ssid;
os_memset(&eapol_conf, 0, sizeof(eapol_conf)); os_memset(&eapol_conf, 0, sizeof(eapol_conf));
eapol_conf.accept_802_1x_keys = 1; 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; struct extra_radius_attr *p, *prev;
wpa_sm_deinit(wpa_s->wpa);
wpa_s->wpa = NULL;
radius_client_deinit(e->radius); radius_client_deinit(e->radius);
wpabuf_free(e->last_eap_radius); wpabuf_free(e->last_eap_radius);
radius_msg_free(e->last_recv_radius); radius_msg_free(e->last_recv_radius);
@ -757,6 +798,8 @@ static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
break; break;
case EAP_CODE_FAILURE: case EAP_CODE_FAILURE:
os_strlcpy(buf, "EAP Failure", sizeof(buf)); os_strlcpy(buf, "EAP Failure", sizeof(buf));
if (e->ctrl_iface)
break;
eloop_terminate(); eloop_terminate();
break; break;
default: default:
@ -901,6 +944,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT && if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
e->eapol_test_num_reauths < 0) || e->eapol_test_num_reauths < 0) ||
hdr->code == RADIUS_CODE_ACCESS_REJECT) { hdr->code == RADIUS_CODE_ACCESS_REJECT) {
if (!e->ctrl_iface)
eloop_terminate(); eloop_terminate();
} }
@ -908,6 +952,44 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
} }
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, static void wpa_init_conf(struct eapol_test_data *e,
struct wpa_supplicant *wpa_s, const char *authsrv, struct wpa_supplicant *wpa_s, const char *authsrv,
int port, const char *secret, int port, const char *secret,
@ -916,6 +998,8 @@ static void wpa_init_conf(struct eapol_test_data *e,
struct hostapd_radius_server *as; struct hostapd_radius_server *as;
int res; int res;
wpa_s->driver = &eapol_test_drv_ops;
wpa_s->drv_priv = e;
wpa_s->bssid[5] = 1; wpa_s->bssid[5] = 1;
os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN); os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN);
e->own_ip_addr.s_addr = htonl((127 << 24) | 1); 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" " [-M<client MAC address>] [-o<server cert file] \\\n"
" [-N<attr spec>] [-R<PC/SC reader>] " " [-N<attr spec>] [-R<PC/SC reader>] "
"[-P<PC/SC PIN>] \\\n" "[-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 scard\n"
"eapol_test sim <PIN> <num triplets> [debug]\n" "eapol_test sim <PIN> <num triplets> [debug]\n"
"\n"); "\n");
@ -1217,6 +1301,7 @@ int main(int argc, char *argv[])
char *pos; char *pos;
struct extra_radius_attr *p = NULL, *p1; struct extra_radius_attr *p = NULL, *p1;
const char *ifname = "test"; const char *ifname = "test";
const char *ctrl_iface = NULL;
if (os_program_init()) if (os_program_init())
return -1; return -1;
@ -1232,7 +1317,7 @@ int main(int argc, char *argv[])
wpa_debug_show_keys = 1; wpa_debug_show_keys = 1;
for (;;) { 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) if (c < 0)
break; break;
switch (c) { switch (c) {
@ -1294,6 +1379,10 @@ int main(int argc, char *argv[])
case 't': case 't':
timeout = atoi(optarg); timeout = atoi(optarg);
break; break;
case 'T':
ctrl_iface = optarg;
eapol_test.ctrl_iface = 1;
break;
case 'W': case 'W':
wait_for_monitor++; wait_for_monitor++;
break; break;
@ -1340,7 +1429,7 @@ int main(int argc, char *argv[])
&argv[optind + 1]); &argv[optind + 1]);
} }
if (conf == NULL) { if (conf == NULL && !ctrl_iface) {
usage(); usage();
printf("Configuration file is required.\n"); printf("Configuration file is required.\n");
return -1; return -1;
@ -1362,12 +1451,15 @@ int main(int argc, char *argv[])
eapol_test.wpa_s = &wpa_s; eapol_test.wpa_s = &wpa_s;
dl_list_init(&wpa_s.bss); dl_list_init(&wpa_s.bss);
dl_list_init(&wpa_s.bss_id); dl_list_init(&wpa_s.bss_id);
if (conf)
wpa_s.conf = wpa_config_read(conf, NULL); wpa_s.conf = wpa_config_read(conf, NULL);
else
wpa_s.conf = wpa_config_alloc_empty(ctrl_iface, NULL);
if (wpa_s.conf == NULL) { if (wpa_s.conf == NULL) {
printf("Failed to parse configuration file '%s'.\n", conf); printf("Failed to parse configuration file '%s'.\n", conf);
return -1; return -1;
} }
if (wpa_s.conf->ssid == NULL) { if (!ctrl_iface && wpa_s.conf->ssid == NULL) {
printf("No networks defined.\n"); printf("No networks defined.\n");
return -1; return -1;
} }
@ -1391,7 +1483,8 @@ int main(int argc, char *argv[])
wpa_s.conf->ctrl_interface); wpa_s.conf->ctrl_interface);
return -1; 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; return -1;
if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid)) 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) if (wait_for_monitor)
wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface); wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);
eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test, 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); 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_terminate(eapol_test_terminate, &wpa_s);
eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s); eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s);
eloop_run(); eloop_run();