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