$search
00001 /* 00002 * WPA Supplicant / dbus-based control interface 00003 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #include <dbus/dbus.h> 00017 00018 #include "common.h" 00019 #include "eap_peer/eap_methods.h" 00020 #include "common/ieee802_11_defs.h" 00021 #include "eapol_supp/eapol_supp_sm.h" 00022 #include "rsn_supp/wpa.h" 00023 #include "../config.h" 00024 #include "../wpa_supplicant_i.h" 00025 #include "../driver_i.h" 00026 #include "../notify.h" 00027 #include "../wpas_glue.h" 00028 #include "../bss.h" 00029 #include "../scan.h" 00030 #include "dbus_old.h" 00031 #include "dbus_old_handlers.h" 00032 #include "dbus_dict_helpers.h" 00033 00034 extern int wpa_debug_level; 00035 extern int wpa_debug_show_keys; 00036 extern int wpa_debug_timestamp; 00037 00045 DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message, 00046 const char *arg) 00047 { 00048 DBusMessage *reply; 00049 00050 reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS, 00051 "Did not receive correct message " 00052 "arguments."); 00053 if (arg != NULL) 00054 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg, 00055 DBUS_TYPE_INVALID); 00056 00057 return reply; 00058 } 00059 00060 00069 DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message) 00070 { 00071 DBusMessage *reply; 00072 unsigned int success = 1; 00073 00074 reply = dbus_message_new_method_return(message); 00075 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success, 00076 DBUS_TYPE_INVALID); 00077 return reply; 00078 } 00079 00080 00092 DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message, 00093 struct wpa_global *global) 00094 { 00095 char *ifname = NULL; 00096 char *driver = NULL; 00097 char *driver_param = NULL; 00098 char *confname = NULL; 00099 char *bridge_ifname = NULL; 00100 DBusMessage *reply = NULL; 00101 DBusMessageIter iter; 00102 00103 dbus_message_iter_init(message, &iter); 00104 00105 /* First argument: interface name (DBUS_TYPE_STRING) 00106 * Required; must be non-zero length 00107 */ 00108 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 00109 goto error; 00110 dbus_message_iter_get_basic(&iter, &ifname); 00111 if (!os_strlen(ifname)) 00112 goto error; 00113 00114 /* Second argument: dict of options */ 00115 if (dbus_message_iter_next(&iter)) { 00116 DBusMessageIter iter_dict; 00117 struct wpa_dbus_dict_entry entry; 00118 00119 if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) 00120 goto error; 00121 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 00122 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 00123 goto error; 00124 if (!strcmp(entry.key, "driver") && 00125 (entry.type == DBUS_TYPE_STRING)) { 00126 driver = os_strdup(entry.str_value); 00127 wpa_dbus_dict_entry_clear(&entry); 00128 if (driver == NULL) 00129 goto error; 00130 } else if (!strcmp(entry.key, "driver-params") && 00131 (entry.type == DBUS_TYPE_STRING)) { 00132 driver_param = os_strdup(entry.str_value); 00133 wpa_dbus_dict_entry_clear(&entry); 00134 if (driver_param == NULL) 00135 goto error; 00136 } else if (!strcmp(entry.key, "config-file") && 00137 (entry.type == DBUS_TYPE_STRING)) { 00138 confname = os_strdup(entry.str_value); 00139 wpa_dbus_dict_entry_clear(&entry); 00140 if (confname == NULL) 00141 goto error; 00142 } else if (!strcmp(entry.key, "bridge-ifname") && 00143 (entry.type == DBUS_TYPE_STRING)) { 00144 bridge_ifname = os_strdup(entry.str_value); 00145 wpa_dbus_dict_entry_clear(&entry); 00146 if (bridge_ifname == NULL) 00147 goto error; 00148 } else { 00149 wpa_dbus_dict_entry_clear(&entry); 00150 goto error; 00151 } 00152 } 00153 } 00154 00155 /* 00156 * Try to get the wpa_supplicant record for this iface, return 00157 * an error if we already control it. 00158 */ 00159 if (wpa_supplicant_get_iface(global, ifname) != NULL) { 00160 reply = dbus_message_new_error(message, 00161 WPAS_ERROR_EXISTS_ERROR, 00162 "wpa_supplicant already " 00163 "controls this interface."); 00164 } else { 00165 struct wpa_supplicant *wpa_s; 00166 struct wpa_interface iface; 00167 os_memset(&iface, 0, sizeof(iface)); 00168 iface.ifname = ifname; 00169 iface.driver = driver; 00170 iface.driver_param = driver_param; 00171 iface.confname = confname; 00172 iface.bridge_ifname = bridge_ifname; 00173 /* Otherwise, have wpa_supplicant attach to it. */ 00174 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) { 00175 const char *path = wpa_s->dbus_path; 00176 reply = dbus_message_new_method_return(message); 00177 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 00178 &path, DBUS_TYPE_INVALID); 00179 } else { 00180 reply = dbus_message_new_error(message, 00181 WPAS_ERROR_ADD_ERROR, 00182 "wpa_supplicant " 00183 "couldn't grab this " 00184 "interface."); 00185 } 00186 } 00187 00188 out: 00189 os_free(driver); 00190 os_free(driver_param); 00191 os_free(confname); 00192 os_free(bridge_ifname); 00193 return reply; 00194 00195 error: 00196 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 00197 goto out; 00198 } 00199 00200 00212 DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message, 00213 struct wpa_global *global) 00214 { 00215 struct wpa_supplicant *wpa_s; 00216 char *path; 00217 DBusMessage *reply = NULL; 00218 00219 if (!dbus_message_get_args(message, NULL, 00220 DBUS_TYPE_OBJECT_PATH, &path, 00221 DBUS_TYPE_INVALID)) { 00222 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 00223 goto out; 00224 } 00225 00226 wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path); 00227 if (wpa_s == NULL) { 00228 reply = wpas_dbus_new_invalid_iface_error(message); 00229 goto out; 00230 } 00231 00232 if (!wpa_supplicant_remove_iface(global, wpa_s)) { 00233 reply = wpas_dbus_new_success_reply(message); 00234 } else { 00235 reply = dbus_message_new_error(message, 00236 WPAS_ERROR_REMOVE_ERROR, 00237 "wpa_supplicant couldn't " 00238 "remove this interface."); 00239 } 00240 00241 out: 00242 return reply; 00243 } 00244 00245 00256 DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message, 00257 struct wpa_global *global) 00258 { 00259 DBusMessage *reply = NULL; 00260 const char *ifname; 00261 const char *path; 00262 struct wpa_supplicant *wpa_s; 00263 00264 if (!dbus_message_get_args(message, NULL, 00265 DBUS_TYPE_STRING, &ifname, 00266 DBUS_TYPE_INVALID)) { 00267 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 00268 goto out; 00269 } 00270 00271 wpa_s = wpa_supplicant_get_iface(global, ifname); 00272 if (wpa_s == NULL) { 00273 reply = wpas_dbus_new_invalid_iface_error(message); 00274 goto out; 00275 } 00276 00277 path = wpa_s->dbus_path; 00278 reply = dbus_message_new_method_return(message); 00279 dbus_message_append_args(reply, 00280 DBUS_TYPE_OBJECT_PATH, &path, 00281 DBUS_TYPE_INVALID); 00282 00283 out: 00284 return reply; 00285 } 00286 00287 00298 DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message, 00299 struct wpa_global *global) 00300 { 00301 DBusMessage *reply = NULL; 00302 int debug_level; 00303 dbus_bool_t debug_timestamp; 00304 dbus_bool_t debug_show_keys; 00305 00306 if (!dbus_message_get_args(message, NULL, 00307 DBUS_TYPE_INT32, &debug_level, 00308 DBUS_TYPE_BOOLEAN, &debug_timestamp, 00309 DBUS_TYPE_BOOLEAN, &debug_show_keys, 00310 DBUS_TYPE_INVALID)) { 00311 return wpas_dbus_new_invalid_opts_error(message, NULL); 00312 } 00313 00314 if (wpa_supplicant_set_debug_params(global, debug_level, 00315 debug_timestamp ? 1 : 0, 00316 debug_show_keys ? 1 : 0)) { 00317 return wpas_dbus_new_invalid_opts_error(message, NULL); 00318 } 00319 00320 reply = wpas_dbus_new_success_reply(message); 00321 00322 return reply; 00323 } 00324 00325 00337 DBusMessage * wpas_dbus_iface_scan(DBusMessage *message, 00338 struct wpa_supplicant *wpa_s) 00339 { 00340 wpa_s->scan_req = 2; 00341 wpa_supplicant_req_scan(wpa_s, 0, 0); 00342 return wpas_dbus_new_success_reply(message); 00343 } 00344 00345 00356 DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message, 00357 struct wpa_supplicant *wpa_s) 00358 { 00359 DBusMessage *reply = NULL; 00360 DBusMessageIter iter; 00361 DBusMessageIter sub_iter; 00362 struct wpa_bss *bss; 00363 00364 /* Create and initialize the return message */ 00365 reply = dbus_message_new_method_return(message); 00366 dbus_message_iter_init_append(reply, &iter); 00367 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 00368 DBUS_TYPE_OBJECT_PATH_AS_STRING, 00369 &sub_iter); 00370 00371 /* Loop through scan results and append each result's object path */ 00372 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 00373 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX]; 00374 char *path = path_buf; 00375 00376 /* Construct the object path for this network. Note that ':' 00377 * is not a valid character in dbus object paths. 00378 */ 00379 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 00380 "%s/" WPAS_DBUS_BSSIDS_PART "/" 00381 WPAS_DBUS_BSSID_FORMAT, 00382 wpa_s->dbus_path, MAC2STR(bss->bssid)); 00383 dbus_message_iter_append_basic(&sub_iter, 00384 DBUS_TYPE_OBJECT_PATH, &path); 00385 } 00386 00387 dbus_message_iter_close_container(&iter, &sub_iter); 00388 00389 return reply; 00390 } 00391 00392 00403 DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message, 00404 struct wpa_supplicant *wpa_s, 00405 struct wpa_bss *bss) 00406 { 00407 DBusMessage *reply; 00408 DBusMessageIter iter, iter_dict; 00409 const u8 *ie; 00410 00411 /* Dump the properties into a dbus message */ 00412 reply = dbus_message_new_method_return(message); 00413 00414 dbus_message_iter_init_append(reply, &iter); 00415 if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 00416 goto error; 00417 00418 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid", 00419 (const char *) bss->bssid, 00420 ETH_ALEN)) 00421 goto error; 00422 00423 ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); 00424 if (ie) { 00425 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid", 00426 (const char *) (ie + 2), 00427 ie[1])) 00428 goto error; 00429 } 00430 00431 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 00432 if (ie) { 00433 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie", 00434 (const char *) ie, 00435 ie[1] + 2)) 00436 goto error; 00437 } 00438 00439 ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); 00440 if (ie) { 00441 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie", 00442 (const char *) ie, 00443 ie[1] + 2)) 00444 goto error; 00445 } 00446 00447 ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE); 00448 if (ie) { 00449 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie", 00450 (const char *) ie, 00451 ie[1] + 2)) 00452 goto error; 00453 } 00454 00455 if (bss->freq) { 00456 if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency", 00457 bss->freq)) 00458 goto error; 00459 } 00460 if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities", 00461 bss->caps)) 00462 goto error; 00463 if (!(bss->flags & WPA_BSS_QUAL_INVALID) && 00464 !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual)) 00465 goto error; 00466 if (!(bss->flags & WPA_BSS_NOISE_INVALID) && 00467 !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise)) 00468 goto error; 00469 if (!(bss->flags & WPA_BSS_LEVEL_INVALID) && 00470 !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level)) 00471 goto error; 00472 if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", 00473 wpa_bss_get_max_rate(bss) * 500000)) 00474 goto error; 00475 00476 if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 00477 goto error; 00478 00479 return reply; 00480 00481 error: 00482 if (reply) 00483 dbus_message_unref(reply); 00484 return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 00485 "an internal error occurred returning " 00486 "BSSID properties."); 00487 } 00488 00489 00498 DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message, 00499 struct wpa_supplicant *wpa_s) 00500 { 00501 DBusMessage *reply = NULL; 00502 struct wpa_driver_capa capa; 00503 int res; 00504 DBusMessageIter iter, iter_dict; 00505 char **eap_methods; 00506 size_t num_items; 00507 dbus_bool_t strict = FALSE; 00508 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; 00509 00510 if (!dbus_message_get_args(message, NULL, 00511 DBUS_TYPE_BOOLEAN, &strict, 00512 DBUS_TYPE_INVALID)) 00513 strict = FALSE; 00514 00515 reply = dbus_message_new_method_return(message); 00516 00517 dbus_message_iter_init_append(reply, &iter); 00518 if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 00519 goto error; 00520 00521 /* EAP methods */ 00522 eap_methods = eap_get_names_as_string_array(&num_items); 00523 if (eap_methods) { 00524 dbus_bool_t success = FALSE; 00525 size_t i = 0; 00526 00527 success = wpa_dbus_dict_append_string_array( 00528 &iter_dict, "eap", (const char **) eap_methods, 00529 num_items); 00530 00531 /* free returned method array */ 00532 while (eap_methods[i]) 00533 os_free(eap_methods[i++]); 00534 os_free(eap_methods); 00535 00536 if (!success) 00537 goto error; 00538 } 00539 00540 res = wpa_drv_get_capa(wpa_s, &capa); 00541 00542 /***** pairwise cipher */ 00543 if (res < 0) { 00544 if (!strict) { 00545 const char *args[] = {"CCMP", "TKIP", "NONE"}; 00546 if (!wpa_dbus_dict_append_string_array( 00547 &iter_dict, "pairwise", args, 00548 sizeof(args) / sizeof(char*))) 00549 goto error; 00550 } 00551 } else { 00552 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise", 00553 &iter_dict_entry, 00554 &iter_dict_val, 00555 &iter_array)) 00556 goto error; 00557 00558 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 00559 if (!wpa_dbus_dict_string_array_add_element( 00560 &iter_array, "CCMP")) 00561 goto error; 00562 } 00563 00564 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 00565 if (!wpa_dbus_dict_string_array_add_element( 00566 &iter_array, "TKIP")) 00567 goto error; 00568 } 00569 00570 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 00571 if (!wpa_dbus_dict_string_array_add_element( 00572 &iter_array, "NONE")) 00573 goto error; 00574 } 00575 00576 if (!wpa_dbus_dict_end_string_array(&iter_dict, 00577 &iter_dict_entry, 00578 &iter_dict_val, 00579 &iter_array)) 00580 goto error; 00581 } 00582 00583 /***** group cipher */ 00584 if (res < 0) { 00585 if (!strict) { 00586 const char *args[] = { 00587 "CCMP", "TKIP", "WEP104", "WEP40" 00588 }; 00589 if (!wpa_dbus_dict_append_string_array( 00590 &iter_dict, "group", args, 00591 sizeof(args) / sizeof(char*))) 00592 goto error; 00593 } 00594 } else { 00595 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group", 00596 &iter_dict_entry, 00597 &iter_dict_val, 00598 &iter_array)) 00599 goto error; 00600 00601 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 00602 if (!wpa_dbus_dict_string_array_add_element( 00603 &iter_array, "CCMP")) 00604 goto error; 00605 } 00606 00607 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 00608 if (!wpa_dbus_dict_string_array_add_element( 00609 &iter_array, "TKIP")) 00610 goto error; 00611 } 00612 00613 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 00614 if (!wpa_dbus_dict_string_array_add_element( 00615 &iter_array, "WEP104")) 00616 goto error; 00617 } 00618 00619 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 00620 if (!wpa_dbus_dict_string_array_add_element( 00621 &iter_array, "WEP40")) 00622 goto error; 00623 } 00624 00625 if (!wpa_dbus_dict_end_string_array(&iter_dict, 00626 &iter_dict_entry, 00627 &iter_dict_val, 00628 &iter_array)) 00629 goto error; 00630 } 00631 00632 /***** key management */ 00633 if (res < 0) { 00634 if (!strict) { 00635 const char *args[] = { 00636 "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE", 00637 "NONE" 00638 }; 00639 if (!wpa_dbus_dict_append_string_array( 00640 &iter_dict, "key_mgmt", args, 00641 sizeof(args) / sizeof(char*))) 00642 goto error; 00643 } 00644 } else { 00645 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt", 00646 &iter_dict_entry, 00647 &iter_dict_val, 00648 &iter_array)) 00649 goto error; 00650 00651 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 00652 "NONE")) 00653 goto error; 00654 00655 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 00656 "IEEE8021X")) 00657 goto error; 00658 00659 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 00660 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 00661 if (!wpa_dbus_dict_string_array_add_element( 00662 &iter_array, "WPA-EAP")) 00663 goto error; 00664 } 00665 00666 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 00667 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 00668 if (!wpa_dbus_dict_string_array_add_element( 00669 &iter_array, "WPA-PSK")) 00670 goto error; 00671 } 00672 00673 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 00674 if (!wpa_dbus_dict_string_array_add_element( 00675 &iter_array, "WPA-NONE")) 00676 goto error; 00677 } 00678 00679 if (!wpa_dbus_dict_end_string_array(&iter_dict, 00680 &iter_dict_entry, 00681 &iter_dict_val, 00682 &iter_array)) 00683 goto error; 00684 } 00685 00686 /***** WPA protocol */ 00687 if (res < 0) { 00688 if (!strict) { 00689 const char *args[] = { "RSN", "WPA" }; 00690 if (!wpa_dbus_dict_append_string_array( 00691 &iter_dict, "proto", args, 00692 sizeof(args) / sizeof(char*))) 00693 goto error; 00694 } 00695 } else { 00696 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto", 00697 &iter_dict_entry, 00698 &iter_dict_val, 00699 &iter_array)) 00700 goto error; 00701 00702 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 00703 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 00704 if (!wpa_dbus_dict_string_array_add_element( 00705 &iter_array, "RSN")) 00706 goto error; 00707 } 00708 00709 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 00710 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 00711 if (!wpa_dbus_dict_string_array_add_element( 00712 &iter_array, "WPA")) 00713 goto error; 00714 } 00715 00716 if (!wpa_dbus_dict_end_string_array(&iter_dict, 00717 &iter_dict_entry, 00718 &iter_dict_val, 00719 &iter_array)) 00720 goto error; 00721 } 00722 00723 /***** auth alg */ 00724 if (res < 0) { 00725 if (!strict) { 00726 const char *args[] = { "OPEN", "SHARED", "LEAP" }; 00727 if (!wpa_dbus_dict_append_string_array( 00728 &iter_dict, "auth_alg", args, 00729 sizeof(args) / sizeof(char*))) 00730 goto error; 00731 } 00732 } else { 00733 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg", 00734 &iter_dict_entry, 00735 &iter_dict_val, 00736 &iter_array)) 00737 goto error; 00738 00739 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 00740 if (!wpa_dbus_dict_string_array_add_element( 00741 &iter_array, "OPEN")) 00742 goto error; 00743 } 00744 00745 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 00746 if (!wpa_dbus_dict_string_array_add_element( 00747 &iter_array, "SHARED")) 00748 goto error; 00749 } 00750 00751 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 00752 if (!wpa_dbus_dict_string_array_add_element( 00753 &iter_array, "LEAP")) 00754 goto error; 00755 } 00756 00757 if (!wpa_dbus_dict_end_string_array(&iter_dict, 00758 &iter_dict_entry, 00759 &iter_dict_val, 00760 &iter_array)) 00761 goto error; 00762 } 00763 00764 if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 00765 goto error; 00766 00767 return reply; 00768 00769 error: 00770 if (reply) 00771 dbus_message_unref(reply); 00772 return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 00773 "an internal error occurred returning " 00774 "interface capabilities."); 00775 } 00776 00777 00786 DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message, 00787 struct wpa_supplicant *wpa_s) 00788 { 00789 DBusMessage *reply = NULL; 00790 struct wpa_ssid *ssid; 00791 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 00792 00793 ssid = wpa_config_add_network(wpa_s->conf); 00794 if (ssid == NULL) { 00795 reply = dbus_message_new_error(message, 00796 WPAS_ERROR_ADD_NETWORK_ERROR, 00797 "wpa_supplicant could not add " 00798 "a network on this interface."); 00799 goto out; 00800 } 00801 wpas_notify_network_added(wpa_s, ssid); 00802 ssid->disabled = 1; 00803 wpa_config_set_network_defaults(ssid); 00804 00805 /* Construct the object path for this network. */ 00806 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 00807 "%s/" WPAS_DBUS_NETWORKS_PART "/%d", 00808 wpa_s->dbus_path, ssid->id); 00809 00810 reply = dbus_message_new_method_return(message); 00811 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 00812 &path, DBUS_TYPE_INVALID); 00813 00814 out: 00815 return reply; 00816 } 00817 00818 00828 DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message, 00829 struct wpa_supplicant *wpa_s) 00830 { 00831 DBusMessage *reply = NULL; 00832 const char *op; 00833 char *iface = NULL, *net_id = NULL; 00834 int id; 00835 struct wpa_ssid *ssid; 00836 00837 if (!dbus_message_get_args(message, NULL, 00838 DBUS_TYPE_OBJECT_PATH, &op, 00839 DBUS_TYPE_INVALID)) { 00840 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 00841 goto out; 00842 } 00843 00844 /* Extract the network ID */ 00845 iface = wpas_dbus_decompose_object_path(op, &net_id, NULL); 00846 if (iface == NULL) { 00847 reply = wpas_dbus_new_invalid_network_error(message); 00848 goto out; 00849 } 00850 00851 /* Ensure the network is actually a child of this interface */ 00852 if (os_strcmp(iface, wpa_s->dbus_path) != 0) { 00853 reply = wpas_dbus_new_invalid_network_error(message); 00854 goto out; 00855 } 00856 00857 id = strtoul(net_id, NULL, 10); 00858 ssid = wpa_config_get_network(wpa_s->conf, id); 00859 if (ssid == NULL) { 00860 reply = wpas_dbus_new_invalid_network_error(message); 00861 goto out; 00862 } 00863 00864 wpas_notify_network_removed(wpa_s, ssid); 00865 00866 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 00867 reply = dbus_message_new_error(message, 00868 WPAS_ERROR_REMOVE_NETWORK_ERROR, 00869 "error removing the specified " 00870 "on this interface."); 00871 goto out; 00872 } 00873 00874 if (ssid == wpa_s->current_ssid) 00875 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 00876 reply = wpas_dbus_new_success_reply(message); 00877 00878 out: 00879 os_free(iface); 00880 os_free(net_id); 00881 return reply; 00882 } 00883 00884 00885 static const char *dont_quote[] = { 00886 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", 00887 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path", 00888 "bssid", NULL 00889 }; 00890 00891 00892 static dbus_bool_t should_quote_opt(const char *key) 00893 { 00894 int i = 0; 00895 while (dont_quote[i] != NULL) { 00896 if (strcmp(key, dont_quote[i]) == 0) 00897 return FALSE; 00898 i++; 00899 } 00900 return TRUE; 00901 } 00902 00903 00914 DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, 00915 struct wpa_supplicant *wpa_s, 00916 struct wpa_ssid *ssid) 00917 { 00918 DBusMessage *reply = NULL; 00919 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 00920 DBusMessageIter iter, iter_dict; 00921 00922 dbus_message_iter_init(message, &iter); 00923 00924 if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) { 00925 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 00926 goto out; 00927 } 00928 00929 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 00930 char *value = NULL; 00931 size_t size = 50; 00932 int ret; 00933 00934 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 00935 reply = wpas_dbus_new_invalid_opts_error(message, 00936 NULL); 00937 goto out; 00938 } 00939 00940 /* Type conversions, since wpa_supplicant wants strings */ 00941 if (entry.type == DBUS_TYPE_ARRAY && 00942 entry.array_type == DBUS_TYPE_BYTE) { 00943 if (entry.array_len <= 0) 00944 goto error; 00945 00946 size = entry.array_len * 2 + 1; 00947 value = os_zalloc(size); 00948 if (value == NULL) 00949 goto error; 00950 ret = wpa_snprintf_hex(value, size, 00951 (u8 *) entry.bytearray_value, 00952 entry.array_len); 00953 if (ret <= 0) 00954 goto error; 00955 } else if (entry.type == DBUS_TYPE_STRING) { 00956 if (should_quote_opt(entry.key)) { 00957 size = os_strlen(entry.str_value); 00958 /* Zero-length option check */ 00959 if (size <= 0) 00960 goto error; 00961 size += 3; /* For quotes and terminator */ 00962 value = os_zalloc(size); 00963 if (value == NULL) 00964 goto error; 00965 ret = os_snprintf(value, size, "\"%s\"", 00966 entry.str_value); 00967 if (ret < 0 || (size_t) ret != (size - 1)) 00968 goto error; 00969 } else { 00970 value = os_strdup(entry.str_value); 00971 if (value == NULL) 00972 goto error; 00973 } 00974 } else if (entry.type == DBUS_TYPE_UINT32) { 00975 value = os_zalloc(size); 00976 if (value == NULL) 00977 goto error; 00978 ret = os_snprintf(value, size, "%u", 00979 entry.uint32_value); 00980 if (ret <= 0) 00981 goto error; 00982 } else if (entry.type == DBUS_TYPE_INT32) { 00983 value = os_zalloc(size); 00984 if (value == NULL) 00985 goto error; 00986 ret = os_snprintf(value, size, "%d", 00987 entry.int32_value); 00988 if (ret <= 0) 00989 goto error; 00990 } else 00991 goto error; 00992 00993 if (wpa_config_set(ssid, entry.key, value, 0) < 0) 00994 goto error; 00995 00996 if ((os_strcmp(entry.key, "psk") == 0 && 00997 value[0] == '"' && ssid->ssid_len) || 00998 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) 00999 wpa_config_update_psk(ssid); 01000 else if (os_strcmp(entry.key, "priority") == 0) 01001 wpa_config_update_prio_list(wpa_s->conf); 01002 01003 os_free(value); 01004 wpa_dbus_dict_entry_clear(&entry); 01005 continue; 01006 01007 error: 01008 os_free(value); 01009 reply = wpas_dbus_new_invalid_opts_error(message, entry.key); 01010 wpa_dbus_dict_entry_clear(&entry); 01011 break; 01012 } 01013 01014 if (!reply) 01015 reply = wpas_dbus_new_success_reply(message); 01016 01017 out: 01018 return reply; 01019 } 01020 01021 01032 DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message, 01033 struct wpa_supplicant *wpa_s, 01034 struct wpa_ssid *ssid) 01035 { 01036 wpa_supplicant_enable_network(wpa_s, ssid); 01037 return wpas_dbus_new_success_reply(message); 01038 } 01039 01040 01051 DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message, 01052 struct wpa_supplicant *wpa_s, 01053 struct wpa_ssid *ssid) 01054 { 01055 wpa_supplicant_disable_network(wpa_s, ssid); 01056 return wpas_dbus_new_success_reply(message); 01057 } 01058 01059 01069 DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, 01070 struct wpa_supplicant *wpa_s) 01071 { 01072 DBusMessage *reply = NULL; 01073 const char *op; 01074 struct wpa_ssid *ssid; 01075 char *iface_obj_path = NULL; 01076 char *network = NULL; 01077 01078 if (os_strlen(dbus_message_get_signature(message)) == 0) { 01079 /* Any network */ 01080 ssid = NULL; 01081 } else { 01082 int nid; 01083 01084 if (!dbus_message_get_args(message, NULL, 01085 DBUS_TYPE_OBJECT_PATH, &op, 01086 DBUS_TYPE_INVALID)) { 01087 reply = wpas_dbus_new_invalid_opts_error(message, 01088 NULL); 01089 goto out; 01090 } 01091 01092 /* Extract the network number */ 01093 iface_obj_path = wpas_dbus_decompose_object_path(op, 01094 &network, 01095 NULL); 01096 if (iface_obj_path == NULL) { 01097 reply = wpas_dbus_new_invalid_iface_error(message); 01098 goto out; 01099 } 01100 /* Ensure the object path really points to this interface */ 01101 if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) { 01102 reply = wpas_dbus_new_invalid_network_error(message); 01103 goto out; 01104 } 01105 01106 nid = strtoul(network, NULL, 10); 01107 if (errno == EINVAL) { 01108 reply = wpas_dbus_new_invalid_network_error(message); 01109 goto out; 01110 } 01111 01112 ssid = wpa_config_get_network(wpa_s->conf, nid); 01113 if (ssid == NULL) { 01114 reply = wpas_dbus_new_invalid_network_error(message); 01115 goto out; 01116 } 01117 } 01118 01119 /* Finally, associate with the network */ 01120 wpa_supplicant_select_network(wpa_s, ssid); 01121 01122 reply = wpas_dbus_new_success_reply(message); 01123 01124 out: 01125 os_free(iface_obj_path); 01126 os_free(network); 01127 return reply; 01128 } 01129 01130 01140 DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message, 01141 struct wpa_supplicant *wpa_s) 01142 { 01143 wpa_s->disconnected = 1; 01144 wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 01145 01146 return wpas_dbus_new_success_reply(message); 01147 } 01148 01149 01159 DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message, 01160 struct wpa_supplicant *wpa_s) 01161 { 01162 DBusMessage *reply = NULL; 01163 dbus_uint32_t ap_scan = 1; 01164 01165 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan, 01166 DBUS_TYPE_INVALID)) { 01167 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 01168 goto out; 01169 } 01170 01171 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 01172 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 01173 goto out; 01174 } 01175 01176 reply = wpas_dbus_new_success_reply(message); 01177 01178 out: 01179 return reply; 01180 } 01181 01182 01192 DBusMessage * wpas_dbus_iface_set_smartcard_modules( 01193 DBusMessage *message, struct wpa_supplicant *wpa_s) 01194 { 01195 DBusMessageIter iter, iter_dict; 01196 char *opensc_engine_path = NULL; 01197 char *pkcs11_engine_path = NULL; 01198 char *pkcs11_module_path = NULL; 01199 struct wpa_dbus_dict_entry entry; 01200 01201 if (!dbus_message_iter_init(message, &iter)) 01202 goto error; 01203 01204 if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) 01205 goto error; 01206 01207 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 01208 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 01209 goto error; 01210 if (!strcmp(entry.key, "opensc_engine_path") && 01211 (entry.type == DBUS_TYPE_STRING)) { 01212 opensc_engine_path = os_strdup(entry.str_value); 01213 if (opensc_engine_path == NULL) 01214 goto error; 01215 } else if (!strcmp(entry.key, "pkcs11_engine_path") && 01216 (entry.type == DBUS_TYPE_STRING)) { 01217 pkcs11_engine_path = os_strdup(entry.str_value); 01218 if (pkcs11_engine_path == NULL) 01219 goto error; 01220 } else if (!strcmp(entry.key, "pkcs11_module_path") && 01221 (entry.type == DBUS_TYPE_STRING)) { 01222 pkcs11_module_path = os_strdup(entry.str_value); 01223 if (pkcs11_module_path == NULL) 01224 goto error; 01225 } else { 01226 wpa_dbus_dict_entry_clear(&entry); 01227 goto error; 01228 } 01229 wpa_dbus_dict_entry_clear(&entry); 01230 } 01231 01232 os_free(wpa_s->conf->opensc_engine_path); 01233 wpa_s->conf->opensc_engine_path = opensc_engine_path; 01234 os_free(wpa_s->conf->pkcs11_engine_path); 01235 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path; 01236 os_free(wpa_s->conf->pkcs11_module_path); 01237 wpa_s->conf->pkcs11_module_path = pkcs11_module_path; 01238 01239 wpa_sm_set_eapol(wpa_s->wpa, NULL); 01240 eapol_sm_deinit(wpa_s->eapol); 01241 wpa_s->eapol = NULL; 01242 wpa_supplicant_init_eapol(wpa_s); 01243 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); 01244 01245 return wpas_dbus_new_success_reply(message); 01246 01247 error: 01248 os_free(opensc_engine_path); 01249 os_free(pkcs11_engine_path); 01250 os_free(pkcs11_module_path); 01251 return wpas_dbus_new_invalid_opts_error(message, NULL); 01252 } 01253 01254 01264 DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, 01265 struct wpa_supplicant *wpa_s) 01266 { 01267 DBusMessage *reply = NULL; 01268 const char *str_state; 01269 01270 reply = dbus_message_new_method_return(message); 01271 if (reply != NULL) { 01272 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 01273 dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state, 01274 DBUS_TYPE_INVALID); 01275 } 01276 01277 return reply; 01278 } 01279 01280 01289 DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message, 01290 struct wpa_supplicant *wpa_s) 01291 { 01292 DBusMessage *reply = NULL; 01293 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 01294 01295 reply = dbus_message_new_method_return(message); 01296 if (reply != NULL) { 01297 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning, 01298 DBUS_TYPE_INVALID); 01299 } else { 01300 wpa_printf(MSG_ERROR, "dbus: Not enough memory to return " 01301 "scanning state"); 01302 } 01303 01304 return reply; 01305 } 01306 01307 01317 DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, 01318 struct wpa_supplicant *wpa_s) 01319 { 01320 DBusMessage *reply = NULL; 01321 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 01322 DBusMessageIter iter, iter_dict; 01323 01324 dbus_message_iter_init(message, &iter); 01325 01326 if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) 01327 return wpas_dbus_new_invalid_opts_error(message, NULL); 01328 01329 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 01330 struct wpa_config_blob *blob; 01331 01332 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 01333 reply = wpas_dbus_new_invalid_opts_error(message, 01334 NULL); 01335 break; 01336 } 01337 01338 if (entry.type != DBUS_TYPE_ARRAY || 01339 entry.array_type != DBUS_TYPE_BYTE) { 01340 reply = wpas_dbus_new_invalid_opts_error( 01341 message, "Byte array expected."); 01342 break; 01343 } 01344 01345 if ((entry.array_len <= 0) || (entry.array_len > 65536) || 01346 !strlen(entry.key)) { 01347 reply = wpas_dbus_new_invalid_opts_error( 01348 message, "Invalid array size."); 01349 break; 01350 } 01351 01352 blob = os_zalloc(sizeof(*blob)); 01353 if (blob == NULL) { 01354 reply = dbus_message_new_error( 01355 message, WPAS_ERROR_ADD_ERROR, 01356 "Not enough memory to add blob."); 01357 break; 01358 } 01359 blob->data = os_zalloc(entry.array_len); 01360 if (blob->data == NULL) { 01361 reply = dbus_message_new_error( 01362 message, WPAS_ERROR_ADD_ERROR, 01363 "Not enough memory to add blob data."); 01364 os_free(blob); 01365 break; 01366 } 01367 01368 blob->name = os_strdup(entry.key); 01369 blob->len = entry.array_len; 01370 os_memcpy(blob->data, (u8 *) entry.bytearray_value, 01371 entry.array_len); 01372 if (blob->name == NULL || blob->data == NULL) { 01373 wpa_config_free_blob(blob); 01374 reply = dbus_message_new_error( 01375 message, WPAS_ERROR_ADD_ERROR, 01376 "Error adding blob."); 01377 break; 01378 } 01379 01380 /* Success */ 01381 if (!wpa_config_remove_blob(wpa_s->conf, blob->name)) 01382 wpas_notify_blob_removed(wpa_s, blob->name); 01383 wpa_config_set_blob(wpa_s->conf, blob); 01384 wpas_notify_blob_added(wpa_s, blob->name); 01385 01386 wpa_dbus_dict_entry_clear(&entry); 01387 } 01388 wpa_dbus_dict_entry_clear(&entry); 01389 01390 return reply ? reply : wpas_dbus_new_success_reply(message); 01391 } 01392 01393 01403 DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, 01404 struct wpa_supplicant *wpa_s) 01405 { 01406 DBusMessageIter iter, array; 01407 char *err_msg = NULL; 01408 01409 dbus_message_iter_init(message, &iter); 01410 01411 if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) || 01412 (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)) 01413 return wpas_dbus_new_invalid_opts_error(message, NULL); 01414 01415 dbus_message_iter_recurse(&iter, &array); 01416 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { 01417 const char *name; 01418 01419 dbus_message_iter_get_basic(&array, &name); 01420 if (!os_strlen(name)) 01421 err_msg = "Invalid blob name."; 01422 01423 if (wpa_config_remove_blob(wpa_s->conf, name) != 0) 01424 err_msg = "Error removing blob."; 01425 else 01426 wpas_notify_blob_removed(wpa_s, name); 01427 dbus_message_iter_next(&array); 01428 } 01429 01430 if (err_msg) 01431 return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR, 01432 err_msg); 01433 01434 return wpas_dbus_new_success_reply(message); 01435 }