1/* 2 * Test program for combined WPA authenticator/supplicant 3 * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16 17#include "common.h" 18#include "eloop.h" 19#include "common/ieee802_11_defs.h" 20#include "../config.h" 21#include "rsn_supp/wpa.h" 22#include "rsn_supp/wpa_ie.h" 23#include "../hostapd/wpa.h" 24 25 26extern int wpa_debug_level; 27extern int wpa_debug_show_keys; 28 29 30struct wpa { 31 u8 auth_addr[ETH_ALEN]; 32 u8 supp_addr[ETH_ALEN]; 33 u8 psk[PMK_LEN]; 34 35 /* from authenticator */ 36 u8 auth_eapol_dst[ETH_ALEN]; 37 u8 *auth_eapol; 38 size_t auth_eapol_len; 39 40 /* from supplicant */ 41 u8 *supp_eapol; 42 size_t supp_eapol_len; 43 44 struct wpa_sm *supp; 45 struct wpa_authenticator *auth_group; 46 struct wpa_state_machine *auth; 47 48 struct wpa_ssid ssid; 49 u8 supp_ie[80]; 50 size_t supp_ie_len; 51}; 52 53 54static int supp_get_bssid(void *ctx, u8 *bssid) 55{ 56 struct wpa *wpa = ctx; 57 wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 58 os_memcpy(bssid, wpa->auth_addr, ETH_ALEN); 59 return 0; 60} 61 62 63static void supp_set_state(void *ctx, enum wpa_states state) 64{ 65 wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state); 66} 67 68 69static void auth_eapol_rx(void *eloop_data, void *user_ctx) 70{ 71 struct wpa *wpa = eloop_data; 72 73 wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame"); 74 wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol, 75 wpa->supp_eapol_len); 76} 77 78 79static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, 80 size_t len) 81{ 82 struct wpa *wpa = ctx; 83 84 wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " 85 "len=%lu)", 86 __func__, MAC2STR(dest), proto, (unsigned long) len); 87 88 os_free(wpa->supp_eapol); 89 wpa->supp_eapol = os_malloc(len); 90 if (wpa->supp_eapol == NULL) 91 return -1; 92 os_memcpy(wpa->supp_eapol, buf, len); 93 wpa->supp_eapol_len = len; 94 eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL); 95 96 return 0; 97} 98 99 100static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, 101 u16 data_len, size_t *msg_len, void **data_pos) 102{ 103 struct ieee802_1x_hdr *hdr; 104 105 wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", 106 __func__, type, data_len); 107 108 *msg_len = sizeof(*hdr) + data_len; 109 hdr = os_malloc(*msg_len); 110 if (hdr == NULL) 111 return NULL; 112 113 hdr->version = 2; 114 hdr->type = type; 115 hdr->length = host_to_be16(data_len); 116 117 if (data) 118 os_memcpy(hdr + 1, data, data_len); 119 else 120 os_memset(hdr + 1, 0, data_len); 121 122 if (data_pos) 123 *data_pos = hdr + 1; 124 125 return (u8 *) hdr; 126} 127 128 129static int supp_get_beacon_ie(void *ctx) 130{ 131 struct wpa *wpa = ctx; 132 const u8 *ie; 133 size_t ielen; 134 135 wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 136 137 ie = wpa_auth_get_wpa_ie(wpa->auth_group, &ielen); 138 if (ie == NULL || ielen < 1) 139 return -1; 140 if (ie[0] == WLAN_EID_RSN) 141 return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]); 142 return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]); 143} 144 145 146static int supp_set_key(void *ctx, enum wpa_alg alg, 147 const u8 *addr, int key_idx, int set_tx, 148 const u8 *seq, size_t seq_len, 149 const u8 *key, size_t key_len) 150{ 151 wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " 152 "set_tx=%d)", 153 __func__, alg, MAC2STR(addr), key_idx, set_tx); 154 wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); 155 wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); 156 return 0; 157} 158 159 160static int supp_mlme_setprotection(void *ctx, const u8 *addr, 161 int protection_type, int key_type) 162{ 163 wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " 164 "key_type=%d)", 165 __func__, MAC2STR(addr), protection_type, key_type); 166 return 0; 167} 168 169 170static void supp_cancel_auth_timeout(void *ctx) 171{ 172 wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 173} 174 175 176static int supp_init(struct wpa *wpa) 177{ 178 struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); 179 if (ctx == NULL) 180 return -1; 181 182 ctx->ctx = wpa; 183 ctx->msg_ctx = wpa; 184 ctx->set_state = supp_set_state; 185 ctx->get_bssid = supp_get_bssid; 186 ctx->ether_send = supp_ether_send; 187 ctx->get_beacon_ie = supp_get_beacon_ie; 188 ctx->alloc_eapol = supp_alloc_eapol; 189 ctx->set_key = supp_set_key; 190 ctx->mlme_setprotection = supp_mlme_setprotection; 191 ctx->cancel_auth_timeout = supp_cancel_auth_timeout; 192 wpa->supp = wpa_sm_init(ctx); 193 if (wpa->supp == NULL) { 194 wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); 195 return -1; 196 } 197 198 wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr); 199 wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1); 200 wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); 201 wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); 202 wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); 203 wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); 204 wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN); 205 206 wpa->supp_ie_len = sizeof(wpa->supp_ie); 207 if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie, 208 &wpa->supp_ie_len) < 0) { 209 wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" 210 " failed"); 211 return -1; 212 } 213 214 wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr); 215 216 return 0; 217} 218 219 220static void auth_logger(void *ctx, const u8 *addr, logger_level level, 221 const char *txt) 222{ 223 if (addr) 224 wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s", 225 MAC2STR(addr), txt); 226 else 227 wpa_printf(MSG_DEBUG, "AUTH: %s", txt); 228} 229 230 231static void supp_eapol_rx(void *eloop_data, void *user_ctx) 232{ 233 struct wpa *wpa = eloop_data; 234 235 wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame"); 236 wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol, 237 wpa->auth_eapol_len); 238} 239 240 241static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, 242 size_t data_len, int encrypt) 243{ 244 struct wpa *wpa = ctx; 245 246 wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu " 247 "encrypt=%d)", 248 __func__, MAC2STR(addr), (unsigned long) data_len, encrypt); 249 250 os_free(wpa->auth_eapol); 251 wpa->auth_eapol = os_malloc(data_len); 252 if (wpa->auth_eapol == NULL) 253 return -1; 254 os_memcpy(wpa->auth_eapol_dst, addr, ETH_ALEN); 255 os_memcpy(wpa->auth_eapol, data, data_len); 256 wpa->auth_eapol_len = data_len; 257 eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); 258 259 return 0; 260} 261 262 263static const u8 * auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk) 264{ 265 struct wpa *wpa = ctx; 266 wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", 267 __func__, MAC2STR(addr), prev_psk); 268 if (prev_psk) 269 return NULL; 270 return wpa->psk; 271} 272 273 274static int auth_init_group(struct wpa *wpa) 275{ 276 struct wpa_auth_config conf; 277 struct wpa_auth_callbacks cb; 278 279 wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine"); 280 281 os_memset(&conf, 0, sizeof(conf)); 282 conf.wpa = 2; 283 conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; 284 conf.wpa_pairwise = WPA_CIPHER_CCMP; 285 conf.rsn_pairwise = WPA_CIPHER_CCMP; 286 conf.wpa_group = WPA_CIPHER_CCMP; 287 conf.eapol_version = 2; 288 289 os_memset(&cb, 0, sizeof(cb)); 290 cb.ctx = wpa; 291 cb.logger = auth_logger; 292 cb.send_eapol = auth_send_eapol; 293 cb.get_psk = auth_get_psk; 294 295 wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &cb); 296 if (wpa->auth_group == NULL) { 297 wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); 298 return -1; 299 } 300 301 return 0; 302} 303 304 305static int auth_init(struct wpa *wpa) 306{ 307 wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr); 308 if (wpa->auth == NULL) { 309 wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); 310 return -1; 311 } 312 313 if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, wpa->supp_ie, 314 wpa->supp_ie_len, NULL, 0) != WPA_IE_OK) { 315 wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); 316 return -1; 317 } 318 319 wpa_auth_sm_event(wpa->auth, WPA_ASSOC); 320 321 wpa_auth_sta_associated(wpa->auth_group, wpa->auth); 322 323 return 0; 324} 325 326 327static void deinit(struct wpa *wpa) 328{ 329 wpa_auth_sta_deinit(wpa->auth); 330 wpa_sm_deinit(wpa->supp); 331 wpa_deinit(wpa->auth_group); 332 os_free(wpa->auth_eapol); 333 wpa->auth_eapol = NULL; 334 os_free(wpa->supp_eapol); 335 wpa->supp_eapol = NULL; 336} 337 338 339int main(int argc, char *argv[]) 340{ 341 struct wpa wpa; 342 343 if (os_program_init()) 344 return -1; 345 346 os_memset(&wpa, 0, sizeof(wpa)); 347 os_memset(wpa.auth_addr, 0x12, ETH_ALEN); 348 os_memset(wpa.supp_addr, 0x32, ETH_ALEN); 349 os_memset(wpa.psk, 0x44, PMK_LEN); 350 351 wpa_debug_level = 0; 352 wpa_debug_show_keys = 1; 353 354 if (eloop_init()) { 355 wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 356 return -1; 357 } 358 359 if (auth_init_group(&wpa) < 0) 360 return -1; 361 362 if (supp_init(&wpa) < 0) 363 return -1; 364 365 if (auth_init(&wpa) < 0) 366 return -1; 367 368 wpa_printf(MSG_DEBUG, "Starting eloop"); 369 eloop_run(); 370 wpa_printf(MSG_DEBUG, "eloop done"); 371 372 deinit(&wpa); 373 374 eloop_destroy(); 375 376 os_program_deinit(); 377 378 return 0; 379} 380