1 /* 2 * WPA Supplicant - test code for pre-authentication 3 * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 * 8 * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c. 9 * Not used in production version. 10 */ 11 12 #include "includes.h" 13 #include <assert.h> 14 15 #include "common.h" 16 #include "config.h" 17 #include "eapol_supp/eapol_supp_sm.h" 18 #include "eloop.h" 19 #include "rsn_supp/wpa.h" 20 #include "eap_peer/eap.h" 21 #include "wpa_supplicant_i.h" 22 #include "l2_packet/l2_packet.h" 23 #include "ctrl_iface.h" 24 #include "pcsc_funcs.h" 25 #include "rsn_supp/preauth.h" 26 #include "rsn_supp/pmksa_cache.h" 27 #include "drivers/driver.h" 28 29 30 struct wpa_driver_ops *wpa_drivers[] = { NULL }; 31 32 33 struct preauth_test_data { 34 int auth_timed_out; 35 }; 36 37 38 static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code) 39 { 40 wpa_supplicant_deauthenticate(wpa_s, reason_code); 41 } 42 43 44 static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, 45 const void *data, u16 data_len, 46 size_t *msg_len, void **data_pos) 47 { 48 struct ieee802_1x_hdr *hdr; 49 50 *msg_len = sizeof(*hdr) + data_len; 51 hdr = os_malloc(*msg_len); 52 if (hdr == NULL) 53 return NULL; 54 55 hdr->version = wpa_s->conf->eapol_version; 56 hdr->type = type; 57 hdr->length = htons(data_len); 58 59 if (data) 60 os_memcpy(hdr + 1, data, data_len); 61 else 62 os_memset(hdr + 1, 0, data_len); 63 64 if (data_pos) 65 *data_pos = hdr + 1; 66 67 return (u8 *) hdr; 68 } 69 70 71 static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type, 72 const void *data, u16 data_len, 73 size_t *msg_len, void **data_pos) 74 { 75 return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos); 76 } 77 78 79 static void _wpa_supplicant_set_state(void *ctx, enum wpa_states state) 80 { 81 struct wpa_supplicant *wpa_s = ctx; 82 wpa_s->wpa_state = state; 83 } 84 85 86 static enum wpa_states _wpa_supplicant_get_state(void *ctx) 87 { 88 struct wpa_supplicant *wpa_s = ctx; 89 return wpa_s->wpa_state; 90 } 91 92 93 static int wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto, 94 const u8 *buf, size_t len) 95 { 96 printf("%s - not implemented\n", __func__); 97 return -1; 98 } 99 100 101 static void * wpa_supplicant_get_network_ctx(void *wpa_s) 102 { 103 return wpa_supplicant_get_ssid(wpa_s); 104 } 105 106 107 static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s) 108 { 109 wpa_supplicant_cancel_auth_timeout(wpa_s); 110 } 111 112 113 static int wpa_supplicant_get_beacon_ie(void *wpa_s) 114 { 115 printf("%s - not implemented\n", __func__); 116 return -1; 117 } 118 119 120 static int wpa_supplicant_get_bssid(void *wpa_s, u8 *bssid) 121 { 122 printf("%s - not implemented\n", __func__); 123 return -1; 124 } 125 126 127 static int wpa_supplicant_set_key(void *wpa_s, enum wpa_alg alg, 128 const u8 *addr, int key_idx, int set_tx, 129 const u8 *seq, size_t seq_len, 130 const u8 *key, size_t key_len) 131 { 132 printf("%s - not implemented\n", __func__); 133 return -1; 134 } 135 136 137 static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, 138 int protection_type, 139 int key_type) 140 { 141 printf("%s - not implemented\n", __func__); 142 return -1; 143 } 144 145 146 static int wpa_supplicant_add_pmkid(void *wpa_s, 147 const u8 *bssid, const u8 *pmkid) 148 { 149 printf("%s - not implemented\n", __func__); 150 return -1; 151 } 152 153 154 static int wpa_supplicant_remove_pmkid(void *wpa_s, 155 const u8 *bssid, const u8 *pmkid) 156 { 157 printf("%s - not implemented\n", __func__); 158 return -1; 159 } 160 161 162 static void wpa_supplicant_set_config_blob(void *ctx, 163 struct wpa_config_blob *blob) 164 { 165 struct wpa_supplicant *wpa_s = ctx; 166 wpa_config_set_blob(wpa_s->conf, blob); 167 } 168 169 170 static const struct wpa_config_blob * 171 wpa_supplicant_get_config_blob(void *ctx, const char *name) 172 { 173 struct wpa_supplicant *wpa_s = ctx; 174 return wpa_config_get_blob(wpa_s->conf, name); 175 } 176 177 178 static void test_eapol_clean(struct wpa_supplicant *wpa_s) 179 { 180 rsn_preauth_deinit(wpa_s->wpa); 181 pmksa_candidate_free(wpa_s->wpa); 182 wpa_sm_deinit(wpa_s->wpa); 183 scard_deinit(wpa_s->scard); 184 if (wpa_s->ctrl_iface) { 185 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); 186 wpa_s->ctrl_iface = NULL; 187 } 188 wpa_config_free(wpa_s->conf); 189 } 190 191 192 static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx) 193 { 194 struct preauth_test_data *p = eloop_ctx; 195 printf("EAPOL test timed out\n"); 196 p->auth_timed_out = 1; 197 eloop_terminate(); 198 } 199 200 201 static void eapol_test_poll(void *eloop_ctx, void *timeout_ctx) 202 { 203 struct wpa_supplicant *wpa_s = eloop_ctx; 204 if (!rsn_preauth_in_progress(wpa_s->wpa)) 205 eloop_terminate(); 206 else { 207 eloop_register_timeout(0, 100000, eapol_test_poll, eloop_ctx, 208 timeout_ctx); 209 } 210 } 211 212 213 static struct wpa_driver_ops dummy_driver; 214 215 216 static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *ifname) 217 { 218 struct l2_packet_data *l2; 219 struct wpa_sm_ctx *ctx; 220 221 os_memset(&dummy_driver, 0, sizeof(dummy_driver)); 222 wpa_s->driver = &dummy_driver; 223 224 ctx = os_zalloc(sizeof(*ctx)); 225 assert(ctx != NULL); 226 227 ctx->ctx = wpa_s; 228 ctx->msg_ctx = wpa_s; 229 ctx->set_state = _wpa_supplicant_set_state; 230 ctx->get_state = _wpa_supplicant_get_state; 231 ctx->deauthenticate = _wpa_supplicant_deauthenticate; 232 ctx->set_key = wpa_supplicant_set_key; 233 ctx->get_network_ctx = wpa_supplicant_get_network_ctx; 234 ctx->get_bssid = wpa_supplicant_get_bssid; 235 ctx->ether_send = wpa_ether_send; 236 ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie; 237 ctx->alloc_eapol = _wpa_alloc_eapol; 238 ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout; 239 ctx->add_pmkid = wpa_supplicant_add_pmkid; 240 ctx->remove_pmkid = wpa_supplicant_remove_pmkid; 241 ctx->set_config_blob = wpa_supplicant_set_config_blob; 242 ctx->get_config_blob = wpa_supplicant_get_config_blob; 243 ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; 244 245 wpa_s->wpa = wpa_sm_init(ctx); 246 assert(wpa_s->wpa != NULL); 247 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN); 248 249 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); 250 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname, NULL); 251 252 l2 = l2_packet_init(wpa_s->ifname, NULL, ETH_P_RSN_PREAUTH, NULL, 253 NULL, 0); 254 assert(l2 != NULL); 255 if (l2_packet_get_own_addr(l2, wpa_s->own_addr)) { 256 wpa_printf(MSG_WARNING, "Failed to get own L2 address\n"); 257 exit(-1); 258 } 259 l2_packet_deinit(l2); 260 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); 261 } 262 263 264 static void eapol_test_terminate(int sig, void *signal_ctx) 265 { 266 struct wpa_supplicant *wpa_s = signal_ctx; 267 wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig); 268 eloop_terminate(); 269 } 270 271 272 int main(int argc, char *argv[]) 273 { 274 struct wpa_supplicant wpa_s; 275 int ret = 1; 276 u8 bssid[ETH_ALEN]; 277 struct preauth_test_data preauth_test; 278 279 if (os_program_init()) 280 return -1; 281 282 os_memset(&preauth_test, 0, sizeof(preauth_test)); 283 284 wpa_debug_level = 0; 285 wpa_debug_show_keys = 1; 286 287 if (argc != 4) { 288 printf("usage: preauth_test <conf> <target MAC address> " 289 "<ifname>\n"); 290 return -1; 291 } 292 293 if (hwaddr_aton(argv[2], bssid)) { 294 printf("Failed to parse target address '%s'.\n", argv[2]); 295 return -1; 296 } 297 298 if (eap_register_methods()) { 299 wpa_printf(MSG_ERROR, "Failed to register EAP methods"); 300 return -1; 301 } 302 303 if (eloop_init()) { 304 wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 305 return -1; 306 } 307 308 os_memset(&wpa_s, 0, sizeof(wpa_s)); 309 wpa_s.conf = wpa_config_read(argv[1], NULL); 310 if (wpa_s.conf == NULL) { 311 printf("Failed to parse configuration file '%s'.\n", argv[1]); 312 return -1; 313 } 314 if (wpa_s.conf->ssid == NULL) { 315 printf("No networks defined.\n"); 316 return -1; 317 } 318 319 wpa_init_conf(&wpa_s, argv[3]); 320 wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s); 321 if (wpa_s.ctrl_iface == NULL) { 322 printf("Failed to initialize control interface '%s'.\n" 323 "You may have another preauth_test process already " 324 "running or the file was\n" 325 "left by an unclean termination of preauth_test in " 326 "which case you will need\n" 327 "to manually remove this file before starting " 328 "preauth_test again.\n", 329 wpa_s.conf->ctrl_interface); 330 return -1; 331 } 332 if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid)) 333 return -1; 334 335 if (rsn_preauth_init(wpa_s.wpa, bssid, &wpa_s.conf->ssid->eap)) 336 return -1; 337 338 eloop_register_timeout(30, 0, eapol_test_timeout, &preauth_test, NULL); 339 eloop_register_timeout(0, 100000, eapol_test_poll, &wpa_s, NULL); 340 eloop_register_signal_terminate(eapol_test_terminate, &wpa_s); 341 eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s); 342 eloop_run(); 343 344 if (preauth_test.auth_timed_out) 345 ret = -2; 346 else { 347 ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0) 348 ? 0 : -3; 349 } 350 351 test_eapol_clean(&wpa_s); 352 353 eap_peer_unregister_methods(); 354 355 eloop_destroy(); 356 357 os_program_deinit(); 358 359 return ret; 360 } 361