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