1 /* 2 * EAP-WSC server for Wi-Fi Protected Setup 3 * Copyright (c) 2007-2008, Jouni Malinen <j (at) 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 "eap_i.h" 20 #include "eap_common/eap_wsc_common.h" 21 #include "p2p/p2p.h" 22 #include "wps/wps.h" 23 24 25 struct eap_wsc_data { 26 enum { START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; 27 int registrar; 28 struct wpabuf *in_buf; 29 struct wpabuf *out_buf; 30 enum wsc_op_code in_op_code, out_op_code; 31 size_t out_used; 32 size_t fragment_size; 33 struct wps_data *wps; 34 int ext_reg_timeout; 35 }; 36 37 38 #ifndef CONFIG_NO_STDOUT_DEBUG 39 static const char * eap_wsc_state_txt(int state) 40 { 41 switch (state) { 42 case START: 43 return "START"; 44 case MESG: 45 return "MESG"; 46 case FRAG_ACK: 47 return "FRAG_ACK"; 48 case WAIT_FRAG_ACK: 49 return "WAIT_FRAG_ACK"; 50 case DONE: 51 return "DONE"; 52 case FAIL: 53 return "FAIL"; 54 default: 55 return "?"; 56 } 57 } 58 #endif /* CONFIG_NO_STDOUT_DEBUG */ 59 60 61 static void eap_wsc_state(struct eap_wsc_data *data, int state) 62 { 63 wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", 64 eap_wsc_state_txt(data->state), 65 eap_wsc_state_txt(state)); 66 data->state = state; 67 } 68 69 70 static void eap_wsc_ext_reg_timeout(void *eloop_ctx, void *timeout_ctx) 71 { 72 struct eap_sm *sm = eloop_ctx; 73 struct eap_wsc_data *data = timeout_ctx; 74 75 if (sm->method_pending != METHOD_PENDING_WAIT) 76 return; 77 78 wpa_printf(MSG_DEBUG, "EAP-WSC: Timeout while waiting for an External " 79 "Registrar"); 80 data->ext_reg_timeout = 1; 81 eap_sm_pending_cb(sm); 82 } 83 84 85 static void * eap_wsc_init(struct eap_sm *sm) 86 { 87 struct eap_wsc_data *data; 88 int registrar; 89 struct wps_config cfg; 90 91 if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN && 92 os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 93 0) 94 registrar = 0; /* Supplicant is Registrar */ 95 else if (sm->identity && sm->identity_len == WSC_ID_ENROLLEE_LEN && 96 os_memcmp(sm->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) 97 == 0) 98 registrar = 1; /* Supplicant is Enrollee */ 99 else { 100 wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", 101 sm->identity, sm->identity_len); 102 return NULL; 103 } 104 105 data = os_zalloc(sizeof(*data)); 106 if (data == NULL) 107 return NULL; 108 data->state = registrar ? START : MESG; 109 data->registrar = registrar; 110 111 os_memset(&cfg, 0, sizeof(cfg)); 112 cfg.wps = sm->wps; 113 cfg.registrar = registrar; 114 if (registrar) { 115 if (sm->wps == NULL || sm->wps->registrar == NULL) { 116 wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not " 117 "initialized"); 118 os_free(data); 119 return NULL; 120 } 121 } else { 122 if (sm->user == NULL || sm->user->password == NULL) { 123 /* 124 * In theory, this should not really be needed, but 125 * Windows 7 uses Registrar mode to probe AP's WPS 126 * capabilities before trying to use Enrollee and fails 127 * if the AP does not allow that probing to happen.. 128 */ 129 wpa_printf(MSG_DEBUG, "EAP-WSC: No AP PIN (password) " 130 "configured for Enrollee functionality - " 131 "allow for probing capabilities (M1)"); 132 } else { 133 cfg.pin = sm->user->password; 134 cfg.pin_len = sm->user->password_len; 135 } 136 } 137 cfg.assoc_wps_ie = sm->assoc_wps_ie; 138 cfg.peer_addr = sm->peer_addr; 139 #ifdef CONFIG_P2P 140 if (sm->assoc_p2p_ie) { 141 wpa_printf(MSG_DEBUG, "EAP-WSC: Prefer PSK format for P2P " 142 "client"); 143 cfg.use_psk_key = 1; 144 cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie); 145 } 146 #endif /* CONFIG_P2P */ 147 cfg.pbc_in_m1 = sm->pbc_in_m1; 148 data->wps = wps_init(&cfg); 149 if (data->wps == NULL) { 150 os_free(data); 151 return NULL; 152 } 153 data->fragment_size = sm->fragment_size > 0 ? sm->fragment_size : 154 WSC_FRAGMENT_SIZE; 155 156 return data; 157 } 158 159 160 static void eap_wsc_reset(struct eap_sm *sm, void *priv) 161 { 162 struct eap_wsc_data *data = priv; 163 eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 164 wpabuf_free(data->in_buf); 165 wpabuf_free(data->out_buf); 166 wps_deinit(data->wps); 167 os_free(data); 168 } 169 170 171 static struct wpabuf * eap_wsc_build_start(struct eap_sm *sm, 172 struct eap_wsc_data *data, u8 id) 173 { 174 struct wpabuf *req; 175 176 req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, 177 EAP_CODE_REQUEST, id); 178 if (req == NULL) { 179 wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " 180 "request"); 181 return NULL; 182 } 183 184 wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/Start"); 185 wpabuf_put_u8(req, WSC_Start); /* Op-Code */ 186 wpabuf_put_u8(req, 0); /* Flags */ 187 188 return req; 189 } 190 191 192 static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id) 193 { 194 struct wpabuf *req; 195 u8 flags; 196 size_t send_len, plen; 197 198 flags = 0; 199 send_len = wpabuf_len(data->out_buf) - data->out_used; 200 if (2 + send_len > data->fragment_size) { 201 send_len = data->fragment_size - 2; 202 flags |= WSC_FLAGS_MF; 203 if (data->out_used == 0) { 204 flags |= WSC_FLAGS_LF; 205 send_len -= 2; 206 } 207 } 208 plen = 2 + send_len; 209 if (flags & WSC_FLAGS_LF) 210 plen += 2; 211 req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, 212 EAP_CODE_REQUEST, id); 213 if (req == NULL) { 214 wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " 215 "request"); 216 return NULL; 217 } 218 219 wpabuf_put_u8(req, data->out_op_code); /* Op-Code */ 220 wpabuf_put_u8(req, flags); /* Flags */ 221 if (flags & WSC_FLAGS_LF) 222 wpabuf_put_be16(req, wpabuf_len(data->out_buf)); 223 224 wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, 225 send_len); 226 data->out_used += send_len; 227 228 if (data->out_used == wpabuf_len(data->out_buf)) { 229 wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 230 "(message sent completely)", 231 (unsigned long) send_len); 232 wpabuf_free(data->out_buf); 233 data->out_buf = NULL; 234 data->out_used = 0; 235 eap_wsc_state(data, MESG); 236 } else { 237 wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " 238 "(%lu more to send)", (unsigned long) send_len, 239 (unsigned long) wpabuf_len(data->out_buf) - 240 data->out_used); 241 eap_wsc_state(data, WAIT_FRAG_ACK); 242 } 243 244 return req; 245 } 246 247 248 static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id) 249 { 250 struct eap_wsc_data *data = priv; 251 252 switch (data->state) { 253 case START: 254 return eap_wsc_build_start(sm, data, id); 255 case MESG: 256 if (data->out_buf == NULL) { 257 data->out_buf = wps_get_msg(data->wps, 258 &data->out_op_code); 259 if (data->out_buf == NULL) { 260 wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to " 261 "receive message from WPS"); 262 return NULL; 263 } 264 data->out_used = 0; 265 } 266 /* pass through */ 267 case WAIT_FRAG_ACK: 268 return eap_wsc_build_msg(data, id); 269 case FRAG_ACK: 270 return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST); 271 default: 272 wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in " 273 "buildReq", data->state); 274 return NULL; 275 } 276 } 277 278 279 static Boolean eap_wsc_check(struct eap_sm *sm, void *priv, 280 struct wpabuf *respData) 281 { 282 const u8 *pos; 283 size_t len; 284 285 pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 286 respData, &len); 287 if (pos == NULL || len < 2) { 288 wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame"); 289 return TRUE; 290 } 291 292 return FALSE; 293 } 294 295 296 static int eap_wsc_process_cont(struct eap_wsc_data *data, 297 const u8 *buf, size_t len, u8 op_code) 298 { 299 /* Process continuation of a pending message */ 300 if (op_code != data->in_op_code) { 301 wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " 302 "fragment (expected %d)", 303 op_code, data->in_op_code); 304 eap_wsc_state(data, FAIL); 305 return -1; 306 } 307 308 if (len > wpabuf_tailroom(data->in_buf)) { 309 wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); 310 eap_wsc_state(data, FAIL); 311 return -1; 312 } 313 314 wpabuf_put_data(data->in_buf, buf, len); 315 wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu " 316 "bytes more", (unsigned long) len, 317 (unsigned long) wpabuf_tailroom(data->in_buf)); 318 319 return 0; 320 } 321 322 323 static int eap_wsc_process_fragment(struct eap_wsc_data *data, 324 u8 flags, u8 op_code, u16 message_length, 325 const u8 *buf, size_t len) 326 { 327 /* Process a fragment that is not the last one of the message */ 328 if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { 329 wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length " 330 "field in a fragmented packet"); 331 return -1; 332 } 333 334 if (data->in_buf == NULL) { 335 /* First fragment of the message */ 336 data->in_buf = wpabuf_alloc(message_length); 337 if (data->in_buf == NULL) { 338 wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " 339 "message"); 340 return -1; 341 } 342 data->in_op_code = op_code; 343 wpabuf_put_data(data->in_buf, buf, len); 344 wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in " 345 "first fragment, waiting for %lu bytes more", 346 (unsigned long) len, 347 (unsigned long) wpabuf_tailroom(data->in_buf)); 348 } 349 350 return 0; 351 } 352 353 354 static void eap_wsc_process(struct eap_sm *sm, void *priv, 355 struct wpabuf *respData) 356 { 357 struct eap_wsc_data *data = priv; 358 const u8 *start, *pos, *end; 359 size_t len; 360 u8 op_code, flags; 361 u16 message_length = 0; 362 enum wps_process_res res; 363 struct wpabuf tmpbuf; 364 365 eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 366 if (data->ext_reg_timeout) { 367 eap_wsc_state(data, FAIL); 368 return; 369 } 370 371 pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 372 respData, &len); 373 if (pos == NULL || len < 2) 374 return; /* Should not happen; message already verified */ 375 376 start = pos; 377 end = start + len; 378 379 op_code = *pos++; 380 flags = *pos++; 381 if (flags & WSC_FLAGS_LF) { 382 if (end - pos < 2) { 383 wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); 384 return; 385 } 386 message_length = WPA_GET_BE16(pos); 387 pos += 2; 388 389 if (message_length < end - pos) { 390 wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " 391 "Length"); 392 return; 393 } 394 } 395 396 wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " 397 "Flags 0x%x Message Length %d", 398 op_code, flags, message_length); 399 400 if (data->state == WAIT_FRAG_ACK) { 401 if (op_code != WSC_FRAG_ACK) { 402 wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " 403 "in WAIT_FRAG_ACK state", op_code); 404 eap_wsc_state(data, FAIL); 405 return; 406 } 407 wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); 408 eap_wsc_state(data, MESG); 409 return; 410 } 411 412 if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && 413 op_code != WSC_Done) { 414 wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", 415 op_code); 416 eap_wsc_state(data, FAIL); 417 return; 418 } 419 420 if (data->in_buf && 421 eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { 422 eap_wsc_state(data, FAIL); 423 return; 424 } 425 426 if (flags & WSC_FLAGS_MF) { 427 if (eap_wsc_process_fragment(data, flags, op_code, 428 message_length, pos, end - pos) < 429 0) 430 eap_wsc_state(data, FAIL); 431 else 432 eap_wsc_state(data, FRAG_ACK); 433 return; 434 } 435 436 if (data->in_buf == NULL) { 437 /* Wrap unfragmented messages as wpabuf without extra copy */ 438 wpabuf_set(&tmpbuf, pos, end - pos); 439 data->in_buf = &tmpbuf; 440 } 441 442 res = wps_process_msg(data->wps, op_code, data->in_buf); 443 switch (res) { 444 case WPS_DONE: 445 wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " 446 "successfully - report EAP failure"); 447 eap_wsc_state(data, FAIL); 448 break; 449 case WPS_CONTINUE: 450 eap_wsc_state(data, MESG); 451 break; 452 case WPS_FAILURE: 453 wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); 454 eap_wsc_state(data, FAIL); 455 break; 456 case WPS_PENDING: 457 eap_wsc_state(data, MESG); 458 sm->method_pending = METHOD_PENDING_WAIT; 459 eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); 460 eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout, 461 sm, data); 462 break; 463 } 464 465 if (data->in_buf != &tmpbuf) 466 wpabuf_free(data->in_buf); 467 data->in_buf = NULL; 468 } 469 470 471 static Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv) 472 { 473 struct eap_wsc_data *data = priv; 474 return data->state == FAIL; 475 } 476 477 478 static Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv) 479 { 480 /* EAP-WSC will always result in EAP-Failure */ 481 return FALSE; 482 } 483 484 485 static int eap_wsc_getTimeout(struct eap_sm *sm, void *priv) 486 { 487 /* Recommended retransmit times: retransmit timeout 5 seconds, 488 * per-message timeout 15 seconds, i.e., 3 tries. */ 489 sm->MaxRetrans = 2; /* total 3 attempts */ 490 return 5; 491 } 492 493 494 int eap_server_wsc_register(void) 495 { 496 struct eap_method *eap; 497 int ret; 498 499 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 500 EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 501 "WSC"); 502 if (eap == NULL) 503 return -1; 504 505 eap->init = eap_wsc_init; 506 eap->reset = eap_wsc_reset; 507 eap->buildReq = eap_wsc_buildReq; 508 eap->check = eap_wsc_check; 509 eap->process = eap_wsc_process; 510 eap->isDone = eap_wsc_isDone; 511 eap->isSuccess = eap_wsc_isSuccess; 512 eap->getTimeout = eap_wsc_getTimeout; 513 514 ret = eap_server_method_register(eap); 515 if (ret) 516 eap_server_method_free(eap); 517 return ret; 518 } 519