1 /* 2 * WPA Supplicant - privilege separated driver interface 3 * Copyright (c) 2007-2009, Jouni Malinen <j@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 #include <sys/un.h> 11 12 #include "common.h" 13 #include "driver.h" 14 #include "eloop.h" 15 #include "common/privsep_commands.h" 16 17 18 struct wpa_driver_privsep_data { 19 void *ctx; 20 u8 own_addr[ETH_ALEN]; 21 int priv_socket; 22 char *own_socket_path; 23 int cmd_socket; 24 char *own_cmd_path; 25 struct sockaddr_un priv_addr; 26 char ifname[16]; 27 }; 28 29 30 static int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd) 31 { 32 int res; 33 34 res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0, 35 (struct sockaddr *) &drv->priv_addr, 36 sizeof(drv->priv_addr)); 37 if (res < 0) 38 wpa_printf(MSG_ERROR, "sendto: %s", strerror(errno)); 39 return res < 0 ? -1 : 0; 40 } 41 42 43 static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd, 44 const void *data, size_t data_len, 45 void *reply, size_t *reply_len) 46 { 47 struct msghdr msg; 48 struct iovec io[2]; 49 50 io[0].iov_base = &cmd; 51 io[0].iov_len = sizeof(cmd); 52 io[1].iov_base = (u8 *) data; 53 io[1].iov_len = data_len; 54 55 os_memset(&msg, 0, sizeof(msg)); 56 msg.msg_iov = io; 57 msg.msg_iovlen = data ? 2 : 1; 58 msg.msg_name = &drv->priv_addr; 59 msg.msg_namelen = sizeof(drv->priv_addr); 60 61 if (sendmsg(drv->cmd_socket, &msg, 0) < 0) { 62 wpa_printf(MSG_ERROR, "sendmsg(cmd_socket): %s", 63 strerror(errno)); 64 return -1; 65 } 66 67 if (reply) { 68 fd_set rfds; 69 struct timeval tv; 70 int res; 71 72 FD_ZERO(&rfds); 73 FD_SET(drv->cmd_socket, &rfds); 74 tv.tv_sec = 5; 75 tv.tv_usec = 0; 76 res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv); 77 if (res < 0 && errno != EINTR) { 78 wpa_printf(MSG_ERROR, "select: %s", strerror(errno)); 79 return -1; 80 } 81 82 if (FD_ISSET(drv->cmd_socket, &rfds)) { 83 res = recv(drv->cmd_socket, reply, *reply_len, 0); 84 if (res < 0) { 85 wpa_printf(MSG_ERROR, "recv: %s", 86 strerror(errno)); 87 return -1; 88 } 89 *reply_len = res; 90 } else { 91 wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting " 92 "for reply (cmd=%d)", cmd); 93 return -1; 94 } 95 } 96 97 return 0; 98 } 99 100 101 static int wpa_driver_privsep_scan(void *priv, 102 struct wpa_driver_scan_params *params) 103 { 104 struct wpa_driver_privsep_data *drv = priv; 105 struct privsep_cmd_scan scan; 106 size_t i; 107 108 wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv); 109 os_memset(&scan, 0, sizeof(scan)); 110 scan.num_ssids = params->num_ssids; 111 for (i = 0; i < params->num_ssids; i++) { 112 if (!params->ssids[i].ssid) 113 continue; 114 scan.ssid_lens[i] = params->ssids[i].ssid_len; 115 os_memcpy(scan.ssids[i], params->ssids[i].ssid, 116 scan.ssid_lens[i]); 117 } 118 119 for (i = 0; i < PRIVSEP_MAX_SCAN_FREQS && 120 params->freqs && params->freqs[i]; i++) 121 scan.freqs[i] = params->freqs[i]; 122 scan.num_freqs = i; 123 124 return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, &scan, sizeof(scan), 125 NULL, NULL); 126 } 127 128 129 static struct wpa_scan_results * 130 wpa_driver_privsep_get_scan_results2(void *priv) 131 { 132 struct wpa_driver_privsep_data *drv = priv; 133 int res, num; 134 u8 *buf, *pos, *end; 135 size_t reply_len = 60000; 136 struct wpa_scan_results *results; 137 struct wpa_scan_res *r; 138 139 buf = os_malloc(reply_len); 140 if (buf == NULL) 141 return NULL; 142 res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS, 143 NULL, 0, buf, &reply_len); 144 if (res < 0) { 145 os_free(buf); 146 return NULL; 147 } 148 149 wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results", 150 (unsigned long) reply_len); 151 if (reply_len < sizeof(int)) { 152 wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu", 153 (unsigned long) reply_len); 154 os_free(buf); 155 return NULL; 156 } 157 158 pos = buf; 159 end = buf + reply_len; 160 os_memcpy(&num, pos, sizeof(int)); 161 if (num < 0 || num > 1000) { 162 os_free(buf); 163 return NULL; 164 } 165 pos += sizeof(int); 166 167 results = os_zalloc(sizeof(*results)); 168 if (results == NULL) { 169 os_free(buf); 170 return NULL; 171 } 172 173 results->res = os_calloc(num, sizeof(struct wpa_scan_res *)); 174 if (results->res == NULL) { 175 os_free(results); 176 os_free(buf); 177 return NULL; 178 } 179 180 while (results->num < (size_t) num && end - pos > (int) sizeof(int)) { 181 int len; 182 os_memcpy(&len, pos, sizeof(int)); 183 pos += sizeof(int); 184 if (len < 0 || len > 10000 || len > end - pos) 185 break; 186 187 r = os_memdup(pos, len); 188 if (r == NULL) 189 break; 190 pos += len; 191 if (sizeof(*r) + r->ie_len + r->beacon_ie_len > (size_t) len) { 192 wpa_printf(MSG_ERROR, 193 "privsep: Invalid scan result len (%d + %d + %d > %d)", 194 (int) sizeof(*r), (int) r->ie_len, 195 (int) r->beacon_ie_len, len); 196 os_free(r); 197 break; 198 } 199 200 results->res[results->num++] = r; 201 } 202 203 os_free(buf); 204 return results; 205 } 206 207 208 static int wpa_driver_privsep_set_key(const char *ifname, void *priv, 209 enum wpa_alg alg, const u8 *addr, 210 int key_idx, int set_tx, 211 const u8 *seq, size_t seq_len, 212 const u8 *key, size_t key_len) 213 { 214 struct wpa_driver_privsep_data *drv = priv; 215 struct privsep_cmd_set_key cmd; 216 217 wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d", 218 __func__, priv, alg, key_idx, set_tx); 219 220 os_memset(&cmd, 0, sizeof(cmd)); 221 cmd.alg = alg; 222 if (addr) 223 os_memcpy(cmd.addr, addr, ETH_ALEN); 224 else 225 os_memset(cmd.addr, 0xff, ETH_ALEN); 226 cmd.key_idx = key_idx; 227 cmd.set_tx = set_tx; 228 if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) { 229 os_memcpy(cmd.seq, seq, seq_len); 230 cmd.seq_len = seq_len; 231 } 232 if (key && key_len > 0 && key_len < sizeof(cmd.key)) { 233 os_memcpy(cmd.key, key, key_len); 234 cmd.key_len = key_len; 235 } 236 237 return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd), 238 NULL, NULL); 239 } 240 241 242 static int wpa_driver_privsep_authenticate( 243 void *priv, struct wpa_driver_auth_params *params) 244 { 245 struct wpa_driver_privsep_data *drv = priv; 246 struct privsep_cmd_authenticate *data; 247 int i, res; 248 size_t buflen; 249 u8 *pos; 250 251 wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d bssid=" MACSTR 252 " auth_alg=%d local_state_change=%d p2p=%d", 253 __func__, priv, params->freq, MAC2STR(params->bssid), 254 params->auth_alg, params->local_state_change, params->p2p); 255 256 buflen = sizeof(*data) + params->ie_len + params->auth_data_len; 257 data = os_zalloc(buflen); 258 if (data == NULL) 259 return -1; 260 261 data->freq = params->freq; 262 os_memcpy(data->bssid, params->bssid, ETH_ALEN); 263 os_memcpy(data->ssid, params->ssid, params->ssid_len); 264 data->ssid_len = params->ssid_len; 265 data->auth_alg = params->auth_alg; 266 data->ie_len = params->ie_len; 267 for (i = 0; i < 4; i++) { 268 if (params->wep_key[i]) 269 os_memcpy(data->wep_key[i], params->wep_key[i], 270 params->wep_key_len[i]); 271 data->wep_key_len[i] = params->wep_key_len[i]; 272 } 273 data->wep_tx_keyidx = params->wep_tx_keyidx; 274 data->local_state_change = params->local_state_change; 275 data->p2p = params->p2p; 276 pos = (u8 *) (data + 1); 277 if (params->ie_len) { 278 os_memcpy(pos, params->ie, params->ie_len); 279 pos += params->ie_len; 280 } 281 if (params->auth_data_len) 282 os_memcpy(pos, params->auth_data, params->auth_data_len); 283 284 res = wpa_priv_cmd(drv, PRIVSEP_CMD_AUTHENTICATE, data, buflen, 285 NULL, NULL); 286 os_free(data); 287 288 return res; 289 } 290 291 292 static int wpa_driver_privsep_associate( 293 void *priv, struct wpa_driver_associate_params *params) 294 { 295 struct wpa_driver_privsep_data *drv = priv; 296 struct privsep_cmd_associate *data; 297 int res; 298 size_t buflen; 299 300 wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " 301 "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", 302 __func__, priv, params->freq.freq, params->pairwise_suite, 303 params->group_suite, params->key_mgmt_suite, 304 params->auth_alg, params->mode); 305 306 buflen = sizeof(*data) + params->wpa_ie_len; 307 data = os_zalloc(buflen); 308 if (data == NULL) 309 return -1; 310 311 if (params->bssid) 312 os_memcpy(data->bssid, params->bssid, ETH_ALEN); 313 os_memcpy(data->ssid, params->ssid, params->ssid_len); 314 data->ssid_len = params->ssid_len; 315 data->hwmode = params->freq.mode; 316 data->freq = params->freq.freq; 317 data->channel = params->freq.channel; 318 data->pairwise_suite = params->pairwise_suite; 319 data->group_suite = params->group_suite; 320 data->key_mgmt_suite = params->key_mgmt_suite; 321 data->auth_alg = params->auth_alg; 322 data->mode = params->mode; 323 data->wpa_ie_len = params->wpa_ie_len; 324 if (params->wpa_ie) 325 os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len); 326 /* TODO: add support for other assoc parameters */ 327 328 res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen, 329 NULL, NULL); 330 os_free(data); 331 332 return res; 333 } 334 335 336 static int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid) 337 { 338 struct wpa_driver_privsep_data *drv = priv; 339 int res; 340 size_t len = ETH_ALEN; 341 342 res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len); 343 if (res < 0 || len != ETH_ALEN) 344 return -1; 345 return 0; 346 } 347 348 349 static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid) 350 { 351 struct wpa_driver_privsep_data *drv = priv; 352 int res, ssid_len; 353 u8 reply[sizeof(int) + SSID_MAX_LEN]; 354 size_t len = sizeof(reply); 355 356 res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len); 357 if (res < 0 || len < sizeof(int)) 358 return -1; 359 os_memcpy(&ssid_len, reply, sizeof(int)); 360 if (ssid_len < 0 || ssid_len > SSID_MAX_LEN || 361 sizeof(int) + ssid_len > len) { 362 wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply"); 363 return -1; 364 } 365 os_memcpy(ssid, &reply[sizeof(int)], ssid_len); 366 return ssid_len; 367 } 368 369 370 static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr, 371 int reason_code) 372 { 373 //struct wpa_driver_privsep_data *drv = priv; 374 wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", 375 __func__, MAC2STR(addr), reason_code); 376 wpa_printf(MSG_DEBUG, "%s - TODO", __func__); 377 return 0; 378 } 379 380 381 static void wpa_driver_privsep_event_auth(void *ctx, u8 *buf, size_t len) 382 { 383 union wpa_event_data data; 384 struct privsep_event_auth *auth; 385 386 os_memset(&data, 0, sizeof(data)); 387 if (len < sizeof(*auth)) 388 return; 389 auth = (struct privsep_event_auth *) buf; 390 if (len < sizeof(*auth) + auth->ies_len) 391 return; 392 393 os_memcpy(data.auth.peer, auth->peer, ETH_ALEN); 394 os_memcpy(data.auth.bssid, auth->bssid, ETH_ALEN); 395 data.auth.auth_type = auth->auth_type; 396 data.auth.auth_transaction = auth->auth_transaction; 397 data.auth.status_code = auth->status_code; 398 if (auth->ies_len) { 399 data.auth.ies = (u8 *) (auth + 1); 400 data.auth.ies_len = auth->ies_len; 401 } 402 403 wpa_supplicant_event(ctx, EVENT_AUTH, &data); 404 } 405 406 407 static void wpa_driver_privsep_event_assoc(void *ctx, 408 enum wpa_event_type event, 409 u8 *buf, size_t len) 410 { 411 union wpa_event_data data; 412 int inc_data = 0; 413 u8 *pos, *end; 414 int ie_len; 415 416 os_memset(&data, 0, sizeof(data)); 417 418 pos = buf; 419 end = buf + len; 420 421 if (end - pos < (int) sizeof(int)) 422 return; 423 os_memcpy(&ie_len, pos, sizeof(int)); 424 pos += sizeof(int); 425 if (ie_len < 0 || ie_len > end - pos) 426 return; 427 if (ie_len) { 428 data.assoc_info.req_ies = pos; 429 data.assoc_info.req_ies_len = ie_len; 430 pos += ie_len; 431 inc_data = 1; 432 } 433 434 wpa_supplicant_event(ctx, event, inc_data ? &data : NULL); 435 } 436 437 438 static void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf, 439 size_t len) 440 { 441 union wpa_event_data data; 442 int ievent; 443 444 if (len < sizeof(int) || 445 len - sizeof(int) > sizeof(data.interface_status.ifname)) 446 return; 447 448 os_memcpy(&ievent, buf, sizeof(int)); 449 450 os_memset(&data, 0, sizeof(data)); 451 data.interface_status.ievent = ievent; 452 os_memcpy(data.interface_status.ifname, buf + sizeof(int), 453 len - sizeof(int)); 454 wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data); 455 } 456 457 458 static void wpa_driver_privsep_event_michael_mic_failure( 459 void *ctx, u8 *buf, size_t len) 460 { 461 union wpa_event_data data; 462 463 if (len != sizeof(int)) 464 return; 465 466 os_memset(&data, 0, sizeof(data)); 467 os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int)); 468 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 469 } 470 471 472 static void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf, 473 size_t len) 474 { 475 union wpa_event_data data; 476 477 if (len != sizeof(struct pmkid_candidate)) 478 return; 479 480 os_memset(&data, 0, sizeof(data)); 481 os_memcpy(&data.pmkid_candidate, buf, len); 482 wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data); 483 } 484 485 486 static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf, 487 size_t len) 488 { 489 union wpa_event_data data; 490 491 if (len < sizeof(int) + ETH_ALEN) 492 return; 493 494 os_memset(&data, 0, sizeof(data)); 495 os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int)); 496 os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN); 497 data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN; 498 data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN; 499 wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data); 500 } 501 502 503 static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len) 504 { 505 if (len < ETH_ALEN) 506 return; 507 drv_event_eapol_rx(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN); 508 } 509 510 511 static void wpa_driver_privsep_receive(int sock, void *eloop_ctx, 512 void *sock_ctx) 513 { 514 struct wpa_driver_privsep_data *drv = eloop_ctx; 515 u8 *buf, *event_buf; 516 size_t event_len; 517 int res, event; 518 enum privsep_event e; 519 struct sockaddr_un from; 520 socklen_t fromlen = sizeof(from); 521 const size_t buflen = 2000; 522 523 buf = os_malloc(buflen); 524 if (buf == NULL) 525 return; 526 res = recvfrom(sock, buf, buflen, 0, 527 (struct sockaddr *) &from, &fromlen); 528 if (res < 0) { 529 wpa_printf(MSG_ERROR, "recvfrom(priv_socket): %s", 530 strerror(errno)); 531 os_free(buf); 532 return; 533 } 534 535 wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res); 536 537 if (res < (int) sizeof(int)) { 538 wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res); 539 return; 540 } 541 542 os_memcpy(&event, buf, sizeof(int)); 543 event_buf = &buf[sizeof(int)]; 544 event_len = res - sizeof(int); 545 wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)", 546 event, (unsigned long) event_len); 547 548 e = event; 549 switch (e) { 550 case PRIVSEP_EVENT_SCAN_RESULTS: 551 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL); 552 break; 553 case PRIVSEP_EVENT_SCAN_STARTED: 554 wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL); 555 break; 556 case PRIVSEP_EVENT_ASSOC: 557 wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC, 558 event_buf, event_len); 559 break; 560 case PRIVSEP_EVENT_DISASSOC: 561 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); 562 break; 563 case PRIVSEP_EVENT_ASSOCINFO: 564 wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO, 565 event_buf, event_len); 566 break; 567 case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE: 568 wpa_driver_privsep_event_michael_mic_failure( 569 drv->ctx, event_buf, event_len); 570 break; 571 case PRIVSEP_EVENT_INTERFACE_STATUS: 572 wpa_driver_privsep_event_interface_status(drv->ctx, event_buf, 573 event_len); 574 break; 575 case PRIVSEP_EVENT_PMKID_CANDIDATE: 576 wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf, 577 event_len); 578 break; 579 case PRIVSEP_EVENT_FT_RESPONSE: 580 wpa_driver_privsep_event_ft_response(drv->ctx, event_buf, 581 event_len); 582 break; 583 case PRIVSEP_EVENT_RX_EAPOL: 584 wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf, 585 event_len); 586 break; 587 case PRIVSEP_EVENT_AUTH: 588 wpa_driver_privsep_event_auth(drv->ctx, event_buf, event_len); 589 break; 590 } 591 592 os_free(buf); 593 } 594 595 596 static void * wpa_driver_privsep_init(void *ctx, const char *ifname) 597 { 598 struct wpa_driver_privsep_data *drv; 599 600 drv = os_zalloc(sizeof(*drv)); 601 if (drv == NULL) 602 return NULL; 603 drv->ctx = ctx; 604 drv->priv_socket = -1; 605 drv->cmd_socket = -1; 606 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); 607 608 return drv; 609 } 610 611 612 static void wpa_driver_privsep_deinit(void *priv) 613 { 614 struct wpa_driver_privsep_data *drv = priv; 615 616 if (drv->priv_socket >= 0) { 617 wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER); 618 eloop_unregister_read_sock(drv->priv_socket); 619 close(drv->priv_socket); 620 } 621 622 if (drv->own_socket_path) { 623 unlink(drv->own_socket_path); 624 os_free(drv->own_socket_path); 625 } 626 627 if (drv->cmd_socket >= 0) { 628 eloop_unregister_read_sock(drv->cmd_socket); 629 close(drv->cmd_socket); 630 } 631 632 if (drv->own_cmd_path) { 633 unlink(drv->own_cmd_path); 634 os_free(drv->own_cmd_path); 635 } 636 637 os_free(drv); 638 } 639 640 641 static int wpa_driver_privsep_set_param(void *priv, const char *param) 642 { 643 struct wpa_driver_privsep_data *drv = priv; 644 const char *pos; 645 char *own_dir, *priv_dir; 646 static unsigned int counter = 0; 647 size_t len; 648 struct sockaddr_un addr; 649 650 wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); 651 if (param == NULL) 652 pos = NULL; 653 else 654 pos = os_strstr(param, "own_dir="); 655 if (pos) { 656 char *end; 657 own_dir = os_strdup(pos + 8); 658 if (own_dir == NULL) 659 return -1; 660 end = os_strchr(own_dir, ' '); 661 if (end) 662 *end = '\0'; 663 } else { 664 own_dir = os_strdup("/tmp"); 665 if (own_dir == NULL) 666 return -1; 667 } 668 669 if (param == NULL) 670 pos = NULL; 671 else 672 pos = os_strstr(param, "priv_dir="); 673 if (pos) { 674 char *end; 675 priv_dir = os_strdup(pos + 9); 676 if (priv_dir == NULL) { 677 os_free(own_dir); 678 return -1; 679 } 680 end = os_strchr(priv_dir, ' '); 681 if (end) 682 *end = '\0'; 683 } else { 684 priv_dir = os_strdup("/var/run/wpa_priv"); 685 if (priv_dir == NULL) { 686 os_free(own_dir); 687 return -1; 688 } 689 } 690 691 len = os_strlen(own_dir) + 50; 692 drv->own_socket_path = os_malloc(len); 693 if (drv->own_socket_path == NULL) { 694 os_free(priv_dir); 695 os_free(own_dir); 696 return -1; 697 } 698 os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d", 699 own_dir, getpid(), counter++); 700 701 len = os_strlen(own_dir) + 50; 702 drv->own_cmd_path = os_malloc(len); 703 if (drv->own_cmd_path == NULL) { 704 os_free(drv->own_socket_path); 705 drv->own_socket_path = NULL; 706 os_free(priv_dir); 707 os_free(own_dir); 708 return -1; 709 } 710 os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d", 711 own_dir, getpid(), counter++); 712 713 os_free(own_dir); 714 715 drv->priv_addr.sun_family = AF_UNIX; 716 os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path), 717 "%s/%s", priv_dir, drv->ifname); 718 os_free(priv_dir); 719 720 drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0); 721 if (drv->priv_socket < 0) { 722 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 723 os_free(drv->own_socket_path); 724 drv->own_socket_path = NULL; 725 return -1; 726 } 727 728 os_memset(&addr, 0, sizeof(addr)); 729 addr.sun_family = AF_UNIX; 730 os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path)); 731 if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) < 732 0) { 733 wpa_printf(MSG_ERROR, 734 "privsep-set-params priv-sock: bind(PF_UNIX): %s", 735 strerror(errno)); 736 close(drv->priv_socket); 737 drv->priv_socket = -1; 738 unlink(drv->own_socket_path); 739 os_free(drv->own_socket_path); 740 drv->own_socket_path = NULL; 741 return -1; 742 } 743 744 eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive, 745 drv, NULL); 746 747 drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0); 748 if (drv->cmd_socket < 0) { 749 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 750 os_free(drv->own_cmd_path); 751 drv->own_cmd_path = NULL; 752 return -1; 753 } 754 755 os_memset(&addr, 0, sizeof(addr)); 756 addr.sun_family = AF_UNIX; 757 os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path)); 758 if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) 759 { 760 wpa_printf(MSG_ERROR, 761 "privsep-set-params cmd-sock: bind(PF_UNIX): %s", 762 strerror(errno)); 763 close(drv->cmd_socket); 764 drv->cmd_socket = -1; 765 unlink(drv->own_cmd_path); 766 os_free(drv->own_cmd_path); 767 drv->own_cmd_path = NULL; 768 return -1; 769 } 770 771 if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) { 772 wpa_printf(MSG_ERROR, "Failed to register with wpa_priv"); 773 return -1; 774 } 775 776 return 0; 777 } 778 779 780 static int wpa_driver_privsep_get_capa(void *priv, 781 struct wpa_driver_capa *capa) 782 { 783 struct wpa_driver_privsep_data *drv = priv; 784 int res; 785 size_t len = sizeof(*capa); 786 787 res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len); 788 if (res < 0 || len != sizeof(*capa)) 789 return -1; 790 /* For now, no support for passing extended_capa pointers */ 791 capa->extended_capa = NULL; 792 capa->extended_capa_mask = NULL; 793 capa->extended_capa_len = 0; 794 return 0; 795 } 796 797 798 static const u8 * wpa_driver_privsep_get_mac_addr(void *priv) 799 { 800 struct wpa_driver_privsep_data *drv = priv; 801 wpa_printf(MSG_DEBUG, "%s", __func__); 802 return drv->own_addr; 803 } 804 805 806 static int wpa_driver_privsep_set_country(void *priv, const char *alpha2) 807 { 808 struct wpa_driver_privsep_data *drv = priv; 809 wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2); 810 return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2, 811 os_strlen(alpha2), NULL, NULL); 812 } 813 814 815 struct wpa_driver_ops wpa_driver_privsep_ops = { 816 "privsep", 817 "wpa_supplicant privilege separated driver", 818 .get_bssid = wpa_driver_privsep_get_bssid, 819 .get_ssid = wpa_driver_privsep_get_ssid, 820 .set_key = wpa_driver_privsep_set_key, 821 .init = wpa_driver_privsep_init, 822 .deinit = wpa_driver_privsep_deinit, 823 .set_param = wpa_driver_privsep_set_param, 824 .scan2 = wpa_driver_privsep_scan, 825 .deauthenticate = wpa_driver_privsep_deauthenticate, 826 .authenticate = wpa_driver_privsep_authenticate, 827 .associate = wpa_driver_privsep_associate, 828 .get_capa = wpa_driver_privsep_get_capa, 829 .get_mac_addr = wpa_driver_privsep_get_mac_addr, 830 .get_scan_results2 = wpa_driver_privsep_get_scan_results2, 831 .set_country = wpa_driver_privsep_set_country, 832 }; 833 834 835 const struct wpa_driver_ops *const wpa_drivers[] = 836 { 837 &wpa_driver_privsep_ops, 838 NULL 839 }; 840