00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00106
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
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
00157
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
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
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
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
00377
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
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
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
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
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
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
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
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
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
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
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
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
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
00959 if (size <= 0)
00960 goto error;
00961 size += 3;
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
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
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
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
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
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 }