1189251Ssam/* 2189251Ssam * Test program for combined WPA authenticator/supplicant 3189251Ssam * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11189251Ssam#include "common.h" 12189251Ssam#include "eloop.h" 13214734Srpaulo#include "common/ieee802_11_defs.h" 14214734Srpaulo#include "../config.h" 15214734Srpaulo#include "rsn_supp/wpa.h" 16214734Srpaulo#include "rsn_supp/wpa_ie.h" 17189251Ssam#include "../hostapd/wpa.h" 18189251Ssam 19189251Ssam 20189251Ssamextern int wpa_debug_level; 21189251Ssamextern int wpa_debug_show_keys; 22189251Ssam 23189251Ssam 24189251Ssamstruct wpa { 25189251Ssam u8 auth_addr[ETH_ALEN]; 26189251Ssam u8 supp_addr[ETH_ALEN]; 27189251Ssam u8 psk[PMK_LEN]; 28189251Ssam 29189251Ssam /* from authenticator */ 30189251Ssam u8 auth_eapol_dst[ETH_ALEN]; 31189251Ssam u8 *auth_eapol; 32189251Ssam size_t auth_eapol_len; 33189251Ssam 34189251Ssam /* from supplicant */ 35189251Ssam u8 *supp_eapol; 36189251Ssam size_t supp_eapol_len; 37189251Ssam 38189251Ssam struct wpa_sm *supp; 39189251Ssam struct wpa_authenticator *auth_group; 40189251Ssam struct wpa_state_machine *auth; 41189251Ssam 42189251Ssam struct wpa_ssid ssid; 43189251Ssam u8 supp_ie[80]; 44189251Ssam size_t supp_ie_len; 45189251Ssam}; 46189251Ssam 47189251Ssam 48189251Ssamstatic int supp_get_bssid(void *ctx, u8 *bssid) 49189251Ssam{ 50189251Ssam struct wpa *wpa = ctx; 51189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 52189251Ssam os_memcpy(bssid, wpa->auth_addr, ETH_ALEN); 53189251Ssam return 0; 54189251Ssam} 55189251Ssam 56189251Ssam 57214734Srpaulostatic void supp_set_state(void *ctx, enum wpa_states state) 58189251Ssam{ 59189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state); 60189251Ssam} 61189251Ssam 62189251Ssam 63189251Ssamstatic void auth_eapol_rx(void *eloop_data, void *user_ctx) 64189251Ssam{ 65189251Ssam struct wpa *wpa = eloop_data; 66189251Ssam 67189251Ssam wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame"); 68189251Ssam wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol, 69189251Ssam wpa->supp_eapol_len); 70189251Ssam} 71189251Ssam 72189251Ssam 73189251Ssamstatic int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, 74189251Ssam size_t len) 75189251Ssam{ 76189251Ssam struct wpa *wpa = ctx; 77189251Ssam 78189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " 79189251Ssam "len=%lu)", 80189251Ssam __func__, MAC2STR(dest), proto, (unsigned long) len); 81189251Ssam 82189251Ssam os_free(wpa->supp_eapol); 83189251Ssam wpa->supp_eapol = os_malloc(len); 84189251Ssam if (wpa->supp_eapol == NULL) 85189251Ssam return -1; 86189251Ssam os_memcpy(wpa->supp_eapol, buf, len); 87189251Ssam wpa->supp_eapol_len = len; 88189251Ssam eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL); 89189251Ssam 90189251Ssam return 0; 91189251Ssam} 92189251Ssam 93189251Ssam 94189251Ssamstatic u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, 95189251Ssam u16 data_len, size_t *msg_len, void **data_pos) 96189251Ssam{ 97189251Ssam struct ieee802_1x_hdr *hdr; 98189251Ssam 99189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", 100189251Ssam __func__, type, data_len); 101189251Ssam 102189251Ssam *msg_len = sizeof(*hdr) + data_len; 103189251Ssam hdr = os_malloc(*msg_len); 104189251Ssam if (hdr == NULL) 105189251Ssam return NULL; 106189251Ssam 107189251Ssam hdr->version = 2; 108189251Ssam hdr->type = type; 109189251Ssam hdr->length = host_to_be16(data_len); 110189251Ssam 111189251Ssam if (data) 112189251Ssam os_memcpy(hdr + 1, data, data_len); 113189251Ssam else 114189251Ssam os_memset(hdr + 1, 0, data_len); 115189251Ssam 116189251Ssam if (data_pos) 117189251Ssam *data_pos = hdr + 1; 118189251Ssam 119189251Ssam return (u8 *) hdr; 120189251Ssam} 121189251Ssam 122189251Ssam 123189251Ssamstatic int supp_get_beacon_ie(void *ctx) 124189251Ssam{ 125189251Ssam struct wpa *wpa = ctx; 126189251Ssam const u8 *ie; 127189251Ssam size_t ielen; 128189251Ssam 129189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 130189251Ssam 131189251Ssam ie = wpa_auth_get_wpa_ie(wpa->auth_group, &ielen); 132189251Ssam if (ie == NULL || ielen < 1) 133189251Ssam return -1; 134189251Ssam if (ie[0] == WLAN_EID_RSN) 135189251Ssam return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]); 136189251Ssam return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]); 137189251Ssam} 138189251Ssam 139189251Ssam 140214734Srpaulostatic int supp_set_key(void *ctx, enum wpa_alg alg, 141189251Ssam const u8 *addr, int key_idx, int set_tx, 142189251Ssam const u8 *seq, size_t seq_len, 143189251Ssam const u8 *key, size_t key_len) 144189251Ssam{ 145189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " 146189251Ssam "set_tx=%d)", 147189251Ssam __func__, alg, MAC2STR(addr), key_idx, set_tx); 148189251Ssam wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); 149189251Ssam wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); 150189251Ssam return 0; 151189251Ssam} 152189251Ssam 153189251Ssam 154189251Ssamstatic int supp_mlme_setprotection(void *ctx, const u8 *addr, 155189251Ssam int protection_type, int key_type) 156189251Ssam{ 157189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " 158189251Ssam "key_type=%d)", 159189251Ssam __func__, MAC2STR(addr), protection_type, key_type); 160189251Ssam return 0; 161189251Ssam} 162189251Ssam 163189251Ssam 164189251Ssamstatic void supp_cancel_auth_timeout(void *ctx) 165189251Ssam{ 166189251Ssam wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 167189251Ssam} 168189251Ssam 169189251Ssam 170189251Ssamstatic int supp_init(struct wpa *wpa) 171189251Ssam{ 172189251Ssam struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); 173189251Ssam if (ctx == NULL) 174189251Ssam return -1; 175189251Ssam 176189251Ssam ctx->ctx = wpa; 177214734Srpaulo ctx->msg_ctx = wpa; 178189251Ssam ctx->set_state = supp_set_state; 179189251Ssam ctx->get_bssid = supp_get_bssid; 180189251Ssam ctx->ether_send = supp_ether_send; 181189251Ssam ctx->get_beacon_ie = supp_get_beacon_ie; 182189251Ssam ctx->alloc_eapol = supp_alloc_eapol; 183189251Ssam ctx->set_key = supp_set_key; 184189251Ssam ctx->mlme_setprotection = supp_mlme_setprotection; 185189251Ssam ctx->cancel_auth_timeout = supp_cancel_auth_timeout; 186189251Ssam wpa->supp = wpa_sm_init(ctx); 187189251Ssam if (wpa->supp == NULL) { 188189251Ssam wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); 189189251Ssam return -1; 190189251Ssam } 191189251Ssam 192189251Ssam wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr); 193189251Ssam wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1); 194189251Ssam wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); 195189251Ssam wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); 196189251Ssam wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); 197189251Ssam wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); 198189251Ssam wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN); 199189251Ssam 200189251Ssam wpa->supp_ie_len = sizeof(wpa->supp_ie); 201189251Ssam if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie, 202189251Ssam &wpa->supp_ie_len) < 0) { 203189251Ssam wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" 204189251Ssam " failed"); 205189251Ssam return -1; 206189251Ssam } 207189251Ssam 208189251Ssam wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr); 209189251Ssam 210189251Ssam return 0; 211189251Ssam} 212189251Ssam 213189251Ssam 214189251Ssamstatic void auth_logger(void *ctx, const u8 *addr, logger_level level, 215189251Ssam const char *txt) 216189251Ssam{ 217189251Ssam if (addr) 218189251Ssam wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s", 219189251Ssam MAC2STR(addr), txt); 220189251Ssam else 221189251Ssam wpa_printf(MSG_DEBUG, "AUTH: %s", txt); 222189251Ssam} 223189251Ssam 224189251Ssam 225189251Ssamstatic void supp_eapol_rx(void *eloop_data, void *user_ctx) 226189251Ssam{ 227189251Ssam struct wpa *wpa = eloop_data; 228189251Ssam 229189251Ssam wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame"); 230189251Ssam wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol, 231189251Ssam wpa->auth_eapol_len); 232189251Ssam} 233189251Ssam 234189251Ssam 235189251Ssamstatic int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, 236189251Ssam size_t data_len, int encrypt) 237189251Ssam{ 238189251Ssam struct wpa *wpa = ctx; 239189251Ssam 240189251Ssam wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu " 241189251Ssam "encrypt=%d)", 242189251Ssam __func__, MAC2STR(addr), (unsigned long) data_len, encrypt); 243189251Ssam 244189251Ssam os_free(wpa->auth_eapol); 245189251Ssam wpa->auth_eapol = os_malloc(data_len); 246189251Ssam if (wpa->auth_eapol == NULL) 247189251Ssam return -1; 248189251Ssam os_memcpy(wpa->auth_eapol_dst, addr, ETH_ALEN); 249189251Ssam os_memcpy(wpa->auth_eapol, data, data_len); 250189251Ssam wpa->auth_eapol_len = data_len; 251189251Ssam eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); 252189251Ssam 253189251Ssam return 0; 254189251Ssam} 255189251Ssam 256189251Ssam 257189251Ssamstatic const u8 * auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk) 258189251Ssam{ 259189251Ssam struct wpa *wpa = ctx; 260189251Ssam wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", 261189251Ssam __func__, MAC2STR(addr), prev_psk); 262189251Ssam if (prev_psk) 263189251Ssam return NULL; 264189251Ssam return wpa->psk; 265189251Ssam} 266189251Ssam 267189251Ssam 268189251Ssamstatic int auth_init_group(struct wpa *wpa) 269189251Ssam{ 270189251Ssam struct wpa_auth_config conf; 271189251Ssam struct wpa_auth_callbacks cb; 272189251Ssam 273189251Ssam wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine"); 274189251Ssam 275189251Ssam os_memset(&conf, 0, sizeof(conf)); 276189251Ssam conf.wpa = 2; 277189251Ssam conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; 278189251Ssam conf.wpa_pairwise = WPA_CIPHER_CCMP; 279189251Ssam conf.rsn_pairwise = WPA_CIPHER_CCMP; 280189251Ssam conf.wpa_group = WPA_CIPHER_CCMP; 281189251Ssam conf.eapol_version = 2; 282189251Ssam 283189251Ssam os_memset(&cb, 0, sizeof(cb)); 284189251Ssam cb.ctx = wpa; 285189251Ssam cb.logger = auth_logger; 286189251Ssam cb.send_eapol = auth_send_eapol; 287189251Ssam cb.get_psk = auth_get_psk; 288189251Ssam 289189251Ssam wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &cb); 290189251Ssam if (wpa->auth_group == NULL) { 291189251Ssam wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); 292189251Ssam return -1; 293189251Ssam } 294189251Ssam 295189251Ssam return 0; 296189251Ssam} 297189251Ssam 298189251Ssam 299189251Ssamstatic int auth_init(struct wpa *wpa) 300189251Ssam{ 301189251Ssam wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr); 302189251Ssam if (wpa->auth == NULL) { 303189251Ssam wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); 304189251Ssam return -1; 305189251Ssam } 306189251Ssam 307189251Ssam if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, wpa->supp_ie, 308189251Ssam wpa->supp_ie_len, NULL, 0) != WPA_IE_OK) { 309189251Ssam wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); 310189251Ssam return -1; 311189251Ssam } 312189251Ssam 313189251Ssam wpa_auth_sm_event(wpa->auth, WPA_ASSOC); 314189251Ssam 315189251Ssam wpa_auth_sta_associated(wpa->auth_group, wpa->auth); 316189251Ssam 317189251Ssam return 0; 318189251Ssam} 319189251Ssam 320189251Ssam 321189251Ssamstatic void deinit(struct wpa *wpa) 322189251Ssam{ 323189251Ssam wpa_auth_sta_deinit(wpa->auth); 324189251Ssam wpa_sm_deinit(wpa->supp); 325189251Ssam wpa_deinit(wpa->auth_group); 326189251Ssam os_free(wpa->auth_eapol); 327189251Ssam wpa->auth_eapol = NULL; 328189251Ssam os_free(wpa->supp_eapol); 329189251Ssam wpa->supp_eapol = NULL; 330189251Ssam} 331189251Ssam 332189251Ssam 333189251Ssamint main(int argc, char *argv[]) 334189251Ssam{ 335189251Ssam struct wpa wpa; 336189251Ssam 337189251Ssam if (os_program_init()) 338189251Ssam return -1; 339189251Ssam 340189251Ssam os_memset(&wpa, 0, sizeof(wpa)); 341189251Ssam os_memset(wpa.auth_addr, 0x12, ETH_ALEN); 342189251Ssam os_memset(wpa.supp_addr, 0x32, ETH_ALEN); 343189251Ssam os_memset(wpa.psk, 0x44, PMK_LEN); 344189251Ssam 345189251Ssam wpa_debug_level = 0; 346189251Ssam wpa_debug_show_keys = 1; 347189251Ssam 348214734Srpaulo if (eloop_init()) { 349189251Ssam wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 350189251Ssam return -1; 351189251Ssam } 352189251Ssam 353189251Ssam if (auth_init_group(&wpa) < 0) 354189251Ssam return -1; 355189251Ssam 356189251Ssam if (supp_init(&wpa) < 0) 357189251Ssam return -1; 358189251Ssam 359189251Ssam if (auth_init(&wpa) < 0) 360189251Ssam return -1; 361189251Ssam 362189251Ssam wpa_printf(MSG_DEBUG, "Starting eloop"); 363189251Ssam eloop_run(); 364189251Ssam wpa_printf(MSG_DEBUG, "eloop done"); 365189251Ssam 366189251Ssam deinit(&wpa); 367189251Ssam 368189251Ssam eloop_destroy(); 369189251Ssam 370189251Ssam os_program_deinit(); 371189251Ssam 372189251Ssam return 0; 373189251Ssam} 374