1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 8 * Sun elects to license this software under the BSD license. 9 * See README for more details. 10 */ 11 12 #pragma ident "%Z%%M% %I% %E% SMI" 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <stdarg.h> 17 #include <unistd.h> 18 #include <string.h> 19 #include <syslog.h> 20 #include <sys/stat.h> 21 #include <errno.h> 22 #include <signal.h> 23 #include <fcntl.h> 24 #include <door.h> 25 #include <libdladm.h> 26 #include <libdllink.h> 27 #include <sys/ethernet.h> 28 29 #include "wpa_impl.h" 30 #include "wpa_enc.h" 31 #include "driver.h" 32 #include "eloop.h" 33 #include "l2_packet.h" 34 35 static const char *wpa_supplicant_version = 36 "wpa_supplicant v1.0"; 37 38 extern struct wpa_driver_ops wpa_driver_wifi_ops; 39 int wpa_debug_level = MSG_ERROR; 40 41 /* 42 * wpa_printf - conditional printf 43 * @level: priority level (MSG_*) of the message 44 * @fmt: printf format string, followed by optional arguments 45 * 46 * This function is used to print conditional debugging and error messages. The 47 * output may be directed to stdout, stderr, and/or syslog based on 48 * configuration. 49 */ 50 void 51 wpa_printf(int level, char *fmt, ...) 52 { 53 va_list ap; 54 char buffer[MAX_LOGBUF]; 55 56 if (level < wpa_debug_level) 57 return; 58 59 va_start(ap, fmt); 60 61 /* LINTED E_SEC_PRINTF_VAR_FMT */ 62 (void) vsnprintf(buffer, sizeof (buffer), fmt, ap); 63 64 va_end(ap); 65 66 syslog(LOG_NOTICE | LOG_DAEMON, "%s", buffer); 67 } 68 69 /* 70 * wpa_hexdump - conditional hex dump 71 * @level: priority level (MSG_*) of the message 72 * @title: title of for the message 73 * @buf: data buffer to be dumped 74 * @len: length of the @buf 75 * 76 * This function is used to print conditional debugging and error messages. The 77 * output may be directed to stdout, stderr, and/or syslog based on 78 * configuration. The contents of @buf is printed out has hex dump. 79 */ 80 void 81 wpa_hexdump(int level, const char *title, const uint8_t *buf, size_t len) 82 { 83 size_t i; 84 char buffer[MAX_LOGBUF], tmp[4]; 85 int n; 86 87 if (level < wpa_debug_level) 88 return; 89 90 (void) snprintf(buffer, sizeof (buffer), "%s - hexdump(len=%d):", 91 title, len); 92 n = strlen(buffer); 93 94 for (i = 0; i < len; i++) { 95 (void) sprintf(tmp, " %02x", buf[i]); 96 97 n += strlen(tmp); 98 if (n >= MAX_LOGBUF) break; 99 100 (void) strlcat(buffer, tmp, sizeof (buffer)); 101 } 102 103 syslog(LOG_NOTICE | LOG_DAEMON, "%s", buffer); 104 } 105 106 static const char * 107 wpa_ssid_txt(char *ssid, size_t ssid_len) 108 { 109 static char ssid_txt[MAX_ESSID_LENGTH + 1]; 110 char *pos; 111 112 if (ssid_len > MAX_ESSID_LENGTH) 113 ssid_len = MAX_ESSID_LENGTH; 114 (void) memcpy(ssid_txt, ssid, ssid_len); 115 ssid_txt[ssid_len] = '\0'; 116 for (pos = ssid_txt; *pos != '\0'; pos ++) { 117 if ((uint8_t)*pos < 32 || (uint8_t)*pos >= 127) 118 *pos = '_'; 119 } 120 return (ssid_txt); 121 } 122 123 /* ARGSUSED */ 124 void 125 wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) 126 { 127 struct wpa_supplicant *wpa_s = eloop_ctx; 128 struct wpa_ssid *ssid; 129 130 if (wpa_s->conf == NULL) 131 return; 132 133 if (wpa_s->wpa_state == WPA_DISCONNECTED) 134 wpa_s->wpa_state = WPA_SCANNING; 135 136 ssid = wpa_s->conf->ssid; 137 wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", 138 ssid ? "specific": "broadcast"); 139 140 if (ssid) { 141 wpa_printf(MSG_DEBUG, "Scan SSID: %s", ssid->ssid); 142 } 143 144 if (wpa_s->driver->scan(wpa_s->ifname)) { 145 wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); 146 } 147 } 148 149 void 150 wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) 151 { 152 wpa_printf(MSG_DEBUG, "Setting scan request: %d sec %d usec", 153 sec, usec); 154 (void) eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 155 (void) eloop_register_timeout(sec, usec, wpa_supplicant_scan, 156 wpa_s, NULL); 157 } 158 159 void 160 wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) 161 { 162 wpa_printf(MSG_DEBUG, "Cancelling scan request"); 163 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 164 } 165 166 /* ARGSUSED */ 167 static void 168 wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) 169 { 170 struct wpa_supplicant *wpa_s = eloop_ctx; 171 172 wpa_printf(MSG_INFO, "Authentication with " MACSTR " timed out.", 173 MAC2STR(wpa_s->bssid)); 174 175 wpa_s->reassociate = 1; 176 wpa_supplicant_req_scan(wpa_s, 0, 0); 177 } 178 179 void 180 wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, 181 int sec, int usec) 182 { 183 wpa_printf(MSG_DEBUG, "Setting authentication timeout: %d sec " 184 "%d usec", sec, usec); 185 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 186 (void) eloop_register_timeout(sec, usec, wpa_supplicant_timeout, 187 wpa_s, NULL); 188 } 189 190 void 191 wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) 192 { 193 wpa_printf(MSG_DEBUG, "Cancelling authentication timeout"); 194 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 195 } 196 197 static void 198 wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) 199 { 200 l2_packet_deinit(wpa_s->l2); 201 wpa_s->l2 = NULL; 202 203 if (wpa_s->conf != NULL) { 204 wpa_config_free(wpa_s->conf); 205 wpa_s->conf = NULL; 206 } 207 208 free(wpa_s->ap_wpa_ie); 209 pmksa_candidate_free(wpa_s); 210 pmksa_cache_free(wpa_s); 211 } 212 213 static void 214 wpa_clear_keys(struct wpa_supplicant *wpa_s, uint8_t *addr) 215 { 216 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 217 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 0, 0, NULL, 0, NULL, 0); 218 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 219 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 1, 0, NULL, 0, NULL, 0); 220 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 221 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 2, 0, NULL, 0, NULL, 0); 222 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 223 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 3, 0, NULL, 0, NULL, 0); 224 if (addr) { 225 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, addr, 226 0, 0, NULL, 0, NULL, 0); 227 } 228 } 229 230 static void 231 wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) 232 { 233 wpa_s->wpa_state = WPA_DISCONNECTED; 234 (void) memset(wpa_s->bssid, 0, IEEE80211_ADDR_LEN); 235 } 236 237 static int 238 wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, 239 dladm_wlan_ess_t *bss, struct wpa_ssid *ssid, 240 uint8_t *wpa_ie, int *wpa_ie_len) 241 { 242 struct wpa_ie_data ie; 243 int sel, proto; 244 uint8_t *ap_ie; 245 size_t ap_ie_len; 246 247 /* RSN or WPA */ 248 if (bss->we_wpa_ie_len && bss->we_wpa_ie[0] == RSN_INFO_ELEM && 249 (ssid->proto & WPA_PROTO_RSN)) { 250 wpa_printf(MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); 251 proto = WPA_PROTO_RSN; 252 } else { 253 wpa_printf(MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); 254 proto = WPA_PROTO_WPA; 255 } 256 257 ap_ie = bss->we_wpa_ie; 258 ap_ie_len = bss->we_wpa_ie_len; 259 260 if (wpa_parse_wpa_ie(wpa_s, ap_ie, ap_ie_len, &ie)) { 261 wpa_printf(MSG_WARNING, "WPA: Failed to parse WPA IE for " 262 "the selected BSS."); 263 return (-1); 264 } 265 266 wpa_s->proto = proto; 267 free(wpa_s->ap_wpa_ie); 268 wpa_s->ap_wpa_ie = malloc(ap_ie_len); 269 (void) memcpy(wpa_s->ap_wpa_ie, ap_ie, ap_ie_len); 270 wpa_s->ap_wpa_ie_len = ap_ie_len; 271 272 sel = ie.group_cipher & ssid->group_cipher; 273 if (sel & WPA_CIPHER_CCMP) { 274 wpa_s->group_cipher = WPA_CIPHER_CCMP; 275 } else if (sel & WPA_CIPHER_TKIP) { 276 wpa_s->group_cipher = WPA_CIPHER_TKIP; 277 } else if (sel & WPA_CIPHER_WEP104) { 278 wpa_s->group_cipher = WPA_CIPHER_WEP104; 279 } else if (sel & WPA_CIPHER_WEP40) { 280 wpa_s->group_cipher = WPA_CIPHER_WEP40; 281 } else { 282 wpa_printf(MSG_WARNING, "WPA: Failed to select group cipher."); 283 return (-1); 284 } 285 286 sel = ie.pairwise_cipher & ssid->pairwise_cipher; 287 if (sel & WPA_CIPHER_CCMP) { 288 wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; 289 } else if (sel & WPA_CIPHER_TKIP) { 290 wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; 291 } else if (sel & WPA_CIPHER_NONE) { 292 wpa_s->pairwise_cipher = WPA_CIPHER_NONE; 293 } else { 294 wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " 295 "cipher."); 296 return (-1); 297 } 298 299 sel = ie.key_mgmt & ssid->key_mgmt; 300 if (sel & WPA_KEY_MGMT_IEEE8021X) { 301 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 302 } else if (sel & WPA_KEY_MGMT_PSK) { 303 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; 304 } else { 305 wpa_printf(MSG_WARNING, "WPA: Failed to select authenticated " 306 "key management type."); 307 return (-1); 308 } 309 310 *wpa_ie_len = wpa_gen_wpa_ie(wpa_s, wpa_ie); 311 if (*wpa_ie_len < 0) { 312 wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE."); 313 return (-1); 314 } 315 wpa_hexdump(MSG_DEBUG, "WPA: Own WPA IE", wpa_ie, *wpa_ie_len); 316 317 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) 318 (void) memcpy(wpa_s->pmk, ssid->psk, PMK_LEN); 319 else if (wpa_s->cur_pmksa) 320 (void) memcpy(wpa_s->pmk, wpa_s->cur_pmksa->pmk, PMK_LEN); 321 else { 322 (void) memset(wpa_s->pmk, 0, PMK_LEN); 323 } 324 325 return (0); 326 } 327 328 static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 329 dladm_wlan_ess_t *bss, struct wpa_ssid *ssid) 330 { 331 uint8_t wpa_ie[IEEE80211_MAX_OPT_IE]; 332 int wpa_ie_len; 333 334 wpa_s->reassociate = 0; 335 wpa_printf(MSG_DEBUG, "Trying to associate with " MACSTR 336 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->we_bssid.wb_bytes), 337 wpa_ssid_txt((char *)ssid->ssid, ssid->ssid_len), bss->we_freq); 338 wpa_supplicant_cancel_scan(wpa_s); 339 340 if (bss->we_wpa_ie_len && 341 (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) { 342 wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, 343 bss->we_bssid.wb_bytes, NULL); 344 if (wpa_s->cur_pmksa) { 345 wpa_hexdump(MSG_DEBUG, "RSN: PMKID", 346 wpa_s->cur_pmksa->pmkid, PMKID_LEN); 347 } 348 if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 349 wpa_ie, &wpa_ie_len)) { 350 wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " 351 "management and encryption suites"); 352 return; 353 } 354 } else { 355 wpa_ie_len = 0; 356 } 357 358 wpa_clear_keys(wpa_s, bss->we_bssid.wb_bytes); 359 wpa_s->wpa_state = WPA_ASSOCIATING; 360 wpa_s->driver->associate(wpa_s->ifname, 361 (const char *)bss->we_bssid.wb_bytes, wpa_ie, wpa_ie_len); 362 363 /* Timeout for IEEE 802.11 authentication and association */ 364 wpa_supplicant_req_auth_timeout(wpa_s, 15, 0); 365 } 366 367 void 368 wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, int reason_code) 369 { 370 uint8_t *addr = NULL; 371 wpa_s->wpa_state = WPA_DISCONNECTED; 372 if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", 373 IEEE80211_ADDR_LEN) != 0) { 374 wpa_s->driver->disassociate(wpa_s->ifname, reason_code); 375 addr = wpa_s->bssid; 376 } 377 wpa_clear_keys(wpa_s, addr); 378 } 379 380 static dladm_wlan_ess_t * 381 wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, 382 dladm_wlan_ess_t *results, int num, struct wpa_ssid **selected_ssid) 383 { 384 struct wpa_ssid *ssid; 385 dladm_wlan_ess_t *bss, *selected = NULL; 386 int i; 387 388 struct wpa_ie_data ie; 389 390 wpa_printf(MSG_DEBUG, "Selecting BSS from scan results (%d)", num); 391 392 bss = NULL; 393 ssid = NULL; 394 395 /* try to find matched AP */ 396 for (i = 0; i < num && !selected; i++) { 397 bss = &results[i]; 398 wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " 399 "wpa_ie_len=%d", 400 i, MAC2STR(bss->we_bssid.wb_bytes), 401 wpa_ssid_txt(bss->we_ssid.we_bytes, bss->we_ssid_len), 402 bss->we_wpa_ie_len); 403 if (bss->we_wpa_ie_len == 0) { 404 wpa_printf(MSG_DEBUG, " skip - no WPA/RSN IE"); 405 } 406 407 ssid = group; 408 if (bss->we_ssid_len != ssid->ssid_len || 409 memcmp(bss->we_ssid.we_bytes, ssid->ssid, 410 bss->we_ssid_len) != 0) { 411 wpa_printf(MSG_DEBUG, " skip - SSID mismatch"); 412 continue; 413 } 414 if (!((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_WPA)) && 415 wpa_parse_wpa_ie(wpa_s, bss->we_wpa_ie, 416 bss->we_wpa_ie_len, &ie) == 0)) { 417 wpa_printf(MSG_DEBUG, " skip - " 418 "could not parse WPA/RSN IE"); 419 continue; 420 } 421 if (!(ie.proto & ssid->proto)) { 422 wpa_printf(MSG_DEBUG, " skip - proto mismatch"); 423 continue; 424 } 425 if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { 426 wpa_printf(MSG_DEBUG, " skip - PTK cipher mismatch"); 427 continue; 428 } 429 if (!(ie.group_cipher & ssid->group_cipher)) { 430 wpa_printf(MSG_DEBUG, " skip - GTK cipher mismatch"); 431 continue; 432 } 433 if (!(ie.key_mgmt & ssid->key_mgmt)) { 434 wpa_printf(MSG_DEBUG, " skip - key mgmt mismatch"); 435 continue; 436 } 437 438 selected = bss; 439 *selected_ssid = ssid; 440 wpa_printf(MSG_DEBUG, " selected"); 441 } 442 443 return (selected); 444 } 445 446 447 static void 448 wpa_supplicant_scan_results(struct wpa_supplicant *wpa_s) 449 { 450 dladm_wlan_ess_t results[MAX_SCANRESULTS]; 451 int num; 452 dladm_wlan_ess_t *selected = NULL; 453 struct wpa_ssid *ssid; 454 455 (void) memset(results, 0, sizeof (dladm_wlan_ess_t) * MAX_SCANRESULTS); 456 num = wpa_s->driver->get_scan_results(wpa_s->ifname, results, 457 MAX_SCANRESULTS); 458 wpa_printf(MSG_DEBUG, "Scan results: %d", num); 459 if (num < 0) 460 return; 461 if (num > MAX_SCANRESULTS) { 462 wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)", 463 num, MAX_SCANRESULTS); 464 num = MAX_SCANRESULTS; 465 } 466 467 selected = wpa_supplicant_select_bss(wpa_s, 468 wpa_s->conf->ssid, results, num, &ssid); 469 470 if (selected) { 471 if (wpa_s->reassociate || 472 memcmp(selected->we_bssid.wb_bytes, wpa_s->bssid, 473 IEEE80211_ADDR_LEN) != 0) { 474 wpa_supplicant_associate(wpa_s, selected, ssid); 475 } else { 476 wpa_printf(MSG_DEBUG, "Already associated with the " 477 "selected AP."); 478 } 479 } else { 480 wpa_printf(MSG_DEBUG, "No suitable AP found."); 481 wpa_supplicant_req_scan(wpa_s, 5, 0); /* wait 5 seconds */ 482 } 483 } 484 485 /* 486 * wpa_event_handler - report a driver event for wpa_supplicant 487 * @wpa_s: pointer to wpa_supplicant data; this is the @ctx variable registered 488 * with wpa_driver_events_init() 489 * @event: event type (defined above) 490 * 491 * Driver wrapper code should call this function whenever an event is received 492 * from the driver. 493 */ 494 void 495 wpa_event_handler(void *cookie, wpa_event_type event) 496 { 497 struct wpa_supplicant *wpa_s = cookie; 498 uint8_t bssid[IEEE80211_ADDR_LEN]; 499 500 switch (event) { 501 case EVENT_ASSOC: 502 wpa_s->wpa_state = WPA_ASSOCIATED; 503 wpa_printf(MSG_DEBUG, "\nAssociation event - clear replay " 504 "counter\n"); 505 (void) memset(wpa_s->rx_replay_counter, 0, 506 WPA_REPLAY_COUNTER_LEN); 507 wpa_s->rx_replay_counter_set = 0; 508 wpa_s->renew_snonce = 1; 509 if (wpa_s->driver->get_bssid(wpa_s->ifname, 510 (char *)bssid) >= 0 && 511 memcmp(bssid, wpa_s->bssid, IEEE80211_ADDR_LEN) != 0) { 512 wpa_printf(MSG_DEBUG, "Associated to a new BSS: " 513 "BSSID=" MACSTR, MAC2STR(bssid)); 514 (void) memcpy(wpa_s->bssid, bssid, IEEE80211_ADDR_LEN); 515 if (wpa_s->key_mgmt != WPA_KEY_MGMT_NONE) 516 wpa_clear_keys(wpa_s, bssid); 517 } 518 519 wpa_s->eapol_received = 0; 520 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { 521 wpa_supplicant_cancel_auth_timeout(wpa_s); 522 } else { 523 /* Timeout for receiving the first EAPOL packet */ 524 wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); 525 } 526 break; 527 case EVENT_DISASSOC: 528 if (wpa_s->wpa_state >= WPA_ASSOCIATED) 529 wpa_supplicant_req_scan(wpa_s, 0, 100000); 530 wpa_supplicant_mark_disassoc(wpa_s); 531 wpa_printf(MSG_DEBUG, "Disconnect event - remove keys"); 532 if (wpa_s->key_mgmt != WPA_KEY_MGMT_NONE) 533 wpa_clear_keys(wpa_s, wpa_s->bssid); 534 break; 535 case EVENT_SCAN_RESULTS: 536 wpa_supplicant_scan_results(wpa_s); 537 break; 538 default: 539 wpa_printf(MSG_INFO, "Unknown event %d", event); 540 break; 541 } 542 } 543 544 /* ARGSUSED */ 545 static void 546 wpa_supplicant_terminate(int sig, void *eloop_ctx, void *signal_ctx) 547 { 548 wpa_printf(MSG_INFO, "Signal %d received - terminating", sig); 549 eloop_terminate(); 550 } 551 552 static int 553 wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) 554 { 555 wpa_s->l2 = l2_packet_init(wpa_s->ifname, ETHERTYPE_EAPOL, 556 wpa_supplicant_rx_eapol, wpa_s); 557 if (wpa_s->l2 == NULL) 558 return (-1); 559 560 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { 561 (void) fprintf(stderr, "Failed to get own L2 address\n"); 562 return (-1); 563 } 564 565 if (wpa_s->driver->set_wpa(wpa_s->ifname, 1) < 0) { 566 wpa_printf(MSG_ERROR, "Failed to enable WPA in the driver."); 567 return (-1); 568 } 569 570 wpa_clear_keys(wpa_s, NULL); 571 wpa_supplicant_req_scan(wpa_s, 0, 100000); 572 573 return (0); 574 } 575 576 static int door_id = -1; 577 578 /* ARGSUSED */ 579 static void 580 event_handler(void *cookie, char *argp, size_t asize, 581 door_desc_t *dp, uint_t n_desc) 582 { 583 wpa_event_type event; 584 585 event = ((wl_events_t *)argp)->event; 586 wpa_event_handler(cookie, event); 587 588 (void) door_return(NULL, 0, NULL, 0); 589 } 590 591 /* 592 * Create the driver to wpad door 593 */ 594 int 595 wpa_supplicant_door_setup(void *cookie, char *doorname) 596 { 597 struct stat stbuf; 598 int error = 0; 599 600 wpa_printf(MSG_DEBUG, "wpa_supplicant_door_setup(%s)", doorname); 601 /* 602 * Create the door 603 */ 604 door_id = door_create(event_handler, cookie, 605 DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 606 607 if (door_id < 0) { 608 error = -1; 609 goto out; 610 } 611 612 if (stat(doorname, &stbuf) < 0) { 613 int newfd; 614 if ((newfd = creat(doorname, 0666)) < 0) { 615 (void) door_revoke(door_id); 616 door_id = -1; 617 error = -1; 618 619 goto out; 620 } 621 (void) close(newfd); 622 } 623 624 if (fattach(door_id, doorname) < 0) { 625 if ((errno != EBUSY) || (fdetach(doorname) < 0) || 626 (fattach(door_id, doorname) < 0)) { 627 (void) door_revoke(door_id); 628 door_id = -1; 629 error = -1; 630 631 goto out; 632 } 633 } 634 635 out: 636 return (error); 637 } 638 639 void 640 wpa_supplicant_door_destroy(char *doorname) 641 { 642 wpa_printf(MSG_DEBUG, "wpa_supplicant_door_destroy(%s)\n", doorname); 643 644 if (door_revoke(door_id) == -1) { 645 wpa_printf(MSG_ERROR, "failed to door_revoke(%d) %s, exiting.", 646 door_id, strerror(errno)); 647 } 648 649 if (fdetach(doorname) == -1) { 650 wpa_printf(MSG_ERROR, "failed to fdetach %s: %s, exiting.", 651 doorname, strerror(errno)); 652 } 653 654 (void) close(door_id); 655 } 656 657 static int 658 wpa_config_parse_ssid(struct wpa_ssid *ssid, int line, const char *value) 659 { 660 free(ssid->ssid); 661 662 ssid->ssid = (uint8_t *)strdup(value); 663 ssid->ssid_len = strlen(value); 664 665 if (ssid->ssid == NULL) { 666 wpa_printf(MSG_ERROR, "Invalid SSID '%s'.", line, value); 667 return (-1); 668 } 669 if (ssid->ssid_len > MAX_ESSID_LENGTH) { 670 free(ssid->ssid); 671 wpa_printf(MSG_ERROR, "Too long SSID '%s'.", line, value); 672 return (-1); 673 } 674 wpa_printf(MSG_MSGDUMP, "SSID: %s", ssid->ssid); 675 return (0); 676 } 677 678 static struct wpa_ssid * 679 wpa_config_read_network(struct wpa_supplicant *wpa_s) 680 { 681 struct wpa_ssid *ssid; 682 char buf[MAX_ESSID_LENGTH + 1]; 683 dladm_secobj_class_t cl; 684 uint8_t psk[MAX_PSK_LENGTH + 1]; 685 uint_t key_len; 686 687 wpa_printf(MSG_MSGDUMP, "Start of a new network configration"); 688 689 ssid = (struct wpa_ssid *)malloc(sizeof (*ssid)); 690 if (ssid == NULL) 691 return (NULL); 692 (void) memset(ssid, 0, sizeof (*ssid)); 693 694 /* 695 * Set default supported values 696 */ 697 ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN; 698 ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP; 699 ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | 700 WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40; 701 ssid->key_mgmt = WPA_KEY_MGMT_PSK; /* | WPA_KEY_MGMT_IEEE8021X; */ 702 703 (void) memset(buf, 0, MAX_ESSID_LENGTH + 1); 704 wpa_s->driver->get_ssid(wpa_s->ifname, (char *)buf); 705 706 (void) wpa_config_parse_ssid(ssid, 0, buf); 707 708 key_len = sizeof (psk); 709 (void) dladm_get_secobj((const char *)wpa_s->kname, &cl, psk, &key_len, 710 DLADM_OPT_TEMP); 711 psk[key_len] = '\0'; 712 ssid->passphrase = strdup((const char *)psk); 713 714 if (ssid->passphrase) { 715 pbkdf2_sha1(ssid->passphrase, (char *)ssid->ssid, 716 ssid->ssid_len, 4096, ssid->psk, PMK_LEN); 717 wpa_hexdump(MSG_MSGDUMP, "PSK (from passphrase)", 718 ssid->psk, PMK_LEN); 719 ssid->psk_set = 1; 720 } 721 722 if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) { 723 wpa_printf(MSG_ERROR, "WPA-PSK accepted for key " 724 "management, but no PSK configured."); 725 free(ssid); 726 ssid = NULL; 727 } 728 729 return (ssid); 730 } 731 732 struct wpa_config * 733 wpa_config_read(void *arg) 734 { 735 struct wpa_ssid *ssid; 736 struct wpa_config *config; 737 struct wpa_supplicant *wpa_s = arg; 738 739 config = malloc(sizeof (*config)); 740 if (config == NULL) 741 return (NULL); 742 (void) memset(config, 0, sizeof (*config)); 743 config->eapol_version = 1; /* fixed value */ 744 745 wpa_printf(MSG_DEBUG, "Reading configuration parameters from driver\n"); 746 747 ssid = wpa_config_read_network(wpa_s); 748 if (ssid == NULL) { 749 wpa_config_free(config); 750 config = NULL; 751 } else { 752 config->ssid = ssid; 753 } 754 755 return (config); 756 } 757 758 void 759 wpa_config_free(struct wpa_config *config) 760 { 761 struct wpa_ssid *ssid = config->ssid; 762 763 free(ssid->ssid); 764 free(ssid->passphrase); 765 free(ssid); 766 free(config); 767 } 768 769 static int 770 daemon(boolean_t nochdir, boolean_t noclose) 771 { 772 int retv; 773 774 if ((retv = fork()) == -1) 775 return (-1); 776 if (retv != 0) 777 _exit(EXIT_SUCCESS); 778 if (setsid() == -1) 779 return (-1); 780 781 if (!nochdir && chdir("/") == -1) 782 return (-1); 783 784 if (!noclose) { 785 (void) close(0); 786 (void) close(1); 787 (void) close(2); 788 if ((retv = open("/dev/null", O_RDWR)) != -1) { 789 (void) dup2(retv, 1); 790 (void) dup2(retv, 2); 791 } 792 } 793 794 return (0); 795 } 796 797 static void 798 usage(void) 799 { 800 (void) printf("%s\n\n" 801 "usage:\n" 802 " wpa_supplicant [-hv] -i<ifname> -k<keyname>" 803 "\n" 804 "options:\n" 805 " -h = show this help text\n" 806 " -v = show version\n", 807 wpa_supplicant_version); 808 } 809 810 int 811 main(int argc, char *argv[]) 812 { 813 struct wpa_supplicant wpa_s; 814 char *link = NULL; 815 char *key = NULL; 816 int c; 817 int exitcode; 818 char door_file[WPA_STRSIZE]; 819 820 (void) memset(&wpa_s, 0, sizeof (wpa_s)); 821 822 for (;;) { 823 c = getopt(argc, argv, "Dk:hi:v"); 824 if (c < 0) 825 break; 826 switch (c) { 827 case 'D': 828 wpa_debug_level = MSG_DEBUG; 829 break; 830 case 'h': 831 usage(); 832 return (-1); 833 case 'i': 834 link = optarg; 835 break; 836 case 'k': 837 key = optarg; 838 break; 839 case 'v': 840 (void) printf("%s\n", wpa_supplicant_version); 841 return (-1); 842 default: 843 usage(); 844 return (-1); 845 } 846 } 847 848 wpa_s.driver = &wpa_driver_wifi_ops; 849 eloop_init(&wpa_s); 850 /* 851 * key name is required to retrieve PSK value through libwdladm APIs. 852 * key is saved by dladm command by keyname 853 * see dladm. 854 */ 855 if ((link == NULL) || (key == NULL)) { 856 wpa_printf(MSG_ERROR, "\nLink & key is required."); 857 return (-1); 858 } 859 860 if ((strlen(link) >= sizeof (wpa_s.ifname)) || 861 (strlen(key) >= sizeof (wpa_s.kname))) { 862 wpa_printf(MSG_ERROR, "Too long link/key name '%s', '%s'.", 863 link, key); 864 return (-1); 865 } 866 867 (void) strlcpy(wpa_s.ifname, link, sizeof (wpa_s.ifname)); 868 (void) strlcpy(wpa_s.kname, key, sizeof (wpa_s.kname)); 869 870 /* 871 * Setup door file to communicate with driver 872 * Since this is multiple instance service, different instance 873 * has different doors. 874 */ 875 (void) snprintf(door_file, WPA_STRSIZE, "%s_%s", WPA_DOOR, link); 876 877 /* 878 * Setup default WPA/WPA2 configuration 879 * get ESSID and PSK value 880 */ 881 wpa_s.conf = wpa_config_read(&wpa_s); 882 if (wpa_s.conf == NULL || wpa_s.conf->ssid == NULL) { 883 wpa_printf(MSG_ERROR, "\nNo networks (SSID) configured.\n"); 884 return (-1); 885 } 886 887 exitcode = 0; 888 889 if (daemon(0, 0)) { 890 exitcode = -1; 891 goto cleanup; 892 } 893 894 if (wpa_supplicant_door_setup(&wpa_s, door_file) != 0) { 895 wpa_printf(MSG_ERROR, "Failed to setup door(%s)", door_file); 896 exitcode = -1; 897 goto cleanup; 898 } 899 900 wpa_s.renew_snonce = 1; 901 if (wpa_supplicant_driver_init(&wpa_s) < 0) { 902 exitcode = -1; 903 goto cleanup; 904 } 905 906 wpa_printf(MSG_DEBUG, "=> eloop_run"); 907 908 (void) eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL); 909 (void) eloop_register_signal(SIGTERM, wpa_supplicant_terminate, NULL); 910 (void) eloop_register_signal(SIGKILL, wpa_supplicant_terminate, NULL); 911 912 eloop_run(); 913 914 wpa_printf(MSG_DEBUG, "<= eloop_run()"); 915 wpa_supplicant_disassociate(&wpa_s, REASON_DEAUTH_LEAVING); 916 917 cleanup: 918 if (wpa_s.driver->set_wpa(wpa_s.ifname, 0) < 0) { 919 wpa_printf(MSG_ERROR, "Failed to disable WPA in the driver.\n"); 920 } 921 922 wpa_supplicant_door_destroy(door_file); 923 wpa_supplicant_cleanup(&wpa_s); 924 eloop_destroy(); 925 926 return (exitcode); 927 } 928