From df0c787c3ece1d65fd6fef34aa8f56da557b5ac0 Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Mon, 17 Jan 2022 13:12:36 -0800 Subject: [PATCH] wpa: Import wpa 2.10 (second part) WPA is in fact two distfiles. Import the second distfile. --- hs20/client/Android.mk | 81 + hs20/client/Makefile | 81 + hs20/client/devdetail.xml | 47 + hs20/client/devinfo.xml | 7 + hs20/client/est.c | 769 + hs20/client/oma_dm_client.c | 1398 ++ hs20/client/osu_client.c | 3431 ++++ hs20/client/osu_client.h | 121 + hs20/client/spp_client.c | 1004 ++ wpa_supplicant/Android.mk | 1827 +++ wpa_supplicant/ChangeLog | 2500 +++ wpa_supplicant/Makefile | 2074 +++ wpa_supplicant/README | 1163 ++ wpa_supplicant/README-DPP | 204 + wpa_supplicant/README-HS20 | 654 + wpa_supplicant/README-P2P | 856 + wpa_supplicant/README-WPS | 399 + wpa_supplicant/README-Windows.txt | 299 + wpa_supplicant/android.config | 545 + wpa_supplicant/ap.c | 1945 +++ wpa_supplicant/ap.h | 106 + wpa_supplicant/autoscan.c | 162 + wpa_supplicant/autoscan.h | 59 + wpa_supplicant/autoscan_exponential.c | 104 + wpa_supplicant/autoscan_periodic.c | 85 + wpa_supplicant/bgscan.c | 109 + wpa_supplicant/bgscan.h | 82 + wpa_supplicant/bgscan_learn.c | 614 + wpa_supplicant/bgscan_simple.c | 275 + wpa_supplicant/binder/.clang-format | 9 + wpa_supplicant/binder/binder.cpp | 104 + wpa_supplicant/binder/binder.h | 46 + wpa_supplicant/binder/binder_constants.cpp | 18 + wpa_supplicant/binder/binder_constants.h | 21 + wpa_supplicant/binder/binder_i.h | 28 + wpa_supplicant/binder/binder_manager.cpp | 100 + wpa_supplicant/binder/binder_manager.h | 58 + wpa_supplicant/binder/iface.cpp | 16 + wpa_supplicant/binder/iface.h | 42 + wpa_supplicant/binder/supplicant.cpp | 127 + wpa_supplicant/binder/supplicant.h | 55 + wpa_supplicant/bss.c | 1385 ++ wpa_supplicant/bss.h | 200 + wpa_supplicant/bssid_ignore.c | 221 + wpa_supplicant/bssid_ignore.h | 33 + wpa_supplicant/config.c | 5429 +++++++ wpa_supplicant/config.h | 1797 +++ wpa_supplicant/config_file.c | 1656 ++ wpa_supplicant/config_none.c | 56 + wpa_supplicant/config_ssid.h | 1182 ++ wpa_supplicant/config_winreg.c | 1061 ++ wpa_supplicant/ctrl_iface.c | 13103 ++++++++++++++++ wpa_supplicant/ctrl_iface.h | 167 + wpa_supplicant/ctrl_iface_named_pipe.c | 831 + wpa_supplicant/ctrl_iface_udp.c | 831 + wpa_supplicant/ctrl_iface_unix.c | 1431 ++ wpa_supplicant/dbus/Makefile | 69 + wpa_supplicant/dbus/dbus-wpa_supplicant.conf | 17 + wpa_supplicant/dbus/dbus_common.c | 373 + wpa_supplicant/dbus/dbus_common.h | 20 + wpa_supplicant/dbus/dbus_common_i.h | 34 + wpa_supplicant/dbus/dbus_dict_helpers.c | 1061 ++ wpa_supplicant/dbus/dbus_dict_helpers.h | 152 + wpa_supplicant/dbus/dbus_new.c | 5105 ++++++ wpa_supplicant/dbus/dbus_new.h | 648 + wpa_supplicant/dbus/dbus_new_handlers.c | 5928 +++++++ wpa_supplicant/dbus/dbus_new_handlers.h | 285 + wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 3107 ++++ wpa_supplicant/dbus/dbus_new_handlers_p2p.h | 152 + wpa_supplicant/dbus/dbus_new_handlers_wps.c | 804 + wpa_supplicant/dbus/dbus_new_helpers.c | 1025 ++ wpa_supplicant/dbus/dbus_new_helpers.h | 154 + wpa_supplicant/dbus/dbus_new_introspect.c | 286 + .../dbus/fi.w1.wpa_supplicant1.service.in | 5 + wpa_supplicant/defconfig | 635 + wpa_supplicant/doc/docbook/Makefile | 28 + wpa_supplicant/doc/docbook/eapol_test.sgml | 209 + .../doc/docbook/wpa_background.sgml | 105 + wpa_supplicant/doc/docbook/wpa_cli.sgml | 360 + wpa_supplicant/doc/docbook/wpa_gui.sgml | 106 + .../doc/docbook/wpa_passphrase.sgml | 77 + wpa_supplicant/doc/docbook/wpa_priv.sgml | 152 + .../doc/docbook/wpa_supplicant.conf.sgml | 243 + .../doc/docbook/wpa_supplicant.sgml | 764 + wpa_supplicant/dpp_supplicant.c | 3995 +++++ wpa_supplicant/dpp_supplicant.h | 45 + wpa_supplicant/driver_i.h | 1120 ++ wpa_supplicant/eap_proxy_dummy.mak | 0 wpa_supplicant/eap_proxy_dummy.mk | 0 wpa_supplicant/eap_register.c | 271 + wpa_supplicant/eap_testing.txt | 392 + wpa_supplicant/eapol_test.c | 1555 ++ wpa_supplicant/eapol_test.py | 159 + wpa_supplicant/events.c | 5783 +++++++ wpa_supplicant/examples/60_wpa_supplicant | 19 + wpa_supplicant/examples/dbus-listen-preq.py | 66 + wpa_supplicant/examples/dpp-nfc.py | 1186 ++ wpa_supplicant/examples/dpp-qrcode.py | 130 + wpa_supplicant/examples/ieee8021x.conf | 13 + wpa_supplicant/examples/openCryptoki.conf | 41 + wpa_supplicant/examples/p2p-action-udhcp.sh | 69 + wpa_supplicant/examples/p2p-action.sh | 96 + wpa_supplicant/examples/p2p-nfc.py | 654 + wpa_supplicant/examples/p2p/p2p_connect.py | 299 + wpa_supplicant/examples/p2p/p2p_disconnect.py | 169 + wpa_supplicant/examples/p2p/p2p_find.py | 192 + wpa_supplicant/examples/p2p/p2p_flush.py | 168 + wpa_supplicant/examples/p2p/p2p_group_add.py | 222 + wpa_supplicant/examples/p2p/p2p_invite.py | 201 + wpa_supplicant/examples/p2p/p2p_listen.py | 182 + wpa_supplicant/examples/p2p/p2p_stop_find.py | 174 + wpa_supplicant/examples/plaintext.conf | 8 + wpa_supplicant/examples/udhcpd-p2p.conf | 118 + wpa_supplicant/examples/wep.conf | 11 + wpa_supplicant/examples/wpa-psk-tkip.conf | 12 + wpa_supplicant/examples/wpa2-eap-ccmp.conf | 15 + .../examples/wpas-dbus-new-getall.py | 58 + .../examples/wpas-dbus-new-signals.py | 203 + wpa_supplicant/examples/wpas-dbus-new-wps.py | 80 + wpa_supplicant/examples/wpas-dbus-new.py | 149 + wpa_supplicant/examples/wps-ap-cli | 81 + wpa_supplicant/examples/wps-nfc.py | 525 + wpa_supplicant/gas_query.c | 897 ++ wpa_supplicant/gas_query.h | 59 + wpa_supplicant/hs20_supplicant.c | 1357 ++ wpa_supplicant/hs20_supplicant.h | 51 + wpa_supplicant/ibss_rsn.c | 954 ++ wpa_supplicant/ibss_rsn.h | 65 + wpa_supplicant/interworking.c | 3293 ++++ wpa_supplicant/interworking.h | 37 + wpa_supplicant/libwpa_test.c | 32 + wpa_supplicant/main.c | 409 + wpa_supplicant/main_none.c | 40 + wpa_supplicant/main_winmain.c | 78 + wpa_supplicant/main_winsvc.c | 458 + wpa_supplicant/mbo.c | 665 + wpa_supplicant/mesh.c | 892 ++ wpa_supplicant/mesh.h | 49 + wpa_supplicant/mesh_mpm.c | 1403 ++ wpa_supplicant/mesh_mpm.h | 46 + wpa_supplicant/mesh_rsn.c | 795 + wpa_supplicant/mesh_rsn.h | 45 + wpa_supplicant/nfc_pw_token.c | 83 + wpa_supplicant/nmake.mak | 240 + wpa_supplicant/notify.c | 975 ++ wpa_supplicant/notify.h | 167 + wpa_supplicant/offchannel.c | 488 + wpa_supplicant/offchannel.h | 35 + wpa_supplicant/op_classes.c | 534 + wpa_supplicant/p2p_supplicant.c | 10107 ++++++++++++ wpa_supplicant/p2p_supplicant.h | 357 + wpa_supplicant/p2p_supplicant_sd.c | 1273 ++ wpa_supplicant/pasn_supplicant.c | 1710 ++ wpa_supplicant/preauth_test.c | 371 + wpa_supplicant/robust_av.c | 1487 ++ wpa_supplicant/rrm.c | 1594 ++ wpa_supplicant/scan.c | 3360 ++++ wpa_supplicant/scan.h | 96 + wpa_supplicant/sme.c | 2955 ++++ wpa_supplicant/sme.h | 137 + .../wpa_supplicant-nl80211.service.arg.in | 15 + .../wpa_supplicant-wired.service.arg.in | 15 + .../systemd/wpa_supplicant.service.arg.in | 15 + .../systemd/wpa_supplicant.service.in | 14 + wpa_supplicant/todo.txt | 78 + wpa_supplicant/twt.c | 142 + wpa_supplicant/utils/log2pcap.py | 54 + .../vs2005/win_if_list/win_if_list.vcproj | 203 + wpa_supplicant/vs2005/wpa_supplicant.sln | 52 + wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj | 465 + wpa_supplicant/wifi_display.c | 431 + wpa_supplicant/wifi_display.h | 24 + wpa_supplicant/win_example.reg | 42 + wpa_supplicant/win_if_list.c | 173 + wpa_supplicant/wmm_ac.c | 987 ++ wpa_supplicant/wmm_ac.h | 176 + wpa_supplicant/wnm_sta.c | 1981 +++ wpa_supplicant/wnm_sta.h | 93 + wpa_supplicant/wpa_cli.c | 5083 ++++++ wpa_supplicant/wpa_gui-qt4/addinterface.cpp | 239 + wpa_supplicant/wpa_gui-qt4/addinterface.h | 39 + wpa_supplicant/wpa_gui-qt4/eventhistory.cpp | 124 + wpa_supplicant/wpa_gui-qt4/eventhistory.h | 57 + wpa_supplicant/wpa_gui-qt4/eventhistory.ui | 61 + wpa_supplicant/wpa_gui-qt4/icons.qrc | 9 + wpa_supplicant/wpa_gui-qt4/icons/Makefile | 37 + wpa_supplicant/wpa_gui-qt4/icons/README | 74 + wpa_supplicant/wpa_gui-qt4/icons/ap.svg | 832 + wpa_supplicant/wpa_gui-qt4/icons/group.svg | 616 + .../wpa_gui-qt4/icons/invitation.svg | 374 + wpa_supplicant/wpa_gui-qt4/icons/laptop.svg | 1568 ++ wpa_supplicant/wpa_gui-qt4/icons/wpa_gui.svg | 256 + wpa_supplicant/wpa_gui-qt4/icons_png.qrc | 9 + wpa_supplicant/wpa_gui-qt4/lang/wpa_gui_de.ts | 1262 ++ wpa_supplicant/wpa_gui-qt4/main.cpp | 67 + wpa_supplicant/wpa_gui-qt4/networkconfig.cpp | 853 + wpa_supplicant/wpa_gui-qt4/networkconfig.h | 55 + wpa_supplicant/wpa_gui-qt4/networkconfig.ui | 435 + wpa_supplicant/wpa_gui-qt4/peers.cpp | 1885 +++ wpa_supplicant/wpa_gui-qt4/peers.h | 90 + wpa_supplicant/wpa_gui-qt4/peers.ui | 40 + wpa_supplicant/wpa_gui-qt4/scanresults.cpp | 141 + wpa_supplicant/wpa_gui-qt4/scanresults.h | 40 + wpa_supplicant/wpa_gui-qt4/scanresults.ui | 94 + .../wpa_gui-qt4/scanresultsitem.cpp | 18 + wpa_supplicant/wpa_gui-qt4/scanresultsitem.h | 21 + wpa_supplicant/wpa_gui-qt4/signalbar.cpp | 58 + wpa_supplicant/wpa_gui-qt4/signalbar.h | 28 + wpa_supplicant/wpa_gui-qt4/stringquery.cpp | 31 + wpa_supplicant/wpa_gui-qt4/stringquery.h | 28 + .../wpa_gui-qt4/userdatarequest.cpp | 94 + wpa_supplicant/wpa_gui-qt4/userdatarequest.h | 40 + wpa_supplicant/wpa_gui-qt4/userdatarequest.ui | 109 + wpa_supplicant/wpa_gui-qt4/wpa_gui.desktop | 10 + wpa_supplicant/wpa_gui-qt4/wpa_gui.pro | 73 + wpa_supplicant/wpa_gui-qt4/wpagui.cpp | 1913 +++ wpa_supplicant/wpa_gui-qt4/wpagui.h | 180 + wpa_supplicant/wpa_gui-qt4/wpagui.ui | 524 + wpa_supplicant/wpa_gui-qt4/wpamsg.h | 35 + wpa_supplicant/wpa_passphrase.c | 73 + wpa_supplicant/wpa_priv.c | 1292 ++ wpa_supplicant/wpa_supplicant.c | 8667 ++++++++++ wpa_supplicant/wpa_supplicant.conf | 2071 +++ wpa_supplicant/wpa_supplicant_conf.mk | 34 + wpa_supplicant/wpa_supplicant_conf.sh | 16 + wpa_supplicant/wpa_supplicant_i.h | 1890 +++ wpa_supplicant/wpa_supplicant_template.conf | 7 + wpa_supplicant/wpas_glue.c | 1494 ++ wpa_supplicant/wpas_glue.h | 30 + wpa_supplicant/wpas_kay.c | 440 + wpa_supplicant/wpas_kay.h | 51 + wpa_supplicant/wpas_module_tests.c | 114 + wpa_supplicant/wps_supplicant.c | 3013 ++++ wpa_supplicant/wps_supplicant.h | 164 + 234 files changed, 170785 insertions(+) create mode 100644 hs20/client/Android.mk create mode 100644 hs20/client/Makefile create mode 100644 hs20/client/devdetail.xml create mode 100644 hs20/client/devinfo.xml create mode 100644 hs20/client/est.c create mode 100644 hs20/client/oma_dm_client.c create mode 100644 hs20/client/osu_client.c create mode 100644 hs20/client/osu_client.h create mode 100644 hs20/client/spp_client.c create mode 100644 wpa_supplicant/Android.mk create mode 100644 wpa_supplicant/ChangeLog create mode 100644 wpa_supplicant/Makefile create mode 100644 wpa_supplicant/README create mode 100644 wpa_supplicant/README-DPP create mode 100644 wpa_supplicant/README-HS20 create mode 100644 wpa_supplicant/README-P2P create mode 100644 wpa_supplicant/README-WPS create mode 100644 wpa_supplicant/README-Windows.txt create mode 100644 wpa_supplicant/android.config create mode 100644 wpa_supplicant/ap.c create mode 100644 wpa_supplicant/ap.h create mode 100644 wpa_supplicant/autoscan.c create mode 100644 wpa_supplicant/autoscan.h create mode 100644 wpa_supplicant/autoscan_exponential.c create mode 100644 wpa_supplicant/autoscan_periodic.c create mode 100644 wpa_supplicant/bgscan.c create mode 100644 wpa_supplicant/bgscan.h create mode 100644 wpa_supplicant/bgscan_learn.c create mode 100644 wpa_supplicant/bgscan_simple.c create mode 100644 wpa_supplicant/binder/.clang-format create mode 100644 wpa_supplicant/binder/binder.cpp create mode 100644 wpa_supplicant/binder/binder.h create mode 100644 wpa_supplicant/binder/binder_constants.cpp create mode 100644 wpa_supplicant/binder/binder_constants.h create mode 100644 wpa_supplicant/binder/binder_i.h create mode 100644 wpa_supplicant/binder/binder_manager.cpp create mode 100644 wpa_supplicant/binder/binder_manager.h create mode 100644 wpa_supplicant/binder/iface.cpp create mode 100644 wpa_supplicant/binder/iface.h create mode 100644 wpa_supplicant/binder/supplicant.cpp create mode 100644 wpa_supplicant/binder/supplicant.h create mode 100644 wpa_supplicant/bss.c create mode 100644 wpa_supplicant/bss.h create mode 100644 wpa_supplicant/bssid_ignore.c create mode 100644 wpa_supplicant/bssid_ignore.h create mode 100644 wpa_supplicant/config.c create mode 100644 wpa_supplicant/config.h create mode 100644 wpa_supplicant/config_file.c create mode 100644 wpa_supplicant/config_none.c create mode 100644 wpa_supplicant/config_ssid.h create mode 100644 wpa_supplicant/config_winreg.c create mode 100644 wpa_supplicant/ctrl_iface.c create mode 100644 wpa_supplicant/ctrl_iface.h create mode 100644 wpa_supplicant/ctrl_iface_named_pipe.c create mode 100644 wpa_supplicant/ctrl_iface_udp.c create mode 100644 wpa_supplicant/ctrl_iface_unix.c create mode 100644 wpa_supplicant/dbus/Makefile create mode 100644 wpa_supplicant/dbus/dbus-wpa_supplicant.conf create mode 100644 wpa_supplicant/dbus/dbus_common.c create mode 100644 wpa_supplicant/dbus/dbus_common.h create mode 100644 wpa_supplicant/dbus/dbus_common_i.h create mode 100644 wpa_supplicant/dbus/dbus_dict_helpers.c create mode 100644 wpa_supplicant/dbus/dbus_dict_helpers.h create mode 100644 wpa_supplicant/dbus/dbus_new.c create mode 100644 wpa_supplicant/dbus/dbus_new.h create mode 100644 wpa_supplicant/dbus/dbus_new_handlers.c create mode 100644 wpa_supplicant/dbus/dbus_new_handlers.h create mode 100644 wpa_supplicant/dbus/dbus_new_handlers_p2p.c create mode 100644 wpa_supplicant/dbus/dbus_new_handlers_p2p.h create mode 100644 wpa_supplicant/dbus/dbus_new_handlers_wps.c create mode 100644 wpa_supplicant/dbus/dbus_new_helpers.c create mode 100644 wpa_supplicant/dbus/dbus_new_helpers.h create mode 100644 wpa_supplicant/dbus/dbus_new_introspect.c create mode 100644 wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service.in create mode 100644 wpa_supplicant/defconfig create mode 100644 wpa_supplicant/doc/docbook/Makefile create mode 100644 wpa_supplicant/doc/docbook/eapol_test.sgml create mode 100644 wpa_supplicant/doc/docbook/wpa_background.sgml create mode 100644 wpa_supplicant/doc/docbook/wpa_cli.sgml create mode 100644 wpa_supplicant/doc/docbook/wpa_gui.sgml create mode 100644 wpa_supplicant/doc/docbook/wpa_passphrase.sgml create mode 100644 wpa_supplicant/doc/docbook/wpa_priv.sgml create mode 100644 wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml create mode 100644 wpa_supplicant/doc/docbook/wpa_supplicant.sgml create mode 100644 wpa_supplicant/dpp_supplicant.c create mode 100644 wpa_supplicant/dpp_supplicant.h create mode 100644 wpa_supplicant/driver_i.h create mode 100644 wpa_supplicant/eap_proxy_dummy.mak create mode 100644 wpa_supplicant/eap_proxy_dummy.mk create mode 100644 wpa_supplicant/eap_register.c create mode 100644 wpa_supplicant/eap_testing.txt create mode 100644 wpa_supplicant/eapol_test.c create mode 100755 wpa_supplicant/eapol_test.py create mode 100644 wpa_supplicant/events.c create mode 100755 wpa_supplicant/examples/60_wpa_supplicant create mode 100755 wpa_supplicant/examples/dbus-listen-preq.py create mode 100755 wpa_supplicant/examples/dpp-nfc.py create mode 100755 wpa_supplicant/examples/dpp-qrcode.py create mode 100644 wpa_supplicant/examples/ieee8021x.conf create mode 100644 wpa_supplicant/examples/openCryptoki.conf create mode 100755 wpa_supplicant/examples/p2p-action-udhcp.sh create mode 100755 wpa_supplicant/examples/p2p-action.sh create mode 100755 wpa_supplicant/examples/p2p-nfc.py create mode 100644 wpa_supplicant/examples/p2p/p2p_connect.py create mode 100644 wpa_supplicant/examples/p2p/p2p_disconnect.py create mode 100644 wpa_supplicant/examples/p2p/p2p_find.py create mode 100644 wpa_supplicant/examples/p2p/p2p_flush.py create mode 100644 wpa_supplicant/examples/p2p/p2p_group_add.py create mode 100644 wpa_supplicant/examples/p2p/p2p_invite.py create mode 100644 wpa_supplicant/examples/p2p/p2p_listen.py create mode 100644 wpa_supplicant/examples/p2p/p2p_stop_find.py create mode 100644 wpa_supplicant/examples/plaintext.conf create mode 100644 wpa_supplicant/examples/udhcpd-p2p.conf create mode 100644 wpa_supplicant/examples/wep.conf create mode 100644 wpa_supplicant/examples/wpa-psk-tkip.conf create mode 100644 wpa_supplicant/examples/wpa2-eap-ccmp.conf create mode 100755 wpa_supplicant/examples/wpas-dbus-new-getall.py create mode 100755 wpa_supplicant/examples/wpas-dbus-new-signals.py create mode 100755 wpa_supplicant/examples/wpas-dbus-new-wps.py create mode 100755 wpa_supplicant/examples/wpas-dbus-new.py create mode 100755 wpa_supplicant/examples/wps-ap-cli create mode 100755 wpa_supplicant/examples/wps-nfc.py create mode 100644 wpa_supplicant/gas_query.c create mode 100644 wpa_supplicant/gas_query.h create mode 100644 wpa_supplicant/hs20_supplicant.c create mode 100644 wpa_supplicant/hs20_supplicant.h create mode 100644 wpa_supplicant/ibss_rsn.c create mode 100644 wpa_supplicant/ibss_rsn.h create mode 100644 wpa_supplicant/interworking.c create mode 100644 wpa_supplicant/interworking.h create mode 100644 wpa_supplicant/libwpa_test.c create mode 100644 wpa_supplicant/main.c create mode 100644 wpa_supplicant/main_none.c create mode 100644 wpa_supplicant/main_winmain.c create mode 100644 wpa_supplicant/main_winsvc.c create mode 100644 wpa_supplicant/mbo.c create mode 100644 wpa_supplicant/mesh.c create mode 100644 wpa_supplicant/mesh.h create mode 100644 wpa_supplicant/mesh_mpm.c create mode 100644 wpa_supplicant/mesh_mpm.h create mode 100644 wpa_supplicant/mesh_rsn.c create mode 100644 wpa_supplicant/mesh_rsn.h create mode 100644 wpa_supplicant/nfc_pw_token.c create mode 100644 wpa_supplicant/nmake.mak create mode 100644 wpa_supplicant/notify.c create mode 100644 wpa_supplicant/notify.h create mode 100644 wpa_supplicant/offchannel.c create mode 100644 wpa_supplicant/offchannel.h create mode 100644 wpa_supplicant/op_classes.c create mode 100644 wpa_supplicant/p2p_supplicant.c create mode 100644 wpa_supplicant/p2p_supplicant.h create mode 100644 wpa_supplicant/p2p_supplicant_sd.c create mode 100644 wpa_supplicant/pasn_supplicant.c create mode 100644 wpa_supplicant/preauth_test.c create mode 100644 wpa_supplicant/robust_av.c create mode 100644 wpa_supplicant/rrm.c create mode 100644 wpa_supplicant/scan.c create mode 100644 wpa_supplicant/scan.h create mode 100644 wpa_supplicant/sme.c create mode 100644 wpa_supplicant/sme.h create mode 100644 wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in create mode 100644 wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in create mode 100644 wpa_supplicant/systemd/wpa_supplicant.service.arg.in create mode 100644 wpa_supplicant/systemd/wpa_supplicant.service.in create mode 100644 wpa_supplicant/todo.txt create mode 100644 wpa_supplicant/twt.c create mode 100755 wpa_supplicant/utils/log2pcap.py create mode 100755 wpa_supplicant/vs2005/win_if_list/win_if_list.vcproj create mode 100755 wpa_supplicant/vs2005/wpa_supplicant.sln create mode 100755 wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj create mode 100644 wpa_supplicant/wifi_display.c create mode 100644 wpa_supplicant/wifi_display.h create mode 100755 wpa_supplicant/win_example.reg create mode 100644 wpa_supplicant/win_if_list.c create mode 100644 wpa_supplicant/wmm_ac.c create mode 100644 wpa_supplicant/wmm_ac.h create mode 100644 wpa_supplicant/wnm_sta.c create mode 100644 wpa_supplicant/wnm_sta.h create mode 100644 wpa_supplicant/wpa_cli.c create mode 100644 wpa_supplicant/wpa_gui-qt4/addinterface.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/addinterface.h create mode 100644 wpa_supplicant/wpa_gui-qt4/eventhistory.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/eventhistory.h create mode 100644 wpa_supplicant/wpa_gui-qt4/eventhistory.ui create mode 100644 wpa_supplicant/wpa_gui-qt4/icons.qrc create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/Makefile create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/README create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/ap.svg create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/group.svg create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/invitation.svg create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/laptop.svg create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/wpa_gui.svg create mode 100644 wpa_supplicant/wpa_gui-qt4/icons_png.qrc create mode 100644 wpa_supplicant/wpa_gui-qt4/lang/wpa_gui_de.ts create mode 100644 wpa_supplicant/wpa_gui-qt4/main.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/networkconfig.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/networkconfig.h create mode 100644 wpa_supplicant/wpa_gui-qt4/networkconfig.ui create mode 100644 wpa_supplicant/wpa_gui-qt4/peers.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/peers.h create mode 100644 wpa_supplicant/wpa_gui-qt4/peers.ui create mode 100644 wpa_supplicant/wpa_gui-qt4/scanresults.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/scanresults.h create mode 100644 wpa_supplicant/wpa_gui-qt4/scanresults.ui create mode 100644 wpa_supplicant/wpa_gui-qt4/scanresultsitem.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/scanresultsitem.h create mode 100644 wpa_supplicant/wpa_gui-qt4/signalbar.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/signalbar.h create mode 100644 wpa_supplicant/wpa_gui-qt4/stringquery.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/stringquery.h create mode 100644 wpa_supplicant/wpa_gui-qt4/userdatarequest.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/userdatarequest.h create mode 100644 wpa_supplicant/wpa_gui-qt4/userdatarequest.ui create mode 100644 wpa_supplicant/wpa_gui-qt4/wpa_gui.desktop create mode 100644 wpa_supplicant/wpa_gui-qt4/wpa_gui.pro create mode 100644 wpa_supplicant/wpa_gui-qt4/wpagui.cpp create mode 100644 wpa_supplicant/wpa_gui-qt4/wpagui.h create mode 100644 wpa_supplicant/wpa_gui-qt4/wpagui.ui create mode 100644 wpa_supplicant/wpa_gui-qt4/wpamsg.h create mode 100644 wpa_supplicant/wpa_passphrase.c create mode 100644 wpa_supplicant/wpa_priv.c create mode 100644 wpa_supplicant/wpa_supplicant.c create mode 100644 wpa_supplicant/wpa_supplicant.conf create mode 100644 wpa_supplicant/wpa_supplicant_conf.mk create mode 100755 wpa_supplicant/wpa_supplicant_conf.sh create mode 100644 wpa_supplicant/wpa_supplicant_i.h create mode 100644 wpa_supplicant/wpa_supplicant_template.conf create mode 100644 wpa_supplicant/wpas_glue.c create mode 100644 wpa_supplicant/wpas_glue.h create mode 100644 wpa_supplicant/wpas_kay.c create mode 100644 wpa_supplicant/wpas_kay.h create mode 100644 wpa_supplicant/wpas_module_tests.c create mode 100644 wpa_supplicant/wps_supplicant.c create mode 100644 wpa_supplicant/wps_supplicant.h diff --git a/hs20/client/Android.mk b/hs20/client/Android.mk new file mode 100644 index 000000000000..e4db32208d50 --- /dev/null +++ b/hs20/client/Android.mk @@ -0,0 +1,81 @@ +LOCAL_PATH := $(call my-dir) + +INCLUDES = $(LOCAL_PATH) +INCLUDES += $(LOCAL_PATH)/../../src/utils +INCLUDES += $(LOCAL_PATH)/../../src/common +INCLUDES += $(LOCAL_PATH)/../../src +INCLUDES += external/libxml2/include +INCLUDES += external/curl/include +INCLUDES += external/webkit/Source/WebKit/gtk + +# We try to keep this compiling against older platform versions. +# The new icu location (external/icu) exports its own headers, but +# the older versions in external/icu4c don't, and we need to add those +# headers to the include path by hand. +ifeq ($(wildcard external/icu),) +INCLUDES += external/icu4c/common +else +# The LOCAL_EXPORT_C_INCLUDE_DIRS from ICU did not seem to fully resolve the +# build (e.g., "mm -B" failed to build, but following that with "mm" allowed +# the build to complete). For now, add the include directory manually here for +# Android 5.0. +ver = $(filter 5.0%,$(PLATFORM_VERSION)) +ifneq (,$(strip $(ver))) +INCLUDES += external/icu/icu4c/source/common +endif +endif + + +L_CFLAGS += -DCONFIG_CTRL_IFACE +L_CFLAGS += -DCONFIG_CTRL_IFACE_UNIX +L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\" + +OBJS = spp_client.c +OBJS += oma_dm_client.c +OBJS += osu_client.c +OBJS += est.c +OBJS += ../../src/common/wpa_ctrl.c +OBJS += ../../src/common/wpa_helpers.c +OBJS += ../../src/utils/xml-utils.c +#OBJS += ../../src/utils/browser-android.c +OBJS += ../../src/utils/browser-wpadebug.c +OBJS += ../../src/utils/wpabuf.c +OBJS += ../../src/utils/eloop.c +OBJS += ../../src/wps/httpread.c +OBJS += ../../src/wps/http_server.c +OBJS += ../../src/utils/xml_libxml2.c +OBJS += ../../src/utils/http_curl.c +OBJS += ../../src/utils/base64.c +OBJS += ../../src/utils/os_unix.c +L_CFLAGS += -DCONFIG_DEBUG_FILE +OBJS += ../../src/utils/wpa_debug.c +OBJS += ../../src/utils/common.c +OBJS += ../../src/crypto/crypto_internal.c +OBJS += ../../src/crypto/md5-internal.c +OBJS += ../../src/crypto/sha1-internal.c +OBJS += ../../src/crypto/sha256-internal.c +OBJS += ../../src/crypto/tls_openssl_ocsp.c + +L_CFLAGS += -DEAP_TLS_OPENSSL + +L_CFLAGS += -Wno-unused-parameter + + +######################## +include $(CLEAR_VARS) +LOCAL_MODULE := hs20-osu-client +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := libc libcutils +LOCAL_SHARED_LIBRARIES += libcrypto libssl +#LOCAL_SHARED_LIBRARIES += libxml2 +LOCAL_STATIC_LIBRARIES += libxml2 +LOCAL_SHARED_LIBRARIES += libicuuc +LOCAL_SHARED_LIBRARIES += libcurl + +LOCAL_CFLAGS := $(L_CFLAGS) +LOCAL_SRC_FILES := $(OBJS) +LOCAL_C_INCLUDES := $(INCLUDES) +include $(BUILD_EXECUTABLE) + +######################## diff --git a/hs20/client/Makefile b/hs20/client/Makefile new file mode 100644 index 000000000000..4dcfe2d3bf2c --- /dev/null +++ b/hs20/client/Makefile @@ -0,0 +1,81 @@ +ALL=hs20-osu-client + +include ../../src/build.rules + +CFLAGS += -I../../src/utils +CFLAGS += -I../../src/common +CFLAGS += -I../../src + +ifndef CONFIG_NO_BROWSER +ifndef CONFIG_BROWSER_SYSTEM +TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0) +ifeq ($(TEST_WK),) +# Try webkit2 +GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0) +GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0) +CFLAGS += -DUSE_WEBKIT2 +else +GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0) +GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0) +endif + +CFLAGS += $(GTKCFLAGS) +LIBS += $(GTKLIBS) +endif +endif + +OBJS=spp_client.o +OBJS += oma_dm_client.o +OBJS += osu_client.o +OBJS += est.o +OBJS += ../../src/utils/xml-utils.o +CFLAGS += -DCONFIG_CTRL_IFACE +CFLAGS += -DCONFIG_CTRL_IFACE_UNIX +OBJS += ../../src/common/wpa_ctrl.o ../../src/common/wpa_helpers.o +ifdef CONFIG_NO_BROWSER +CFLAGS += -DCONFIG_NO_BROWSER +else +ifdef CONFIG_BROWSER_SYSTEM +OBJS += ../../src/utils/eloop.o +OBJS += ../../src/utils/wpabuf.o +OBJS += ../../src/wps/httpread.o +OBJS += ../../src/wps/http_server.o +OBJS += ../../src/utils/browser-system.o +else +OBJS += ../../src/utils/browser.o +endif +endif +OBJS += ../../src/utils/xml_libxml2.o +OBJS += ../../src/utils/http_curl.o +OBJS += ../../src/utils/base64.o +OBJS += ../../src/utils/os_unix.o +CFLAGS += -DCONFIG_DEBUG_FILE +OBJS += ../../src/utils/wpa_debug.o +OBJS += ../../src/utils/common.o +OBJS += ../../src/crypto/crypto_internal.o +OBJS += ../../src/crypto/md5-internal.o +OBJS += ../../src/crypto/sha1-internal.o +OBJS += ../../src/crypto/sha256-internal.o + +CFLAGS += $(shell xml2-config --cflags) +LIBS += $(shell xml2-config --libs) + +# Allow static/custom linking of libcurl. +ifdef CUST_CURL_LINKAGE +LIBS += ${CUST_CURL_LINKAGE} +else +LIBS += -lcurl +endif + +CFLAGS += -DEAP_TLS_OPENSSL +OBJS += ../../src/crypto/tls_openssl_ocsp.o +LIBS += -lssl -lcrypto + +_OBJS_VAR := OBJS +include ../../src/objs.mk +hs20-osu-client: $(OBJS) + $(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS) + @$(E) " LD " $@ + +clean: common-clean + rm -f core *~ diff --git a/hs20/client/devdetail.xml b/hs20/client/devdetail.xml new file mode 100644 index 000000000000..6d0389e8a133 --- /dev/null +++ b/hs20/client/devdetail.xml @@ -0,0 +1,47 @@ + + + + + + + 13 + + + 21 + MS-CHAP-V2 + + + 18 + + + 23 + + + 50 + + + false + 020102030405 + 310026000000000 + imei:490123456789012 + http://localhost:12345/ + + + + + + + + + + 0 + 0 + 0 + + MobilePhone + Manufacturer + 1.0 + 1.0 + 1.0 + false + diff --git a/hs20/client/devinfo.xml b/hs20/client/devinfo.xml new file mode 100644 index 000000000000..d48a520a98a1 --- /dev/null +++ b/hs20/client/devinfo.xml @@ -0,0 +1,7 @@ + + urn:Example:HS20-station:123456 + Manufacturer + HS20-station + 1.2 + en + diff --git a/hs20/client/est.c b/hs20/client/est.c new file mode 100644 index 000000000000..97f9132100c4 --- /dev/null +++ b/hs20/client/est.c @@ -0,0 +1,769 @@ +/* + * Hotspot 2.0 OSU client - EST client + * Copyright (c) 2012-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef OPENSSL_IS_BORINGSSL +#include +#endif /* OPENSSL_IS_BORINGSSL */ + +#include "common.h" +#include "utils/base64.h" +#include "utils/xml-utils.h" +#include "utils/http-utils.h" +#include "osu_client.h" + + +static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7, + size_t len, char *pem_file, char *der_file) +{ +#ifdef OPENSSL_IS_BORINGSSL + CBS pkcs7_cbs; +#else /* OPENSSL_IS_BORINGSSL */ + PKCS7 *p7 = NULL; + const unsigned char *p = pkcs7; +#endif /* OPENSSL_IS_BORINGSSL */ + STACK_OF(X509) *certs; + int i, num, ret = -1; + BIO *out = NULL; + +#ifdef OPENSSL_IS_BORINGSSL + certs = sk_X509_new_null(); + if (!certs) + goto fail; + CBS_init(&pkcs7_cbs, pkcs7, len); + if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) { + wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s", + ERR_error_string(ERR_get_error(), NULL)); + write_result(ctx, "Could not parse PKCS#7 object from EST"); + goto fail; + } +#else /* OPENSSL_IS_BORINGSSL */ + p7 = d2i_PKCS7(NULL, &p, len); + if (p7 == NULL) { + wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s", + ERR_error_string(ERR_get_error(), NULL)); + write_result(ctx, "Could not parse PKCS#7 object from EST"); + goto fail; + } + + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_signed: + certs = p7->d.sign->cert; + break; + case NID_pkcs7_signedAndEnveloped: + certs = p7->d.signed_and_enveloped->cert; + break; + default: + certs = NULL; + break; + } +#endif /* OPENSSL_IS_BORINGSSL */ + + if (!certs || ((num = sk_X509_num(certs)) == 0)) { + wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object"); + write_result(ctx, "No certificates found in PKCS#7 object"); + goto fail; + } + + if (der_file) { + FILE *f = fopen(der_file, "wb"); + if (f == NULL) + goto fail; + i2d_X509_fp(f, sk_X509_value(certs, 0)); + fclose(f); + } + + if (pem_file) { + out = BIO_new(BIO_s_file()); + if (out == NULL || + BIO_write_filename(out, pem_file) <= 0) + goto fail; + + for (i = 0; i < num; i++) { + X509 *cert = sk_X509_value(certs, i); + X509_print(out, cert); + PEM_write_bio_X509(out, cert); + BIO_puts(out, "\n"); + } + } + + ret = 0; + +fail: +#ifdef OPENSSL_IS_BORINGSSL + if (certs) + sk_X509_pop_free(certs, X509_free); +#else /* OPENSSL_IS_BORINGSSL */ + PKCS7_free(p7); +#endif /* OPENSSL_IS_BORINGSSL */ + if (out) + BIO_free_all(out); + + return ret; +} + + +int est_load_cacerts(struct hs20_osu_client *ctx, const char *url) +{ + char *buf, *resp; + size_t buflen; + unsigned char *pkcs7; + size_t pkcs7_len, resp_len; + int res; + + buflen = os_strlen(url) + 100; + buf = os_malloc(buflen); + if (buf == NULL) + return -1; + + os_snprintf(buf, buflen, "%s/cacerts", url); + wpa_printf(MSG_INFO, "Download EST cacerts from %s", buf); + write_summary(ctx, "Download EST cacerts from %s", buf); + ctx->no_osu_cert_validation = 1; + http_ocsp_set(ctx->http, 1); + res = http_download_file(ctx->http, buf, "Cert/est-cacerts.txt", + ctx->ca_fname); + http_ocsp_set(ctx->http, + (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2); + ctx->no_osu_cert_validation = 0; + if (res < 0) { + wpa_printf(MSG_INFO, "Failed to download EST cacerts from %s", + buf); + write_result(ctx, "Failed to download EST cacerts from %s", + buf); + os_free(buf); + return -1; + } + os_free(buf); + + resp = os_readfile("Cert/est-cacerts.txt", &resp_len); + if (resp == NULL) { + wpa_printf(MSG_INFO, "Could not read Cert/est-cacerts.txt"); + write_result(ctx, "Could not read EST cacerts"); + return -1; + } + + pkcs7 = base64_decode(resp, resp_len, &pkcs7_len); + if (pkcs7 && pkcs7_len < resp_len / 2) { + wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary", + (unsigned int) pkcs7_len, (unsigned int) resp_len); + os_free(pkcs7); + pkcs7 = NULL; + } + if (pkcs7 == NULL) { + wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7"); + pkcs7 = os_malloc(resp_len); + if (pkcs7) { + os_memcpy(pkcs7, resp, resp_len); + pkcs7_len = resp_len; + } + } + os_free(resp); + + if (pkcs7 == NULL) { + wpa_printf(MSG_INFO, "Could not fetch PKCS7 cacerts"); + write_result(ctx, "Could not fetch EST PKCS#7 cacerts"); + return -1; + } + + res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est-cacerts.pem", + NULL); + os_free(pkcs7); + if (res < 0) { + wpa_printf(MSG_INFO, "Could not parse CA certs from PKCS#7 cacerts response"); + write_result(ctx, "Could not parse CA certs from EST PKCS#7 cacerts response"); + return -1; + } + unlink("Cert/est-cacerts.txt"); + + return 0; +} + + +/* + * CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID + * + * AttrOrOID ::= CHOICE { + * oid OBJECT IDENTIFIER, + * attribute Attribute } + * + * Attribute ::= SEQUENCE { + * type OBJECT IDENTIFIER, + * values SET SIZE(1..MAX) OF OBJECT IDENTIFIER } + */ + +typedef struct { + ASN1_OBJECT *type; + STACK_OF(ASN1_OBJECT) *values; +} Attribute; + +typedef struct { + int type; + union { + ASN1_OBJECT *oid; + Attribute *attribute; + } d; +} AttrOrOID; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL) +DEFINE_STACK_OF(AttrOrOID) +#endif + +typedef struct { + int type; + STACK_OF(AttrOrOID) *attrs; +} CsrAttrs; + +ASN1_SEQUENCE(Attribute) = { + ASN1_SIMPLE(Attribute, type, ASN1_OBJECT), + ASN1_SET_OF(Attribute, values, ASN1_OBJECT) +} ASN1_SEQUENCE_END(Attribute); + +ASN1_CHOICE(AttrOrOID) = { + ASN1_SIMPLE(AttrOrOID, d.oid, ASN1_OBJECT), + ASN1_SIMPLE(AttrOrOID, d.attribute, Attribute) +} ASN1_CHOICE_END(AttrOrOID); + +ASN1_CHOICE(CsrAttrs) = { + ASN1_SEQUENCE_OF(CsrAttrs, attrs, AttrOrOID) +} ASN1_CHOICE_END(CsrAttrs); + +IMPLEMENT_ASN1_FUNCTIONS(CsrAttrs); + + +static void add_csrattrs_oid(struct hs20_osu_client *ctx, ASN1_OBJECT *oid, + STACK_OF(X509_EXTENSION) *exts) +{ + char txt[100]; + int res; + + if (!oid) + return; + + res = OBJ_obj2txt(txt, sizeof(txt), oid, 1); + if (res < 0 || res >= (int) sizeof(txt)) + return; + + if (os_strcmp(txt, "1.2.840.113549.1.9.7") == 0) { + wpa_printf(MSG_INFO, "TODO: csrattr challengePassword"); + } else if (os_strcmp(txt, "1.2.840.113549.1.1.11") == 0) { + wpa_printf(MSG_INFO, "csrattr sha256WithRSAEncryption"); + } else { + wpa_printf(MSG_INFO, "Ignore unsupported csrattr oid %s", txt); + } +} + + +static void add_csrattrs_ext_req(struct hs20_osu_client *ctx, + STACK_OF(ASN1_OBJECT) *values, + STACK_OF(X509_EXTENSION) *exts) +{ + char txt[100]; + int i, num, res; + + num = sk_ASN1_OBJECT_num(values); + for (i = 0; i < num; i++) { + ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(values, i); + + res = OBJ_obj2txt(txt, sizeof(txt), oid, 1); + if (res < 0 || res >= (int) sizeof(txt)) + continue; + + if (os_strcmp(txt, "1.3.6.1.1.1.1.22") == 0) { + wpa_printf(MSG_INFO, "TODO: extReq macAddress"); + } else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.3") == 0) { + wpa_printf(MSG_INFO, "TODO: extReq imei"); + } else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.4") == 0) { + wpa_printf(MSG_INFO, "TODO: extReq meid"); + } else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.5") == 0) { + wpa_printf(MSG_INFO, "TODO: extReq DevId"); + } else { + wpa_printf(MSG_INFO, "Ignore unsupported cstattr extensionsRequest %s", + txt); + } + } +} + + +static void add_csrattrs_attr(struct hs20_osu_client *ctx, Attribute *attr, + STACK_OF(X509_EXTENSION) *exts) +{ + char txt[100], txt2[100]; + int i, num, res; + + if (!attr || !attr->type || !attr->values) + return; + + res = OBJ_obj2txt(txt, sizeof(txt), attr->type, 1); + if (res < 0 || res >= (int) sizeof(txt)) + return; + + if (os_strcmp(txt, "1.2.840.113549.1.9.14") == 0) { + add_csrattrs_ext_req(ctx, attr->values, exts); + return; + } + + num = sk_ASN1_OBJECT_num(attr->values); + for (i = 0; i < num; i++) { + ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(attr->values, i); + + res = OBJ_obj2txt(txt2, sizeof(txt2), oid, 1); + if (res < 0 || res >= (int) sizeof(txt2)) + continue; + + wpa_printf(MSG_INFO, "Ignore unsupported cstattr::attr %s oid %s", + txt, txt2); + } +} + + +static void add_csrattrs(struct hs20_osu_client *ctx, CsrAttrs *csrattrs, + STACK_OF(X509_EXTENSION) *exts) +{ + int i, num; + + if (!csrattrs || ! csrattrs->attrs) + return; + +#ifdef OPENSSL_IS_BORINGSSL + num = sk_num(CHECKED_CAST(_STACK *, STACK_OF(AttrOrOID) *, + csrattrs->attrs)); + for (i = 0; i < num; i++) { + AttrOrOID *ao = sk_value( + CHECKED_CAST(_STACK *, const STACK_OF(AttrOrOID) *, + csrattrs->attrs), i); + switch (ao->type) { + case 0: + add_csrattrs_oid(ctx, ao->d.oid, exts); + break; + case 1: + add_csrattrs_attr(ctx, ao->d.attribute, exts); + break; + } + } +#else /* OPENSSL_IS_BORINGSSL */ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL) + num = sk_AttrOrOID_num(csrattrs->attrs); +#else + num = SKM_sk_num(AttrOrOID, csrattrs->attrs); +#endif + for (i = 0; i < num; i++) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL) + AttrOrOID *ao = sk_AttrOrOID_value(csrattrs->attrs, i); +#else + AttrOrOID *ao = SKM_sk_value(AttrOrOID, csrattrs->attrs, i); +#endif + switch (ao->type) { + case 0: + add_csrattrs_oid(ctx, ao->d.oid, exts); + break; + case 1: + add_csrattrs_attr(ctx, ao->d.attribute, exts); + break; + } + } +#endif /* OPENSSL_IS_BORINGSSL */ +} + + +static int generate_csr(struct hs20_osu_client *ctx, char *key_pem, + char *csr_pem, char *est_req, char *old_cert, + CsrAttrs *csrattrs) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + RSA *rsa; + X509_REQ *req = NULL; + int ret = -1; + unsigned int val; + X509_NAME *subj = NULL; + char name[100]; + STACK_OF(X509_EXTENSION) *exts = NULL; + X509_EXTENSION *ex; + BIO *out; + CONF *ctmp = NULL; + + wpa_printf(MSG_INFO, "Generate RSA private key"); + write_summary(ctx, "Generate RSA private key"); + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (!pctx) + return -1; + + if (EVP_PKEY_keygen_init(pctx) <= 0) + goto fail; + + if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048) <= 0) + goto fail; + + if (EVP_PKEY_keygen(pctx, &pkey) <= 0) + goto fail; + EVP_PKEY_CTX_free(pctx); + pctx = NULL; + + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa == NULL) + goto fail; + + if (key_pem) { + FILE *f = fopen(key_pem, "wb"); + if (f == NULL) + goto fail; + if (!PEM_write_RSAPrivateKey(f, rsa, NULL, NULL, 0, NULL, + NULL)) { + wpa_printf(MSG_INFO, "Could not write private key: %s", + ERR_error_string(ERR_get_error(), NULL)); + fclose(f); + goto fail; + } + fclose(f); + } + + wpa_printf(MSG_INFO, "Generate CSR"); + write_summary(ctx, "Generate CSR"); + req = X509_REQ_new(); + if (req == NULL) + goto fail; + + if (old_cert) { + FILE *f; + X509 *cert; + int res; + + f = fopen(old_cert, "r"); + if (f == NULL) + goto fail; + cert = PEM_read_X509(f, NULL, NULL, NULL); + fclose(f); + + if (cert == NULL) + goto fail; + res = X509_REQ_set_subject_name(req, + X509_get_subject_name(cert)); + X509_free(cert); + if (!res) + goto fail; + } else { + os_get_random((u8 *) &val, sizeof(val)); + os_snprintf(name, sizeof(name), "cert-user-%u", val); + subj = X509_NAME_new(); + if (subj == NULL || + !X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC, + (unsigned char *) name, + -1, -1, 0) || + !X509_REQ_set_subject_name(req, subj)) + goto fail; + X509_NAME_free(subj); + subj = NULL; + } + + if (!X509_REQ_set_pubkey(req, pkey)) + goto fail; + + exts = sk_X509_EXTENSION_new_null(); + if (!exts) + goto fail; + + ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_basic_constraints, + "CA:FALSE"); + if (ex == NULL || + !sk_X509_EXTENSION_push(exts, ex)) + goto fail; + + ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_key_usage, + "nonRepudiation,digitalSignature,keyEncipherment"); + if (ex == NULL || + !sk_X509_EXTENSION_push(exts, ex)) + goto fail; + + ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_ext_key_usage, + "1.3.6.1.4.1.40808.1.1.2"); + if (ex == NULL || + !sk_X509_EXTENSION_push(exts, ex)) + goto fail; + + add_csrattrs(ctx, csrattrs, exts); + + if (!X509_REQ_add_extensions(req, exts)) + goto fail; + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + exts = NULL; + + if (!X509_REQ_sign(req, pkey, EVP_sha256())) + goto fail; + + out = BIO_new(BIO_s_mem()); + if (out) { + char *txt; + size_t rlen; + +#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL) + X509_REQ_print(out, req); +#endif + rlen = BIO_ctrl_pending(out); + txt = os_malloc(rlen + 1); + if (txt) { + int res = BIO_read(out, txt, rlen); + if (res > 0) { + txt[res] = '\0'; + wpa_printf(MSG_MSGDUMP, "OpenSSL: Certificate request:\n%s", + txt); + } + os_free(txt); + } + BIO_free(out); + } + + if (csr_pem) { + FILE *f = fopen(csr_pem, "w"); + if (f == NULL) + goto fail; +#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL) + X509_REQ_print_fp(f, req); +#endif + if (!PEM_write_X509_REQ(f, req)) { + fclose(f); + goto fail; + } + fclose(f); + } + + if (est_req) { + BIO *mem = BIO_new(BIO_s_mem()); + BUF_MEM *ptr; + char *pos, *end, *buf_end; + FILE *f; + + if (mem == NULL) + goto fail; + if (!PEM_write_bio_X509_REQ(mem, req)) { + BIO_free(mem); + goto fail; + } + + BIO_get_mem_ptr(mem, &ptr); + pos = ptr->data; + buf_end = pos + ptr->length; + + /* Remove START/END lines */ + while (pos < buf_end && *pos != '\n') + pos++; + if (pos == buf_end) { + BIO_free(mem); + goto fail; + } + pos++; + + end = pos; + while (end < buf_end && *end != '-') + end++; + + f = fopen(est_req, "w"); + if (f == NULL) { + BIO_free(mem); + goto fail; + } + fwrite(pos, end - pos, 1, f); + fclose(f); + + BIO_free(mem); + } + + ret = 0; +fail: + if (exts) + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + if (subj) + X509_NAME_free(subj); + if (req) + X509_REQ_free(req); + if (pkey) + EVP_PKEY_free(pkey); + if (pctx) + EVP_PKEY_CTX_free(pctx); + return ret; +} + + +int est_build_csr(struct hs20_osu_client *ctx, const char *url) +{ + char *buf; + size_t buflen; + int res; + char old_cert_buf[200]; + char *old_cert = NULL; + CsrAttrs *csrattrs = NULL; + + buflen = os_strlen(url) + 100; + buf = os_malloc(buflen); + if (buf == NULL) + return -1; + + os_snprintf(buf, buflen, "%s/csrattrs", url); + wpa_printf(MSG_INFO, "Download csrattrs from %s", buf); + write_summary(ctx, "Download EST csrattrs from %s", buf); + ctx->no_osu_cert_validation = 1; + http_ocsp_set(ctx->http, 1); + res = http_download_file(ctx->http, buf, "Cert/est-csrattrs.txt", + ctx->ca_fname); + http_ocsp_set(ctx->http, + (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2); + ctx->no_osu_cert_validation = 0; + os_free(buf); + if (res < 0) { + wpa_printf(MSG_INFO, "Failed to download EST csrattrs - assume no extra attributes are needed"); + } else { + size_t resp_len; + char *resp; + unsigned char *attrs; + const unsigned char *pos; + size_t attrs_len; + + resp = os_readfile("Cert/est-csrattrs.txt", &resp_len); + if (resp == NULL) { + wpa_printf(MSG_INFO, "Could not read csrattrs"); + return -1; + } + + attrs = base64_decode(resp, resp_len, &attrs_len); + os_free(resp); + + if (attrs == NULL) { + wpa_printf(MSG_INFO, "Could not base64 decode csrattrs"); + return -1; + } + unlink("Cert/est-csrattrs.txt"); + + pos = attrs; + csrattrs = d2i_CsrAttrs(NULL, &pos, attrs_len); + os_free(attrs); + if (csrattrs == NULL) { + wpa_printf(MSG_INFO, "Failed to parse csrattrs ASN.1"); + /* Continue assuming no additional requirements */ + } + } + + if (ctx->client_cert_present) { + os_snprintf(old_cert_buf, sizeof(old_cert_buf), + "SP/%s/client-cert.pem", ctx->fqdn); + old_cert = old_cert_buf; + } + + res = generate_csr(ctx, "Cert/privkey-plain.pem", "Cert/est-req.pem", + "Cert/est-req.b64", old_cert, csrattrs); + if (csrattrs) + CsrAttrs_free(csrattrs); + + return res; +} + + +int est_simple_enroll(struct hs20_osu_client *ctx, const char *url, + const char *user, const char *pw) +{ + char *buf, *resp, *req, *req2; + size_t buflen, resp_len, len, pkcs7_len; + unsigned char *pkcs7; + char client_cert_buf[200]; + char client_key_buf[200]; + const char *client_cert = NULL, *client_key = NULL; + int res; + + req = os_readfile("Cert/est-req.b64", &len); + if (req == NULL) { + wpa_printf(MSG_INFO, "Could not read Cert/req.b64"); + return -1; + } + req2 = os_realloc(req, len + 1); + if (req2 == NULL) { + os_free(req); + return -1; + } + req2[len] = '\0'; + req = req2; + wpa_printf(MSG_DEBUG, "EST simpleenroll request: %s", req); + + buflen = os_strlen(url) + 100; + buf = os_malloc(buflen); + if (buf == NULL) { + os_free(req); + return -1; + } + + if (ctx->client_cert_present) { + os_snprintf(buf, buflen, "%s/simplereenroll", url); + os_snprintf(client_cert_buf, sizeof(client_cert_buf), + "SP/%s/client-cert.pem", ctx->fqdn); + client_cert = client_cert_buf; + os_snprintf(client_key_buf, sizeof(client_key_buf), + "SP/%s/client-key.pem", ctx->fqdn); + client_key = client_key_buf; + } else + os_snprintf(buf, buflen, "%s/simpleenroll", url); + wpa_printf(MSG_INFO, "EST simpleenroll URL: %s", buf); + write_summary(ctx, "EST simpleenroll URL: %s", buf); + ctx->no_osu_cert_validation = 1; + http_ocsp_set(ctx->http, 1); + resp = http_post(ctx->http, buf, req, "application/pkcs10", + "Content-Transfer-Encoding: base64", + ctx->ca_fname, user, pw, client_cert, client_key, + &resp_len); + http_ocsp_set(ctx->http, + (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2); + ctx->no_osu_cert_validation = 0; + os_free(buf); + if (resp == NULL) { + wpa_printf(MSG_INFO, "EST certificate enrollment failed"); + write_result(ctx, "EST certificate enrollment failed"); + return -1; + } + wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp); + + pkcs7 = base64_decode(resp, resp_len, &pkcs7_len); + if (pkcs7 == NULL) { + wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7"); + pkcs7 = os_malloc(resp_len); + if (pkcs7) { + os_memcpy(pkcs7, resp, resp_len); + pkcs7_len = resp_len; + } + } + os_free(resp); + + if (pkcs7 == NULL) { + wpa_printf(MSG_INFO, "Failed to parse simpleenroll base64 response"); + write_result(ctx, "Failed to parse EST simpleenroll base64 response"); + return -1; + } + + res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est_cert.pem", + "Cert/est_cert.der"); + os_free(pkcs7); + + if (res < 0) { + wpa_printf(MSG_INFO, "EST: Failed to extract certificate from PKCS7 file"); + write_result(ctx, "EST: Failed to extract certificate from EST PKCS7 file"); + return -1; + } + + wpa_printf(MSG_INFO, "EST simple%senroll completed successfully", + ctx->client_cert_present ? "re" : ""); + write_summary(ctx, "EST simple%senroll completed successfully", + ctx->client_cert_present ? "re" : ""); + + return 0; +} diff --git a/hs20/client/oma_dm_client.c b/hs20/client/oma_dm_client.c new file mode 100644 index 000000000000..bcd68b8775d5 --- /dev/null +++ b/hs20/client/oma_dm_client.c @@ -0,0 +1,1398 @@ +/* + * Hotspot 2.0 - OMA DM client + * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "wpa_helpers.h" +#include "xml-utils.h" +#include "http-utils.h" +#include "utils/browser.h" +#include "osu_client.h" + + +#define DM_SERVER_INITIATED_MGMT 1200 +#define DM_CLIENT_INITIATED_MGMT 1201 +#define DM_GENERIC_ALERT 1226 + +/* OMA-TS-SyncML-RepPro-V1_2_2 - 10. Response Status Codes */ +#define DM_RESP_OK 200 +#define DM_RESP_AUTH_ACCEPTED 212 +#define DM_RESP_CHUNKED_ITEM_ACCEPTED 213 +#define DM_RESP_NOT_EXECUTED 215 +#define DM_RESP_ATOMIC_ROLL_BACK_OK 216 +#define DM_RESP_NOT_MODIFIED 304 +#define DM_RESP_BAD_REQUEST 400 +#define DM_RESP_UNAUTHORIZED 401 +#define DM_RESP_FORBIDDEN 403 +#define DM_RESP_NOT_FOUND 404 +#define DM_RESP_COMMAND_NOT_ALLOWED 405 +#define DM_RESP_OPTIONAL_FEATURE_NOT_SUPPORTED 406 +#define DM_RESP_MISSING_CREDENTIALS 407 +#define DM_RESP_CONFLICT 409 +#define DM_RESP_GONE 410 +#define DM_RESP_INCOMPLETE_COMMAND 412 +#define DM_RESP_REQ_ENTITY_TOO_LARGE 413 +#define DM_RESP_URI_TOO_LONG 414 +#define DM_RESP_UNSUPPORTED_MEDIA_TYPE_OR_FORMAT 415 +#define DM_RESP_REQ_TOO_BIG 416 +#define DM_RESP_ALREADY_EXISTS 418 +#define DM_RESP_DEVICE_FULL 420 +#define DM_RESP_SIZE_MISMATCH 424 +#define DM_RESP_PERMISSION_DENIED 425 +#define DM_RESP_COMMAND_FAILED 500 +#define DM_RESP_COMMAND_NOT_IMPLEMENTED 501 +#define DM_RESP_ATOMIC_ROLL_BACK_FAILED 516 + +#define DM_HS20_SUBSCRIPTION_CREATION \ + "org.wi-fi.hotspot2dot0.SubscriptionCreation" +#define DM_HS20_SUBSCRIPTION_PROVISIONING \ + "org.wi-fi.hotspot2dot0.SubscriptionProvisioning" +#define DM_HS20_SUBSCRIPTION_REMEDIATION \ + "org.wi-fi.hotspot2dot0.SubscriptionRemediation" +#define DM_HS20_POLICY_UPDATE \ + "org.wi-fi.hotspot2dot0.PolicyUpdate" + +#define DM_URI_PPS "./Wi-Fi/org.wi-fi/PerProviderSubscription" +#define DM_URI_LAUNCH_BROWSER \ + "./DevDetail/Ext/org.wi-fi/Wi-Fi/Ops/launchBrowserToURI" + + +static void add_item(struct hs20_osu_client *ctx, xml_node_t *parent, + const char *locuri, const char *data); + + +static const char * int2str(int val) +{ + static char buf[20]; + snprintf(buf, sizeof(buf), "%d", val); + return buf; +} + + +static char * oma_dm_get_target_locuri(struct hs20_osu_client *ctx, + xml_node_t *node) +{ + xml_node_t *locuri; + char *uri, *ret = NULL; + + locuri = get_node(ctx->xml, node, "Item/Target/LocURI"); + if (locuri == NULL) + return NULL; + + uri = xml_node_get_text(ctx->xml, locuri); + if (uri) + ret = os_strdup(uri); + xml_node_get_text_free(ctx->xml, uri); + return ret; +} + + +static void oma_dm_add_locuri(struct hs20_osu_client *ctx, xml_node_t *parent, + const char *element, const char *uri) +{ + xml_node_t *node; + + node = xml_node_create(ctx->xml, parent, NULL, element); + if (node == NULL) + return; + xml_node_create_text(ctx->xml, node, NULL, "LocURI", uri); +} + + +static xml_node_t * oma_dm_build_hdr(struct hs20_osu_client *ctx, + const char *url, int msgid) +{ + xml_node_t *syncml, *synchdr; + xml_namespace_t *ns; + + if (!ctx->devid) { + wpa_printf(MSG_ERROR, + "DevId from devinfo.xml is not available - cannot use OMA DM"); + return NULL; + } + + syncml = xml_node_create_root(ctx->xml, "SYNCML:SYNCML1.2", NULL, &ns, + "SyncML"); + + synchdr = xml_node_create(ctx->xml, syncml, NULL, "SyncHdr"); + xml_node_create_text(ctx->xml, synchdr, NULL, "VerDTD", "1.2"); + xml_node_create_text(ctx->xml, synchdr, NULL, "VerProto", "DM/1.2"); + xml_node_create_text(ctx->xml, synchdr, NULL, "SessionID", "1"); + xml_node_create_text(ctx->xml, synchdr, NULL, "MsgID", int2str(msgid)); + + oma_dm_add_locuri(ctx, synchdr, "Target", url); + oma_dm_add_locuri(ctx, synchdr, "Source", ctx->devid); + + return syncml; +} + + +static void oma_dm_add_cmdid(struct hs20_osu_client *ctx, xml_node_t *parent, + int cmdid) +{ + xml_node_create_text(ctx->xml, parent, NULL, "CmdID", int2str(cmdid)); +} + + +static xml_node_t * add_alert(struct hs20_osu_client *ctx, xml_node_t *parent, + int cmdid, int data) +{ + xml_node_t *node; + + node = xml_node_create(ctx->xml, parent, NULL, "Alert"); + if (node == NULL) + return NULL; + oma_dm_add_cmdid(ctx, node, cmdid); + xml_node_create_text(ctx->xml, node, NULL, "Data", int2str(data)); + + return node; +} + + +static xml_node_t * add_status(struct hs20_osu_client *ctx, xml_node_t *parent, + int msgref, int cmdref, int cmdid, + const char *cmd, int data, const char *targetref) +{ + xml_node_t *node; + + node = xml_node_create(ctx->xml, parent, NULL, "Status"); + if (node == NULL) + return NULL; + oma_dm_add_cmdid(ctx, node, cmdid); + xml_node_create_text(ctx->xml, node, NULL, "MsgRef", int2str(msgref)); + if (cmdref) + xml_node_create_text(ctx->xml, node, NULL, "CmdRef", + int2str(cmdref)); + xml_node_create_text(ctx->xml, node, NULL, "Cmd", cmd); + xml_node_create_text(ctx->xml, node, NULL, "Data", int2str(data)); + if (targetref) { + xml_node_create_text(ctx->xml, node, NULL, "TargetRef", + targetref); + } + + return node; +} + + +static xml_node_t * add_results(struct hs20_osu_client *ctx, xml_node_t *parent, + int msgref, int cmdref, int cmdid, + const char *locuri, const char *data) +{ + xml_node_t *node; + + node = xml_node_create(ctx->xml, parent, NULL, "Results"); + if (node == NULL) + return NULL; + + oma_dm_add_cmdid(ctx, node, cmdid); + xml_node_create_text(ctx->xml, node, NULL, "MsgRef", int2str(msgref)); + xml_node_create_text(ctx->xml, node, NULL, "CmdRef", int2str(cmdref)); + add_item(ctx, node, locuri, data); + + return node; +} + + +static char * mo_str(struct hs20_osu_client *ctx, const char *urn, + const char *fname) +{ + xml_node_t *fnode, *tnds; + char *str; + + fnode = node_from_file(ctx->xml, fname); + if (!fnode) + return NULL; + tnds = mo_to_tnds(ctx->xml, fnode, 0, urn, "syncml:dmddf1.2"); + xml_node_free(ctx->xml, fnode); + if (!tnds) + return NULL; + + str = xml_node_to_str(ctx->xml, tnds); + xml_node_free(ctx->xml, tnds); + if (str == NULL) + return NULL; + wpa_printf(MSG_INFO, "MgmtTree: %s", str); + + return str; +} + + +static void add_item(struct hs20_osu_client *ctx, xml_node_t *parent, + const char *locuri, const char *data) +{ + xml_node_t *item, *node; + + item = xml_node_create(ctx->xml, parent, NULL, "Item"); + oma_dm_add_locuri(ctx, item, "Source", locuri); + node = xml_node_create(ctx->xml, item, NULL, "Meta"); + xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Format", + "Chr"); + xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Type", + "text/plain"); + xml_node_create_text(ctx->xml, item, NULL, "Data", data); +} + + +static void add_replace_devinfo(struct hs20_osu_client *ctx, xml_node_t *parent, + int cmdid) +{ + xml_node_t *info, *child, *replace; + const char *name; + char locuri[200], *txt; + + info = node_from_file(ctx->xml, "devinfo.xml"); + if (info == NULL) { + wpa_printf(MSG_INFO, "Could not read devinfo.xml"); + return; + } + + replace = xml_node_create(ctx->xml, parent, NULL, "Replace"); + if (replace == NULL) { + xml_node_free(ctx->xml, info); + return; + } + oma_dm_add_cmdid(ctx, replace, cmdid); + + xml_node_for_each_child(ctx->xml, child, info) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + os_snprintf(locuri, sizeof(locuri), "./DevInfo/%s", name); + txt = xml_node_get_text(ctx->xml, child); + if (txt) { + add_item(ctx, replace, locuri, txt); + xml_node_get_text_free(ctx->xml, txt); + } + } + + xml_node_free(ctx->xml, info); +} + + +static void oma_dm_add_hs20_generic_alert(struct hs20_osu_client *ctx, + xml_node_t *syncbody, + int cmdid, const char *oper, + const char *data) +{ + xml_node_t *node, *item; + char buf[200]; + + node = add_alert(ctx, syncbody, cmdid, DM_GENERIC_ALERT); + + item = xml_node_create(ctx->xml, node, NULL, "Item"); + oma_dm_add_locuri(ctx, item, "Source", DM_URI_PPS); + node = xml_node_create(ctx->xml, item, NULL, "Meta"); + snprintf(buf, sizeof(buf), "Reversed-Domain-Name: %s", oper); + xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Type", buf); + xml_node_create_text_ns(ctx->xml, node, "syncml:metinf", "Format", + "xml"); + xml_node_create_text(ctx->xml, item, NULL, "Data", data); +} + + +static xml_node_t * build_oma_dm_1(struct hs20_osu_client *ctx, + const char *url, int msgid, const char *oper) +{ + xml_node_t *syncml, *syncbody; + char *str; + int cmdid = 0; + + syncml = oma_dm_build_hdr(ctx, url, msgid); + if (syncml == NULL) + return NULL; + + syncbody = xml_node_create(ctx->xml, syncml, NULL, "SyncBody"); + if (syncbody == NULL) { + xml_node_free(ctx->xml, syncml); + return NULL; + } + + cmdid++; + add_alert(ctx, syncbody, cmdid, DM_CLIENT_INITIATED_MGMT); + + str = mo_str(ctx, NULL, "devdetail.xml"); + if (str == NULL) { + xml_node_free(ctx->xml, syncml); + return NULL; + } + cmdid++; + oma_dm_add_hs20_generic_alert(ctx, syncbody, cmdid, oper, str); + os_free(str); + + cmdid++; + add_replace_devinfo(ctx, syncbody, cmdid); + + xml_node_create(ctx->xml, syncbody, NULL, "Final"); + + return syncml; +} + + +static xml_node_t * build_oma_dm_1_sub_reg(struct hs20_osu_client *ctx, + const char *url, int msgid) +{ + xml_node_t *syncml; + + syncml = build_oma_dm_1(ctx, url, msgid, DM_HS20_SUBSCRIPTION_CREATION); + if (syncml) + debug_dump_node(ctx, "OMA-DM Package 1 (sub reg)", syncml); + + return syncml; +} + + +static xml_node_t * build_oma_dm_1_sub_prov(struct hs20_osu_client *ctx, + const char *url, int msgid) +{ + xml_node_t *syncml; + + syncml = build_oma_dm_1(ctx, url, msgid, + DM_HS20_SUBSCRIPTION_PROVISIONING); + if (syncml) + debug_dump_node(ctx, "OMA-DM Package 1 (sub prov)", syncml); + + return syncml; +} + + +static xml_node_t * build_oma_dm_1_pol_upd(struct hs20_osu_client *ctx, + const char *url, int msgid) +{ + xml_node_t *syncml; + + syncml = build_oma_dm_1(ctx, url, msgid, DM_HS20_POLICY_UPDATE); + if (syncml) + debug_dump_node(ctx, "OMA-DM Package 1 (pol upd)", syncml); + + return syncml; +} + + +static xml_node_t * build_oma_dm_1_sub_rem(struct hs20_osu_client *ctx, + const char *url, int msgid) +{ + xml_node_t *syncml; + + syncml = build_oma_dm_1(ctx, url, msgid, + DM_HS20_SUBSCRIPTION_REMEDIATION); + if (syncml) + debug_dump_node(ctx, "OMA-DM Package 1 (sub rem)", syncml); + + return syncml; +} + + +static int oma_dm_exec_browser(struct hs20_osu_client *ctx, xml_node_t *exec) +{ + xml_node_t *node; + char *data; + int res; + + node = get_node(ctx->xml, exec, "Item/Data"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No Data node found"); + return DM_RESP_BAD_REQUEST; + } + + data = xml_node_get_text(ctx->xml, node); + if (data == NULL) { + wpa_printf(MSG_INFO, "Invalid data"); + return DM_RESP_BAD_REQUEST; + } + wpa_printf(MSG_INFO, "Data: %s", data); + wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data); + write_summary(ctx, "Launch browser to URI '%s'", data); + res = hs20_web_browser(data, 1); + xml_node_get_text_free(ctx->xml, data); + if (res > 0) { + wpa_printf(MSG_INFO, "User response in browser completed successfully"); + write_summary(ctx, "User response in browser completed successfully"); + return DM_RESP_OK; + } else { + wpa_printf(MSG_INFO, "Failed to receive user response"); + write_summary(ctx, "Failed to receive user response"); + return DM_RESP_COMMAND_FAILED; + } +} + + +static int oma_dm_exec_get_cert(struct hs20_osu_client *ctx, xml_node_t *exec) +{ + xml_node_t *node, *getcert; + char *data; + const char *name; + int res; + + wpa_printf(MSG_INFO, "Client certificate enrollment"); + write_summary(ctx, "Client certificate enrollment"); + + node = get_node(ctx->xml, exec, "Item/Data"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No Data node found"); + return DM_RESP_BAD_REQUEST; + } + + data = xml_node_get_text(ctx->xml, node); + if (data == NULL) { + wpa_printf(MSG_INFO, "Invalid data"); + return DM_RESP_BAD_REQUEST; + } + wpa_printf(MSG_INFO, "Data: %s", data); + getcert = xml_node_from_buf(ctx->xml, data); + xml_node_get_text_free(ctx->xml, data); + + if (getcert == NULL) { + wpa_printf(MSG_INFO, "Could not parse Item/Data node contents"); + return DM_RESP_BAD_REQUEST; + } + + debug_dump_node(ctx, "OMA-DM getCertificate", getcert); + + name = xml_node_get_localname(ctx->xml, getcert); + if (name == NULL || os_strcasecmp(name, "getCertificate") != 0) { + wpa_printf(MSG_INFO, "Unexpected getCertificate node name '%s'", + name); + return DM_RESP_BAD_REQUEST; + } + + res = osu_get_certificate(ctx, getcert); + + xml_node_free(ctx->xml, getcert); + + return res == 0 ? DM_RESP_OK : DM_RESP_COMMAND_FAILED; +} + + +static int oma_dm_exec(struct hs20_osu_client *ctx, xml_node_t *exec) +{ + char *locuri; + int ret; + + locuri = oma_dm_get_target_locuri(ctx, exec); + if (locuri == NULL) { + wpa_printf(MSG_INFO, "No Target LocURI node found"); + return DM_RESP_BAD_REQUEST; + } + + wpa_printf(MSG_INFO, "Target LocURI: %s", locuri); + + if (os_strcasecmp(locuri, "./DevDetail/Ext/org.wi-fi/Wi-Fi/Ops/" + "launchBrowserToURI") == 0) { + ret = oma_dm_exec_browser(ctx, exec); + } else if (os_strcasecmp(locuri, "./DevDetail/Ext/org.wi-fi/Wi-Fi/Ops/" + "getCertificate") == 0) { + ret = oma_dm_exec_get_cert(ctx, exec); + } else { + wpa_printf(MSG_INFO, "Unsupported exec Target LocURI"); + ret = DM_RESP_NOT_FOUND; + } + os_free(locuri); + + return ret; +} + + +static int oma_dm_run_add(struct hs20_osu_client *ctx, const char *locuri, + xml_node_t *add, xml_node_t *pps, + const char *pps_fname) +{ + const char *pos; + size_t fqdn_len; + xml_node_t *node, *tnds, *unode, *pps_node; + char *data, *uri, *upos, *end; + int use_tnds = 0; + size_t uri_len; + + wpa_printf(MSG_INFO, "Add command target LocURI: %s", locuri); + + if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) { + wpa_printf(MSG_INFO, "Do not allow Add outside ./Wi-Fi"); + return DM_RESP_PERMISSION_DENIED; + } + pos = locuri + 8; + + if (ctx->fqdn == NULL) + return DM_RESP_COMMAND_FAILED; + fqdn_len = os_strlen(ctx->fqdn); + if (os_strncasecmp(pos, ctx->fqdn, fqdn_len) != 0 || + pos[fqdn_len] != '/') { + wpa_printf(MSG_INFO, "Do not allow Add outside ./Wi-Fi/%s", + ctx->fqdn); + return DM_RESP_PERMISSION_DENIED; + } + pos += fqdn_len + 1; + + if (os_strncasecmp(pos, "PerProviderSubscription/", 24) != 0) { + wpa_printf(MSG_INFO, + "Do not allow Add outside ./Wi-Fi/%s/PerProviderSubscription", + ctx->fqdn); + return DM_RESP_PERMISSION_DENIED; + } + pos += 24; + + wpa_printf(MSG_INFO, "Add command for PPS node %s", pos); + + pps_node = get_node(ctx->xml, pps, pos); + if (pps_node) { + wpa_printf(MSG_INFO, "Specified PPS node exists already"); + return DM_RESP_ALREADY_EXISTS; + } + + uri = os_strdup(pos); + if (uri == NULL) + return DM_RESP_COMMAND_FAILED; + while (!pps_node) { + upos = os_strrchr(uri, '/'); + if (!upos) + break; + upos[0] = '\0'; + pps_node = get_node(ctx->xml, pps, uri); + wpa_printf(MSG_INFO, "Node %s %s", uri, + pps_node ? "exists" : "does not exist"); + } + + wpa_printf(MSG_INFO, "Parent URI: %s", uri); + + if (!pps_node) { + /* Add at root of PPS MO */ + pps_node = pps; + } + + uri_len = os_strlen(uri); + os_strlcpy(uri, pos + uri_len, os_strlen(pos)); + upos = uri; + while (*upos == '/') + upos++; + wpa_printf(MSG_INFO, "Nodes to add: %s", upos); + + for (;;) { + end = os_strchr(upos, '/'); + if (!end) + break; + *end = '\0'; + wpa_printf(MSG_INFO, "Adding interim node %s", upos); + pps_node = xml_node_create(ctx->xml, pps_node, NULL, upos); + if (pps_node == NULL) { + os_free(uri); + return DM_RESP_COMMAND_FAILED; + } + upos = end + 1; + } + + wpa_printf(MSG_INFO, "Adding node %s", upos); + + node = get_node(ctx->xml, add, "Item/Meta/Type"); + if (node) { + char *type; + type = xml_node_get_text(ctx->xml, node); + if (type == NULL) { + wpa_printf(MSG_ERROR, "Could not find type text"); + os_free(uri); + return DM_RESP_BAD_REQUEST; + } + use_tnds = node && + os_strstr(type, "application/vnd.syncml.dmtnds+xml"); + } + + node = get_node(ctx->xml, add, "Item/Data"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No Add/Item/Data found"); + os_free(uri); + return DM_RESP_BAD_REQUEST; + } + + data = xml_node_get_text(ctx->xml, node); + if (data == NULL) { + wpa_printf(MSG_INFO, "Could not get Add/Item/Data text"); + os_free(uri); + return DM_RESP_BAD_REQUEST; + } + + wpa_printf(MSG_DEBUG, "Add/Item/Data: %s", data); + + if (use_tnds) { + tnds = xml_node_from_buf(ctx->xml, data); + xml_node_get_text_free(ctx->xml, data); + if (tnds == NULL) { + wpa_printf(MSG_INFO, + "Could not parse Add/Item/Data text"); + os_free(uri); + return DM_RESP_BAD_REQUEST; + } + + unode = tnds_to_mo(ctx->xml, tnds); + xml_node_free(ctx->xml, tnds); + if (unode == NULL) { + wpa_printf(MSG_INFO, "Could not parse TNDS text"); + os_free(uri); + return DM_RESP_BAD_REQUEST; + } + + debug_dump_node(ctx, "Parsed TNDS", unode); + + xml_node_add_child(ctx->xml, pps_node, unode); + } else { + /* TODO: What to do here? */ + os_free(uri); + return DM_RESP_BAD_REQUEST; + } + + os_free(uri); + + if (update_pps_file(ctx, pps_fname, pps) < 0) + return DM_RESP_COMMAND_FAILED; + + ctx->pps_updated = 1; + + return DM_RESP_OK; +} + + +static int oma_dm_add(struct hs20_osu_client *ctx, xml_node_t *add, + xml_node_t *pps, const char *pps_fname) +{ + xml_node_t *node; + char *locuri; + char fname[300]; + int ret; + + node = get_node(ctx->xml, add, "Item/Target/LocURI"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No Target LocURI node found"); + return DM_RESP_BAD_REQUEST; + } + locuri = xml_node_get_text(ctx->xml, node); + if (locuri == NULL) { + wpa_printf(MSG_ERROR, "No LocURI node text found"); + return DM_RESP_BAD_REQUEST; + } + wpa_printf(MSG_INFO, "Target LocURI: %s", locuri); + if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) { + wpa_printf(MSG_INFO, "Unsupported Add Target LocURI"); + xml_node_get_text_free(ctx->xml, locuri); + return DM_RESP_PERMISSION_DENIED; + } + + node = get_node(ctx->xml, add, "Item/Data"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No Data node found"); + xml_node_get_text_free(ctx->xml, locuri); + return DM_RESP_BAD_REQUEST; + } + + if (pps_fname && os_file_exists(pps_fname)) { + ret = oma_dm_run_add(ctx, locuri, add, pps, pps_fname); + if (ret != DM_RESP_OK) { + xml_node_get_text_free(ctx->xml, locuri); + return ret; + } + ret = 0; + os_strlcpy(fname, pps_fname, sizeof(fname)); + } else + ret = hs20_add_pps_mo(ctx, locuri, node, fname, sizeof(fname)); + xml_node_get_text_free(ctx->xml, locuri); + if (ret < 0) + return ret == -2 ? DM_RESP_ALREADY_EXISTS : + DM_RESP_COMMAND_FAILED; + + if (ctx->no_reconnect == 2) { + os_snprintf(ctx->pps_fname, sizeof(ctx->pps_fname), "%s", + fname); + ctx->pps_cred_set = 1; + return DM_RESP_OK; + } + + wpa_printf(MSG_INFO, "Updating wpa_supplicant credentials"); + cmd_set_pps(ctx, fname); + + if (ctx->no_reconnect) + return DM_RESP_OK; + + wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration"); + if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) + wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect"); + + return DM_RESP_OK; +} + + +static int oma_dm_replace(struct hs20_osu_client *ctx, xml_node_t *replace, + xml_node_t *pps, const char *pps_fname) +{ + char *locuri, *pos; + size_t fqdn_len; + xml_node_t *node, *tnds, *unode, *pps_node, *parent; + char *data; + int use_tnds = 0; + + locuri = oma_dm_get_target_locuri(ctx, replace); + if (locuri == NULL) + return DM_RESP_BAD_REQUEST; + + wpa_printf(MSG_INFO, "Replace command target LocURI: %s", locuri); + if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) { + wpa_printf(MSG_INFO, "Do not allow Replace outside ./Wi-Fi"); + os_free(locuri); + return DM_RESP_PERMISSION_DENIED; + } + pos = locuri + 8; + + if (ctx->fqdn == NULL) { + os_free(locuri); + return DM_RESP_COMMAND_FAILED; + } + fqdn_len = os_strlen(ctx->fqdn); + if (os_strncasecmp(pos, ctx->fqdn, fqdn_len) != 0 || + pos[fqdn_len] != '/') { + wpa_printf(MSG_INFO, "Do not allow Replace outside ./Wi-Fi/%s", + ctx->fqdn); + os_free(locuri); + return DM_RESP_PERMISSION_DENIED; + } + pos += fqdn_len + 1; + + if (os_strncasecmp(pos, "PerProviderSubscription/", 24) != 0) { + wpa_printf(MSG_INFO, + "Do not allow Replace outside ./Wi-Fi/%s/PerProviderSubscription", + ctx->fqdn); + os_free(locuri); + return DM_RESP_PERMISSION_DENIED; + } + pos += 24; + + wpa_printf(MSG_INFO, "Replace command for PPS node %s", pos); + + pps_node = get_node(ctx->xml, pps, pos); + if (pps_node == NULL) { + wpa_printf(MSG_INFO, "Specified PPS node not found"); + os_free(locuri); + return DM_RESP_NOT_FOUND; + } + + node = get_node(ctx->xml, replace, "Item/Meta/Type"); + if (node) { + char *type; + type = xml_node_get_text(ctx->xml, node); + if (type == NULL) { + wpa_printf(MSG_INFO, "Could not find type text"); + os_free(locuri); + return DM_RESP_BAD_REQUEST; + } + use_tnds = node && + os_strstr(type, "application/vnd.syncml.dmtnds+xml"); + } + + node = get_node(ctx->xml, replace, "Item/Data"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No Replace/Item/Data found"); + os_free(locuri); + return DM_RESP_BAD_REQUEST; + } + + data = xml_node_get_text(ctx->xml, node); + if (data == NULL) { + wpa_printf(MSG_INFO, "Could not get Replace/Item/Data text"); + os_free(locuri); + return DM_RESP_BAD_REQUEST; + } + + wpa_printf(MSG_DEBUG, "Replace/Item/Data: %s", data); + + if (use_tnds) { + tnds = xml_node_from_buf(ctx->xml, data); + xml_node_get_text_free(ctx->xml, data); + if (tnds == NULL) { + wpa_printf(MSG_INFO, + "Could not parse Replace/Item/Data text"); + os_free(locuri); + return DM_RESP_BAD_REQUEST; + } + + unode = tnds_to_mo(ctx->xml, tnds); + xml_node_free(ctx->xml, tnds); + if (unode == NULL) { + wpa_printf(MSG_INFO, "Could not parse TNDS text"); + os_free(locuri); + return DM_RESP_BAD_REQUEST; + } + + debug_dump_node(ctx, "Parsed TNDS", unode); + + parent = xml_node_get_parent(ctx->xml, pps_node); + xml_node_detach(ctx->xml, pps_node); + xml_node_add_child(ctx->xml, parent, unode); + } else { + xml_node_set_text(ctx->xml, pps_node, data); + xml_node_get_text_free(ctx->xml, data); + } + + os_free(locuri); + + if (update_pps_file(ctx, pps_fname, pps) < 0) + return DM_RESP_COMMAND_FAILED; + + ctx->pps_updated = 1; + + return DM_RESP_OK; +} + + +static int oma_dm_get(struct hs20_osu_client *ctx, xml_node_t *get, + xml_node_t *pps, const char *pps_fname, char **value) +{ + char *locuri, *pos; + size_t fqdn_len; + xml_node_t *pps_node; + const char *name; + + *value = NULL; + + locuri = oma_dm_get_target_locuri(ctx, get); + if (locuri == NULL) + return DM_RESP_BAD_REQUEST; + + wpa_printf(MSG_INFO, "Get command target LocURI: %s", locuri); + if (os_strncasecmp(locuri, "./Wi-Fi/", 8) != 0) { + wpa_printf(MSG_INFO, "Do not allow Get outside ./Wi-Fi"); + os_free(locuri); + return DM_RESP_PERMISSION_DENIED; + } + pos = locuri + 8; + + if (ctx->fqdn == NULL) + return DM_RESP_COMMAND_FAILED; + fqdn_len = os_strlen(ctx->fqdn); + if (os_strncasecmp(pos, ctx->fqdn, fqdn_len) != 0 || + pos[fqdn_len] != '/') { + wpa_printf(MSG_INFO, "Do not allow Get outside ./Wi-Fi/%s", + ctx->fqdn); + os_free(locuri); + return DM_RESP_PERMISSION_DENIED; + } + pos += fqdn_len + 1; + + if (os_strncasecmp(pos, "PerProviderSubscription/", 24) != 0) { + wpa_printf(MSG_INFO, + "Do not allow Get outside ./Wi-Fi/%s/PerProviderSubscription", + ctx->fqdn); + os_free(locuri); + return DM_RESP_PERMISSION_DENIED; + } + pos += 24; + + wpa_printf(MSG_INFO, "Get command for PPS node %s", pos); + + pps_node = get_node(ctx->xml, pps, pos); + if (pps_node == NULL) { + wpa_printf(MSG_INFO, "Specified PPS node not found"); + os_free(locuri); + return DM_RESP_NOT_FOUND; + } + + name = xml_node_get_localname(ctx->xml, pps_node); + wpa_printf(MSG_INFO, "Get command returned node with name '%s'", name); + if (os_strcasecmp(name, "Password") == 0) { + wpa_printf(MSG_INFO, "Do not allow Get for Password node"); + os_free(locuri); + return DM_RESP_PERMISSION_DENIED; + } + + /* + * TODO: No support for DMTNDS, so if interior node, reply with a + * list of children node names in Results element. The child list type is + * defined in [DMTND]. + */ + + *value = xml_node_get_text(ctx->xml, pps_node); + if (*value == NULL) + return DM_RESP_COMMAND_FAILED; + + return DM_RESP_OK; +} + + +static int oma_dm_get_cmdid(struct hs20_osu_client *ctx, xml_node_t *node) +{ + xml_node_t *cnode; + char *str; + int ret; + + cnode = get_node(ctx->xml, node, "CmdID"); + if (cnode == NULL) + return 0; + + str = xml_node_get_text(ctx->xml, cnode); + if (str == NULL) + return 0; + ret = atoi(str); + xml_node_get_text_free(ctx->xml, str); + return ret; +} + + +static xml_node_t * oma_dm_send_recv(struct hs20_osu_client *ctx, + const char *url, xml_node_t *syncml, + const char *ext_hdr, + const char *username, const char *password, + const char *client_cert, + const char *client_key) +{ + xml_node_t *resp; + char *str, *res; + char *resp_uri = NULL; + + str = xml_node_to_str(ctx->xml, syncml); + xml_node_free(ctx->xml, syncml); + if (str == NULL) + return NULL; + + wpa_printf(MSG_INFO, "Send OMA DM Package"); + write_summary(ctx, "Send OMA DM Package"); + os_free(ctx->server_url); + ctx->server_url = os_strdup(url); + res = http_post(ctx->http, url, str, "application/vnd.syncml.dm+xml", + ext_hdr, ctx->ca_fname, username, password, + client_cert, client_key, NULL); + os_free(str); + os_free(resp_uri); + resp_uri = NULL; + + if (res == NULL) { + const char *err = http_get_err(ctx->http); + if (err) { + wpa_printf(MSG_INFO, "HTTP error: %s", err); + write_result(ctx, "HTTP error: %s", err); + } else { + write_summary(ctx, "Failed to send OMA DM Package"); + } + return NULL; + } + wpa_printf(MSG_DEBUG, "Server response: %s", res); + + wpa_printf(MSG_INFO, "Process OMA DM Package"); + write_summary(ctx, "Process received OMA DM Package"); + resp = xml_node_from_buf(ctx->xml, res); + os_free(res); + if (resp == NULL) { + wpa_printf(MSG_INFO, "Failed to parse OMA DM response"); + return NULL; + } + + debug_dump_node(ctx, "OMA DM Package", resp); + + return resp; +} + + +static xml_node_t * oma_dm_process(struct hs20_osu_client *ctx, const char *url, + xml_node_t *resp, int msgid, + char **ret_resp_uri, + xml_node_t *pps, const char *pps_fname) +{ + xml_node_t *syncml, *syncbody, *hdr, *body, *child; + const char *name; + char *resp_uri = NULL; + int server_msgid = 0; + int cmdid = 0; + int server_cmdid; + int resp_needed = 0; + char *tmp; + int final = 0; + char *locuri; + + *ret_resp_uri = NULL; + + name = xml_node_get_localname(ctx->xml, resp); + if (name == NULL || os_strcasecmp(name, "SyncML") != 0) { + wpa_printf(MSG_INFO, "SyncML node not found"); + return NULL; + } + + hdr = get_node(ctx->xml, resp, "SyncHdr"); + body = get_node(ctx->xml, resp, "SyncBody"); + if (hdr == NULL || body == NULL) { + wpa_printf(MSG_INFO, "Could not find SyncHdr or SyncBody"); + return NULL; + } + + xml_node_for_each_child(ctx->xml, child, hdr) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + wpa_printf(MSG_INFO, "SyncHdr %s", name); + if (os_strcasecmp(name, "RespURI") == 0) { + tmp = xml_node_get_text(ctx->xml, child); + if (tmp) + resp_uri = os_strdup(tmp); + xml_node_get_text_free(ctx->xml, tmp); + } else if (os_strcasecmp(name, "MsgID") == 0) { + tmp = xml_node_get_text(ctx->xml, child); + if (tmp) + server_msgid = atoi(tmp); + xml_node_get_text_free(ctx->xml, tmp); + } + } + + wpa_printf(MSG_INFO, "Server MsgID: %d", server_msgid); + if (resp_uri) + wpa_printf(MSG_INFO, "RespURI: %s", resp_uri); + + syncml = oma_dm_build_hdr(ctx, resp_uri ? resp_uri : url, msgid); + if (syncml == NULL) { + os_free(resp_uri); + return NULL; + } + + syncbody = xml_node_create(ctx->xml, syncml, NULL, "SyncBody"); + cmdid++; + add_status(ctx, syncbody, server_msgid, 0, cmdid, "SyncHdr", + DM_RESP_AUTH_ACCEPTED, NULL); + + xml_node_for_each_child(ctx->xml, child, body) { + xml_node_for_each_check(ctx->xml, child); + server_cmdid = oma_dm_get_cmdid(ctx, child); + name = xml_node_get_localname(ctx->xml, child); + wpa_printf(MSG_INFO, "SyncBody CmdID=%d - %s", + server_cmdid, name); + if (os_strcasecmp(name, "Exec") == 0) { + int res = oma_dm_exec(ctx, child); + cmdid++; + locuri = oma_dm_get_target_locuri(ctx, child); + if (locuri == NULL) + res = DM_RESP_BAD_REQUEST; + add_status(ctx, syncbody, server_msgid, server_cmdid, + cmdid, name, res, locuri); + os_free(locuri); + resp_needed = 1; + } else if (os_strcasecmp(name, "Add") == 0) { + int res = oma_dm_add(ctx, child, pps, pps_fname); + cmdid++; + locuri = oma_dm_get_target_locuri(ctx, child); + if (locuri == NULL) + res = DM_RESP_BAD_REQUEST; + add_status(ctx, syncbody, server_msgid, server_cmdid, + cmdid, name, res, locuri); + os_free(locuri); + resp_needed = 1; + } else if (os_strcasecmp(name, "Replace") == 0) { + int res; + res = oma_dm_replace(ctx, child, pps, pps_fname); + cmdid++; + locuri = oma_dm_get_target_locuri(ctx, child); + if (locuri == NULL) + res = DM_RESP_BAD_REQUEST; + add_status(ctx, syncbody, server_msgid, server_cmdid, + cmdid, name, res, locuri); + os_free(locuri); + resp_needed = 1; + } else if (os_strcasecmp(name, "Status") == 0) { + /* TODO: Verify success */ + } else if (os_strcasecmp(name, "Get") == 0) { + int res; + char *value; + res = oma_dm_get(ctx, child, pps, pps_fname, &value); + cmdid++; + locuri = oma_dm_get_target_locuri(ctx, child); + if (locuri == NULL) + res = DM_RESP_BAD_REQUEST; + add_status(ctx, syncbody, server_msgid, server_cmdid, + cmdid, name, res, locuri); + if (res == DM_RESP_OK && value) { + cmdid++; + add_results(ctx, syncbody, server_msgid, + server_cmdid, cmdid, locuri, value); + } + os_free(locuri); + xml_node_get_text_free(ctx->xml, value); + resp_needed = 1; +#if 0 /* TODO: MUST support */ + } else if (os_strcasecmp(name, "Delete") == 0) { +#endif +#if 0 /* TODO: MUST support */ + } else if (os_strcasecmp(name, "Sequence") == 0) { +#endif + } else if (os_strcasecmp(name, "Final") == 0) { + final = 1; + break; + } else { + locuri = oma_dm_get_target_locuri(ctx, child); + add_status(ctx, syncbody, server_msgid, server_cmdid, + cmdid, name, DM_RESP_COMMAND_NOT_IMPLEMENTED, + locuri); + os_free(locuri); + resp_needed = 1; + } + } + + if (!final) { + wpa_printf(MSG_INFO, "Final node not found"); + xml_node_free(ctx->xml, syncml); + os_free(resp_uri); + return NULL; + } + + if (!resp_needed) { + wpa_printf(MSG_INFO, "Exchange completed - no response needed"); + xml_node_free(ctx->xml, syncml); + os_free(resp_uri); + return NULL; + } + + xml_node_create(ctx->xml, syncbody, NULL, "Final"); + + debug_dump_node(ctx, "OMA-DM Package 3", syncml); + + *ret_resp_uri = resp_uri; + return syncml; +} + + +int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url) +{ + xml_node_t *syncml, *resp; + char *resp_uri = NULL; + int msgid = 0; + + if (url == NULL) { + wpa_printf(MSG_INFO, "Invalid prov command (missing URL)"); + return -1; + } + + wpa_printf(MSG_INFO, "OMA-DM credential provisioning requested"); + write_summary(ctx, "OMA-DM credential provisioning"); + + msgid++; + syncml = build_oma_dm_1_sub_reg(ctx, url, msgid); + if (syncml == NULL) + return -1; + + while (syncml) { + resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : url, + syncml, NULL, NULL, NULL, NULL, NULL); + if (resp == NULL) + return -1; + + msgid++; + syncml = oma_dm_process(ctx, url, resp, msgid, &resp_uri, + NULL, NULL); + xml_node_free(ctx->xml, resp); + } + + os_free(resp_uri); + + return ctx->pps_cred_set ? 0 : -1; +} + + +int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url) +{ + xml_node_t *syncml, *resp; + char *resp_uri = NULL; + int msgid = 0; + + if (url == NULL) { + wpa_printf(MSG_INFO, "Invalid prov command (missing URL)"); + return -1; + } + + wpa_printf(MSG_INFO, "OMA-DM SIM provisioning requested"); + ctx->no_reconnect = 2; + + wpa_printf(MSG_INFO, "Wait for IP address before starting SIM provisioning"); + write_summary(ctx, "Wait for IP address before starting SIM provisioning"); + + if (wait_ip_addr(ctx->ifname, 15) < 0) { + wpa_printf(MSG_INFO, "Could not get IP address for WLAN - try connection anyway"); + } + write_summary(ctx, "OMA-DM SIM provisioning"); + + msgid++; + syncml = build_oma_dm_1_sub_prov(ctx, url, msgid); + if (syncml == NULL) + return -1; + + while (syncml) { + resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : url, + syncml, NULL, NULL, NULL, NULL, NULL); + if (resp == NULL) + return -1; + + msgid++; + syncml = oma_dm_process(ctx, url, resp, msgid, &resp_uri, + NULL, NULL); + xml_node_free(ctx->xml, resp); + } + + os_free(resp_uri); + + if (ctx->pps_cred_set) { + wpa_printf(MSG_INFO, "Updating wpa_supplicant credentials"); + cmd_set_pps(ctx, ctx->pps_fname); + + wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration"); + write_summary(ctx, "Requesting reconnection with updated configuration"); + if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) { + wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect"); + write_summary(ctx, "Failed to request wpa_supplicant to reconnect"); + return -1; + } + } + + return ctx->pps_cred_set ? 0 : -1; +} + + +void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps) +{ + xml_node_t *syncml, *resp; + char *resp_uri = NULL; + int msgid = 0; + + wpa_printf(MSG_INFO, "OMA-DM policy update"); + write_summary(ctx, "OMA-DM policy update"); + + msgid++; + syncml = build_oma_dm_1_pol_upd(ctx, address, msgid); + if (syncml == NULL) + return; + + while (syncml) { + resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : address, + syncml, NULL, cred_username, + cred_password, client_cert, client_key); + if (resp == NULL) + return; + + msgid++; + syncml = oma_dm_process(ctx, address, resp, msgid, &resp_uri, + pps, pps_fname); + xml_node_free(ctx->xml, resp); + } + + os_free(resp_uri); + + if (ctx->pps_updated) { + wpa_printf(MSG_INFO, "Update wpa_supplicant credential based on updated PPS MO"); + write_summary(ctx, "Update wpa_supplicant credential based on updated PPS MO and request connection"); + cmd_set_pps(ctx, pps_fname); + if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) { + wpa_printf(MSG_INFO, + "Failed to request wpa_supplicant to reconnect"); + write_summary(ctx, + "Failed to request wpa_supplicant to reconnect"); + } + } +} + + +void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps) +{ + xml_node_t *syncml, *resp; + char *resp_uri = NULL; + int msgid = 0; + + wpa_printf(MSG_INFO, "OMA-DM subscription remediation"); + write_summary(ctx, "OMA-DM subscription remediation"); + + msgid++; + syncml = build_oma_dm_1_sub_rem(ctx, address, msgid); + if (syncml == NULL) + return; + + while (syncml) { + resp = oma_dm_send_recv(ctx, resp_uri ? resp_uri : address, + syncml, NULL, cred_username, + cred_password, client_cert, client_key); + if (resp == NULL) + return; + + msgid++; + syncml = oma_dm_process(ctx, address, resp, msgid, &resp_uri, + pps, pps_fname); + xml_node_free(ctx->xml, resp); + } + + os_free(resp_uri); + + wpa_printf(MSG_INFO, "Update wpa_supplicant credential based on updated PPS MO and request reconnection"); + write_summary(ctx, "Update wpa_supplicant credential based on updated PPS MO and request reconnection"); + cmd_set_pps(ctx, pps_fname); + if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) { + wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect"); + write_summary(ctx, "Failed to request wpa_supplicant to reconnect"); + } +} + + +void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname, + const char *add_fname) +{ + xml_node_t *pps, *add; + int res; + + ctx->fqdn = os_strdup("wi-fi.org"); + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "PPS file %s could not be parsed", + pps_fname); + return; + } + + add = node_from_file(ctx->xml, add_fname); + if (add == NULL) { + wpa_printf(MSG_INFO, "Add file %s could not be parsed", + add_fname); + xml_node_free(ctx->xml, pps); + return; + } + + res = oma_dm_add(ctx, add, pps, pps_fname); + wpa_printf(MSG_INFO, "oma_dm_add --> %d", res); + + xml_node_free(ctx->xml, pps); + xml_node_free(ctx->xml, add); +} + + +void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname, + const char *replace_fname) +{ + xml_node_t *pps, *replace; + int res; + + ctx->fqdn = os_strdup("wi-fi.org"); + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "PPS file %s could not be parsed", + pps_fname); + return; + } + + replace = node_from_file(ctx->xml, replace_fname); + if (replace == NULL) { + wpa_printf(MSG_INFO, "Replace file %s could not be parsed", + replace_fname); + xml_node_free(ctx->xml, pps); + return; + } + + res = oma_dm_replace(ctx, replace, pps, pps_fname); + wpa_printf(MSG_INFO, "oma_dm_replace --> %d", res); + + xml_node_free(ctx->xml, pps); + xml_node_free(ctx->xml, replace); +} diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c new file mode 100644 index 000000000000..11bf0db35e93 --- /dev/null +++ b/hs20/client/osu_client.c @@ -0,0 +1,3431 @@ +/* + * Hotspot 2.0 OSU client + * Copyright (c) 2012-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" +#include +#include +#ifdef ANDROID +#include "private/android_filesystem_config.h" +#endif /* ANDROID */ + +#include "common.h" +#include "utils/browser.h" +#include "utils/base64.h" +#include "utils/xml-utils.h" +#include "utils/http-utils.h" +#include "common/wpa_ctrl.h" +#include "common/wpa_helpers.h" +#include "eap_common/eap_defs.h" +#include "crypto/crypto.h" +#include "crypto/sha256.h" +#include "osu_client.h" + +const char *spp_xsd_fname = "spp.xsd"; + + +void write_result(struct hs20_osu_client *ctx, const char *fmt, ...) +{ + va_list ap; + FILE *f; + char buf[500]; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + write_summary(ctx, "%s", buf); + + if (!ctx->result_file) + return; + + f = fopen(ctx->result_file, "w"); + if (f == NULL) + return; + + va_start(ap, fmt); + vfprintf(f, fmt, ap); + va_end(ap); + fprintf(f, "\n"); + fclose(f); +} + + +void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...) +{ + va_list ap; + FILE *f; + + if (!ctx->summary_file) + return; + + f = fopen(ctx->summary_file, "a"); + if (f == NULL) + return; + + va_start(ap, fmt); + vfprintf(f, fmt, ap); + va_end(ap); + fprintf(f, "\n"); + fclose(f); +} + + +void debug_dump_node(struct hs20_osu_client *ctx, const char *title, + xml_node_t *node) +{ + char *str = xml_node_to_str(ctx->xml, node); + wpa_printf(MSG_DEBUG, "[hs20] %s: '%s'", title, str); + free(str); +} + + +static int valid_fqdn(const char *fqdn) +{ + const char *pos; + + /* TODO: could make this more complete.. */ + if (strchr(fqdn, '.') == 0 || strlen(fqdn) > 255) + return 0; + for (pos = fqdn; *pos; pos++) { + if (*pos >= 'a' && *pos <= 'z') + continue; + if (*pos >= 'A' && *pos <= 'Z') + continue; + if (*pos >= '0' && *pos <= '9') + continue; + if (*pos == '-' || *pos == '.' || *pos == '_') + continue; + return 0; + } + return 1; +} + + +static int android_update_permission(const char *path, mode_t mode) +{ +#ifdef ANDROID + /* we need to change file/folder permission for Android */ + + if (!path) { + wpa_printf(MSG_ERROR, "file path null"); + return -1; + } + + /* Allow processes running with Group ID as AID_WIFI, + * to read files from SP, SP/, Cert and osu-info directories */ + if (lchown(path, -1, AID_WIFI)) { + wpa_printf(MSG_INFO, "CTRL: Could not lchown directory: %s", + strerror(errno)); + return -1; + } + + if (chmod(path, mode) < 0) { + wpa_printf(MSG_INFO, "CTRL: Could not chmod directory: %s", + strerror(errno)); + return -1; + } +#endif /* ANDROID */ + + return 0; +} + + +int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert) +{ + xml_node_t *node; + char *url, *user = NULL, *pw = NULL; + char *proto; + int ret = -1; + + proto = xml_node_get_attr_value(ctx->xml, getcert, + "enrollmentProtocol"); + if (!proto) + return -1; + wpa_printf(MSG_INFO, "getCertificate - enrollmentProtocol=%s", proto); + write_summary(ctx, "getCertificate - enrollmentProtocol=%s", proto); + if (os_strcasecmp(proto, "EST") != 0) { + wpa_printf(MSG_INFO, "Unsupported enrollmentProtocol"); + xml_node_get_attr_value_free(ctx->xml, proto); + return -1; + } + xml_node_get_attr_value_free(ctx->xml, proto); + + node = get_node(ctx->xml, getcert, "enrollmentServerURI"); + if (node == NULL) { + wpa_printf(MSG_INFO, "Could not find enrollmentServerURI node"); + xml_node_get_attr_value_free(ctx->xml, proto); + return -1; + } + url = xml_node_get_text(ctx->xml, node); + if (url == NULL) { + wpa_printf(MSG_INFO, "Could not get URL text"); + return -1; + } + wpa_printf(MSG_INFO, "enrollmentServerURI: %s", url); + write_summary(ctx, "enrollmentServerURI: %s", url); + + node = get_node(ctx->xml, getcert, "estUserID"); + if (node == NULL && !ctx->client_cert_present) { + wpa_printf(MSG_INFO, "Could not find estUserID node"); + goto fail; + } + if (node) { + user = xml_node_get_text(ctx->xml, node); + if (user == NULL) { + wpa_printf(MSG_INFO, "Could not get estUserID text"); + goto fail; + } + wpa_printf(MSG_INFO, "estUserID: %s", user); + write_summary(ctx, "estUserID: %s", user); + } + + node = get_node(ctx->xml, getcert, "estPassword"); + if (node == NULL && !ctx->client_cert_present) { + wpa_printf(MSG_INFO, "Could not find estPassword node"); + goto fail; + } + if (node) { + pw = xml_node_get_base64_text(ctx->xml, node, NULL); + if (pw == NULL) { + wpa_printf(MSG_INFO, "Could not get estPassword text"); + goto fail; + } + wpa_printf(MSG_INFO, "estPassword: %s", pw); + } + + mkdir("Cert", S_IRWXU); + android_update_permission("Cert", S_IRWXU | S_IRWXG); + + if (est_load_cacerts(ctx, url) < 0 || + est_build_csr(ctx, url) < 0 || + est_simple_enroll(ctx, url, user, pw) < 0) + goto fail; + + ret = 0; +fail: + xml_node_get_text_free(ctx->xml, url); + xml_node_get_text_free(ctx->xml, user); + xml_node_get_text_free(ctx->xml, pw); + + return ret; +} + + +static int process_est_cert(struct hs20_osu_client *ctx, xml_node_t *cert, + const char *fqdn) +{ + u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN]; + char *der, *pem; + size_t der_len, pem_len; + char *fingerprint; + char buf[200]; + + wpa_printf(MSG_INFO, "PPS for certificate credential - fqdn=%s", fqdn); + + fingerprint = xml_node_get_text(ctx->xml, cert); + if (fingerprint == NULL) + return -1; + if (hexstr2bin(fingerprint, digest1, SHA256_MAC_LEN) < 0) { + wpa_printf(MSG_INFO, "Invalid SHA256 hash value"); + write_result(ctx, "Invalid client certificate SHA256 hash value in PPS"); + xml_node_get_text_free(ctx->xml, fingerprint); + return -1; + } + xml_node_get_text_free(ctx->xml, fingerprint); + + der = os_readfile("Cert/est_cert.der", &der_len); + if (der == NULL) { + wpa_printf(MSG_INFO, "Could not find client certificate from EST"); + write_result(ctx, "Could not find client certificate from EST"); + return -1; + } + + if (sha256_vector(1, (const u8 **) &der, &der_len, digest2) < 0) { + os_free(der); + return -1; + } + os_free(der); + + if (os_memcmp(digest1, digest2, sizeof(digest1)) != 0) { + wpa_printf(MSG_INFO, "Client certificate from EST does not match fingerprint from PPS MO"); + write_result(ctx, "Client certificate from EST does not match fingerprint from PPS MO"); + return -1; + } + + wpa_printf(MSG_INFO, "Client certificate from EST matches PPS MO"); + unlink("Cert/est_cert.der"); + + os_snprintf(buf, sizeof(buf), "SP/%s/client-ca.pem", fqdn); + if (rename("Cert/est-cacerts.pem", buf) < 0) { + wpa_printf(MSG_INFO, "Could not move est-cacerts.pem to client-ca.pem: %s", + strerror(errno)); + return -1; + } + pem = os_readfile(buf, &pem_len); + + os_snprintf(buf, sizeof(buf), "SP/%s/client-cert.pem", fqdn); + if (rename("Cert/est_cert.pem", buf) < 0) { + wpa_printf(MSG_INFO, "Could not move est_cert.pem to client-cert.pem: %s", + strerror(errno)); + os_free(pem); + return -1; + } + + if (pem) { + FILE *f = fopen(buf, "a"); + if (f) { + fwrite(pem, pem_len, 1, f); + fclose(f); + } + os_free(pem); + } + + os_snprintf(buf, sizeof(buf), "SP/%s/client-key.pem", fqdn); + if (rename("Cert/privkey-plain.pem", buf) < 0) { + wpa_printf(MSG_INFO, "Could not move privkey-plain.pem to client-key.pem: %s", + strerror(errno)); + return -1; + } + + unlink("Cert/est-req.b64"); + unlink("Cert/est-req.pem"); + rmdir("Cert"); + + return 0; +} + + +#define TMP_CERT_DL_FILE "tmp-cert-download" + +static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params, + const char *fname) +{ + xml_node_t *url_node, *hash_node; + char *url, *hash; + char *cert; + size_t len; + u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN]; + int res; + char *b64; + FILE *f; + + url_node = get_node(ctx->xml, params, "CertURL"); + hash_node = get_node(ctx->xml, params, "CertSHA256Fingerprint"); + if (url_node == NULL || hash_node == NULL) + return -1; + url = xml_node_get_text(ctx->xml, url_node); + hash = xml_node_get_text(ctx->xml, hash_node); + if (url == NULL || hash == NULL) { + xml_node_get_text_free(ctx->xml, url); + xml_node_get_text_free(ctx->xml, hash); + return -1; + } + + wpa_printf(MSG_INFO, "CertURL: %s", url); + wpa_printf(MSG_INFO, "SHA256 hash: %s", hash); + + if (hexstr2bin(hash, digest1, SHA256_MAC_LEN) < 0) { + wpa_printf(MSG_INFO, "Invalid SHA256 hash value"); + write_result(ctx, "Invalid SHA256 hash value for downloaded certificate"); + xml_node_get_text_free(ctx->xml, hash); + return -1; + } + xml_node_get_text_free(ctx->xml, hash); + + write_summary(ctx, "Download certificate from %s", url); + ctx->no_osu_cert_validation = 1; + http_ocsp_set(ctx->http, 1); + res = http_download_file(ctx->http, url, TMP_CERT_DL_FILE, NULL); + http_ocsp_set(ctx->http, + (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2); + ctx->no_osu_cert_validation = 0; + xml_node_get_text_free(ctx->xml, url); + if (res < 0) + return -1; + + cert = os_readfile(TMP_CERT_DL_FILE, &len); + remove(TMP_CERT_DL_FILE); + if (cert == NULL) + return -1; + + if (sha256_vector(1, (const u8 **) &cert, &len, digest2) < 0) { + os_free(cert); + return -1; + } + + if (os_memcmp(digest1, digest2, sizeof(digest1)) != 0) { + wpa_printf(MSG_INFO, "Downloaded certificate fingerprint did not match"); + write_result(ctx, "Downloaded certificate fingerprint did not match"); + os_free(cert); + return -1; + } + + b64 = base64_encode(cert, len, NULL); + os_free(cert); + if (b64 == NULL) + return -1; + + f = fopen(fname, "wb"); + if (f == NULL) { + os_free(b64); + return -1; + } + + fprintf(f, "-----BEGIN CERTIFICATE-----\n" + "%s" + "-----END CERTIFICATE-----\n", + b64); + + os_free(b64); + fclose(f); + + wpa_printf(MSG_INFO, "Downloaded certificate into %s and validated fingerprint", + fname); + write_summary(ctx, "Downloaded certificate into %s and validated fingerprint", + fname); + + return 0; +} + + +static int cmd_dl_osu_ca(struct hs20_osu_client *ctx, const char *pps_fname, + const char *ca_fname) +{ + xml_node_t *pps, *node; + int ret; + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "Could not read or parse '%s'", pps_fname); + return -1; + } + + node = get_child_node(ctx->xml, pps, + "SubscriptionUpdate/TrustRoot"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No SubscriptionUpdate/TrustRoot/CertURL found from PPS"); + xml_node_free(ctx->xml, pps); + return -1; + } + + ret = download_cert(ctx, node, ca_fname); + xml_node_free(ctx->xml, pps); + + return ret; +} + + +static int cmd_dl_polupd_ca(struct hs20_osu_client *ctx, const char *pps_fname, + const char *ca_fname) +{ + xml_node_t *pps, *node; + int ret; + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "Could not read or parse '%s'", pps_fname); + return -1; + } + + node = get_child_node(ctx->xml, pps, + "Policy/PolicyUpdate/TrustRoot"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No Policy/PolicyUpdate/TrustRoot/CertURL found from PPS"); + xml_node_free(ctx->xml, pps); + return -2; + } + + ret = download_cert(ctx, node, ca_fname); + xml_node_free(ctx->xml, pps); + + return ret; +} + + +static int cmd_dl_aaa_ca(struct hs20_osu_client *ctx, const char *pps_fname, + const char *ca_fname) +{ + xml_node_t *pps, *node, *aaa; + int ret; + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "Could not read or parse '%s'", pps_fname); + return -1; + } + + node = get_child_node(ctx->xml, pps, + "AAAServerTrustRoot"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No AAAServerTrustRoot/CertURL found from PPS"); + xml_node_free(ctx->xml, pps); + return -2; + } + + aaa = xml_node_first_child(ctx->xml, node); + if (aaa == NULL) { + wpa_printf(MSG_INFO, "No AAAServerTrustRoot/CertURL found from PPS"); + xml_node_free(ctx->xml, pps); + return -1; + } + + ret = download_cert(ctx, aaa, ca_fname); + xml_node_free(ctx->xml, pps); + + return ret; +} + + +static int download_trust_roots(struct hs20_osu_client *ctx, + const char *pps_fname) +{ + char *dir, *pos; + char fname[300]; + int ret, ret1; + + dir = os_strdup(pps_fname); + if (dir == NULL) + return -1; + pos = os_strrchr(dir, '/'); + if (pos == NULL) { + os_free(dir); + return -1; + } + *pos = '\0'; + + snprintf(fname, sizeof(fname), "%s/ca.pem", dir); + ret = cmd_dl_osu_ca(ctx, pps_fname, fname); + snprintf(fname, sizeof(fname), "%s/polupd-ca.pem", dir); + ret1 = cmd_dl_polupd_ca(ctx, pps_fname, fname); + if (ret == 0 && ret1 == -1) + ret = -1; + snprintf(fname, sizeof(fname), "%s/aaa-ca.pem", dir); + ret1 = cmd_dl_aaa_ca(ctx, pps_fname, fname); + if (ret == 0 && ret1 == -1) + ret = -1; + + os_free(dir); + + return ret; +} + + +static int server_dnsname_suffix_match(struct hs20_osu_client *ctx, + const char *fqdn) +{ + size_t match_len, len, i; + const char *val; + + match_len = os_strlen(fqdn); + + for (i = 0; i < ctx->server_dnsname_count; i++) { + wpa_printf(MSG_INFO, + "Checking suffix match against server dNSName %s", + ctx->server_dnsname[i]); + val = ctx->server_dnsname[i]; + len = os_strlen(val); + + if (match_len > len) + continue; + + if (os_strncasecmp(val + len - match_len, fqdn, match_len) != 0) + continue; /* no match */ + + if (match_len == len) + return 1; /* exact match */ + + if (val[len - match_len - 1] == '.') + return 1; /* full label match completes suffix match */ + + /* Reject due to incomplete label match */ + } + + /* None of the dNSName(s) matched */ + return 0; +} + + +int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri, + xml_node_t *add_mo, char *fname, size_t fname_len) +{ + char *str; + char *fqdn, *pos; + xml_node_t *tnds, *mo, *cert; + const char *name; + int ret; + + if (strncmp(uri, "./Wi-Fi/", 8) != 0) { + wpa_printf(MSG_INFO, "Unsupported location for addMO to add PPS MO: '%s'", + uri); + write_result(ctx, "Unsupported location for addMO to add PPS MO: '%s'", + uri); + return -1; + } + + fqdn = strdup(uri + 8); + if (fqdn == NULL) + return -1; + pos = strchr(fqdn, '/'); + if (pos) { + if (os_strcasecmp(pos, "/PerProviderSubscription") != 0) { + wpa_printf(MSG_INFO, "Unsupported location for addMO to add PPS MO (extra directory): '%s'", + uri); + write_result(ctx, "Unsupported location for addMO to " + "add PPS MO (extra directory): '%s'", uri); + free(fqdn); + return -1; + } + *pos = '\0'; /* remove trailing slash and PPS node name */ + } + wpa_printf(MSG_INFO, "SP FQDN: %s", fqdn); + + if (!server_dnsname_suffix_match(ctx, fqdn)) { + wpa_printf(MSG_INFO, + "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values, count: %d", + fqdn, (int) ctx->server_dnsname_count); + write_result(ctx, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values", + fqdn); + free(fqdn); + return -1; + } + + if (!valid_fqdn(fqdn)) { + wpa_printf(MSG_INFO, "Invalid FQDN '%s'", fqdn); + write_result(ctx, "Invalid FQDN '%s'", fqdn); + free(fqdn); + return -1; + } + + mkdir("SP", S_IRWXU); + snprintf(fname, fname_len, "SP/%s", fqdn); + if (mkdir(fname, S_IRWXU) < 0) { + if (errno != EEXIST) { + int err = errno; + wpa_printf(MSG_INFO, "mkdir(%s) failed: %s", + fname, strerror(err)); + free(fqdn); + return -1; + } + } + + android_update_permission("SP", S_IRWXU | S_IRWXG); + android_update_permission(fname, S_IRWXU | S_IRWXG); + + snprintf(fname, fname_len, "SP/%s/pps.xml", fqdn); + + if (os_file_exists(fname)) { + wpa_printf(MSG_INFO, "PPS file '%s' exists - reject addMO", + fname); + write_result(ctx, "PPS file '%s' exists - reject addMO", + fname); + free(fqdn); + return -2; + } + wpa_printf(MSG_INFO, "Using PPS file: %s", fname); + + str = xml_node_get_text(ctx->xml, add_mo); + if (str == NULL) { + wpa_printf(MSG_INFO, "Could not extract MO text"); + free(fqdn); + return -1; + } + wpa_printf(MSG_DEBUG, "[hs20] addMO text: '%s'", str); + + tnds = xml_node_from_buf(ctx->xml, str); + xml_node_get_text_free(ctx->xml, str); + if (tnds == NULL) { + wpa_printf(MSG_INFO, "[hs20] Could not parse addMO text"); + free(fqdn); + return -1; + } + + mo = tnds_to_mo(ctx->xml, tnds); + if (mo == NULL) { + wpa_printf(MSG_INFO, "[hs20] Could not parse addMO TNDS text"); + free(fqdn); + return -1; + } + + debug_dump_node(ctx, "Parsed TNDS", mo); + + name = xml_node_get_localname(ctx->xml, mo); + if (os_strcasecmp(name, "PerProviderSubscription") != 0) { + wpa_printf(MSG_INFO, "[hs20] Unexpected PPS MO root node name '%s'", + name); + free(fqdn); + return -1; + } + + cert = get_child_node(ctx->xml, mo, + "Credential/DigitalCertificate/" + "CertSHA256Fingerprint"); + if (cert && process_est_cert(ctx, cert, fqdn) < 0) { + xml_node_free(ctx->xml, mo); + free(fqdn); + return -1; + } + free(fqdn); + + if (node_to_file(ctx->xml, fname, mo) < 0) { + wpa_printf(MSG_INFO, "Could not write MO to file"); + xml_node_free(ctx->xml, mo); + return -1; + } + xml_node_free(ctx->xml, mo); + + wpa_printf(MSG_INFO, "A new PPS MO added as '%s'", fname); + write_summary(ctx, "A new PPS MO added as '%s'", fname); + + ret = download_trust_roots(ctx, fname); + if (ret < 0) { + wpa_printf(MSG_INFO, "Remove invalid PPS MO file"); + write_summary(ctx, "Remove invalid PPS MO file"); + unlink(fname); + } + + return ret; +} + + +int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname, + xml_node_t *pps) +{ + char *str; + FILE *f; + char backup[300]; + + if (ctx->client_cert_present) { + xml_node_t *cert; + cert = get_child_node(ctx->xml, pps, + "Credential/DigitalCertificate/" + "CertSHA256Fingerprint"); + if (cert && os_file_exists("Cert/est_cert.der") && + process_est_cert(ctx, cert, ctx->fqdn) < 0) { + wpa_printf(MSG_INFO, "EST certificate update processing failed on PPS MO update"); + return -1; + } + } + + wpa_printf(MSG_INFO, "Updating PPS MO %s", pps_fname); + + str = xml_node_to_str(ctx->xml, pps); + if (str == NULL) { + wpa_printf(MSG_ERROR, "No node found"); + return -1; + } + wpa_printf(MSG_MSGDUMP, "[hs20] Updated PPS: '%s'", str); + + snprintf(backup, sizeof(backup), "%s.bak", pps_fname); + rename(pps_fname, backup); + f = fopen(pps_fname, "w"); + if (f == NULL) { + wpa_printf(MSG_INFO, "Could not write PPS"); + rename(backup, pps_fname); + free(str); + return -1; + } + fprintf(f, "%s\n", str); + fclose(f); + + free(str); + + return 0; +} + + +void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps, + const char *alt_loc, char **user, char **pw) +{ + xml_node_t *node; + + node = get_child_node(ctx->xml, pps, + "Credential/UsernamePassword/Username"); + if (node) + *user = xml_node_get_text(ctx->xml, node); + + node = get_child_node(ctx->xml, pps, + "Credential/UsernamePassword/Password"); + if (node) + *pw = xml_node_get_base64_text(ctx->xml, node, NULL); + + node = get_child_node(ctx->xml, pps, alt_loc); + if (node) { + xml_node_t *a; + a = get_node(ctx->xml, node, "Username"); + if (a) { + xml_node_get_text_free(ctx->xml, *user); + *user = xml_node_get_text(ctx->xml, a); + wpa_printf(MSG_INFO, "Use OSU username '%s'", *user); + } + + a = get_node(ctx->xml, node, "Password"); + if (a) { + free(*pw); + *pw = xml_node_get_base64_text(ctx->xml, a, NULL); + wpa_printf(MSG_INFO, "Use OSU password"); + } + } +} + + +/* Remove old credentials based on HomeSP/FQDN */ +static void remove_sp_creds(struct hs20_osu_client *ctx, const char *fqdn) +{ + char cmd[300]; + os_snprintf(cmd, sizeof(cmd), "REMOVE_CRED provisioning_sp=%s", fqdn); + if (wpa_command(ctx->ifname, cmd) < 0) + wpa_printf(MSG_INFO, "Failed to remove old credential(s)"); +} + + +static void set_pps_cred_policy_spe(struct hs20_osu_client *ctx, int id, + xml_node_t *spe) +{ + xml_node_t *ssid; + char *txt; + + ssid = get_node(ctx->xml, spe, "SSID"); + if (ssid == NULL) + return; + txt = xml_node_get_text(ctx->xml, ssid); + if (txt == NULL) + return; + wpa_printf(MSG_DEBUG, "- Policy/SPExclusionList//SSID = %s", txt); + if (set_cred_quoted(ctx->ifname, id, "excluded_ssid", txt) < 0) + wpa_printf(MSG_INFO, "Failed to set cred excluded_ssid"); + xml_node_get_text_free(ctx->xml, txt); +} + + +static void set_pps_cred_policy_spel(struct hs20_osu_client *ctx, int id, + xml_node_t *spel) +{ + xml_node_t *child; + + xml_node_for_each_child(ctx->xml, child, spel) { + xml_node_for_each_check(ctx->xml, child); + set_pps_cred_policy_spe(ctx, id, child); + } +} + + +static void set_pps_cred_policy_prp(struct hs20_osu_client *ctx, int id, + xml_node_t *prp) +{ + xml_node_t *node; + char *txt = NULL, *pos; + char *prio, *country_buf = NULL; + const char *country; + char val[200]; + int priority; + + node = get_node(ctx->xml, prp, "Priority"); + if (node == NULL) + return; + prio = xml_node_get_text(ctx->xml, node); + if (prio == NULL) + return; + wpa_printf(MSG_INFO, "- Policy/PreferredRoamingPartnerList//Priority = %s", + prio); + priority = atoi(prio); + xml_node_get_text_free(ctx->xml, prio); + + node = get_node(ctx->xml, prp, "Country"); + if (node) { + country_buf = xml_node_get_text(ctx->xml, node); + if (country_buf == NULL) + return; + country = country_buf; + wpa_printf(MSG_INFO, "- Policy/PreferredRoamingPartnerList//Country = %s", + country); + } else { + country = "*"; + } + + node = get_node(ctx->xml, prp, "FQDN_Match"); + if (node == NULL) + goto out; + txt = xml_node_get_text(ctx->xml, node); + if (txt == NULL) + goto out; + wpa_printf(MSG_INFO, "- Policy/PreferredRoamingPartnerList//FQDN_Match = %s", + txt); + pos = strrchr(txt, ','); + if (pos == NULL) + goto out; + *pos++ = '\0'; + + snprintf(val, sizeof(val), "%s,%d,%d,%s", txt, + strcmp(pos, "includeSubdomains") != 0, priority, country); + if (set_cred_quoted(ctx->ifname, id, "roaming_partner", val) < 0) + wpa_printf(MSG_INFO, "Failed to set cred roaming_partner"); +out: + xml_node_get_text_free(ctx->xml, country_buf); + xml_node_get_text_free(ctx->xml, txt); +} + + +static void set_pps_cred_policy_prpl(struct hs20_osu_client *ctx, int id, + xml_node_t *prpl) +{ + xml_node_t *child; + + xml_node_for_each_child(ctx->xml, child, prpl) { + xml_node_for_each_check(ctx->xml, child); + set_pps_cred_policy_prp(ctx, id, child); + } +} + + +static void set_pps_cred_policy_min_backhaul(struct hs20_osu_client *ctx, int id, + xml_node_t *min_backhaul) +{ + xml_node_t *node; + char *type, *dl = NULL, *ul = NULL; + int home; + + node = get_node(ctx->xml, min_backhaul, "NetworkType"); + if (node == NULL) { + wpa_printf(MSG_INFO, "Ignore MinBackhaulThreshold without mandatory NetworkType node"); + return; + } + + type = xml_node_get_text(ctx->xml, node); + if (type == NULL) + return; + wpa_printf(MSG_INFO, "- Policy/MinBackhaulThreshold//NetworkType = %s", + type); + if (os_strcasecmp(type, "home") == 0) + home = 1; + else if (os_strcasecmp(type, "roaming") == 0) + home = 0; + else { + wpa_printf(MSG_INFO, "Ignore MinBackhaulThreshold with invalid NetworkType"); + xml_node_get_text_free(ctx->xml, type); + return; + } + xml_node_get_text_free(ctx->xml, type); + + node = get_node(ctx->xml, min_backhaul, "DLBandwidth"); + if (node) + dl = xml_node_get_text(ctx->xml, node); + + node = get_node(ctx->xml, min_backhaul, "ULBandwidth"); + if (node) + ul = xml_node_get_text(ctx->xml, node); + + if (dl == NULL && ul == NULL) { + wpa_printf(MSG_INFO, "Ignore MinBackhaulThreshold without either DLBandwidth or ULBandwidth nodes"); + return; + } + + if (dl) + wpa_printf(MSG_INFO, "- Policy/MinBackhaulThreshold//DLBandwidth = %s", + dl); + if (ul) + wpa_printf(MSG_INFO, "- Policy/MinBackhaulThreshold//ULBandwidth = %s", + ul); + + if (home) { + if (dl && + set_cred(ctx->ifname, id, "min_dl_bandwidth_home", dl) < 0) + wpa_printf(MSG_INFO, "Failed to set cred bandwidth limit"); + if (ul && + set_cred(ctx->ifname, id, "min_ul_bandwidth_home", ul) < 0) + wpa_printf(MSG_INFO, "Failed to set cred bandwidth limit"); + } else { + if (dl && + set_cred(ctx->ifname, id, "min_dl_bandwidth_roaming", dl) < + 0) + wpa_printf(MSG_INFO, "Failed to set cred bandwidth limit"); + if (ul && + set_cred(ctx->ifname, id, "min_ul_bandwidth_roaming", ul) < + 0) + wpa_printf(MSG_INFO, "Failed to set cred bandwidth limit"); + } + + xml_node_get_text_free(ctx->xml, dl); + xml_node_get_text_free(ctx->xml, ul); +} + + +static void set_pps_cred_policy_min_backhaul_list(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + xml_node_t *child; + + wpa_printf(MSG_INFO, "- Policy/MinBackhaulThreshold"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + set_pps_cred_policy_min_backhaul(ctx, id, child); + } +} + + +static void set_pps_cred_policy_update(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + wpa_printf(MSG_INFO, "- Policy/PolicyUpdate"); + /* Not used in wpa_supplicant */ +} + + +static void set_pps_cred_policy_required_proto_port(struct hs20_osu_client *ctx, + int id, xml_node_t *tuple) +{ + xml_node_t *node; + char *proto, *port; + char *buf; + size_t buflen; + + node = get_node(ctx->xml, tuple, "IPProtocol"); + if (node == NULL) { + wpa_printf(MSG_INFO, "Ignore RequiredProtoPortTuple without mandatory IPProtocol node"); + return; + } + + proto = xml_node_get_text(ctx->xml, node); + if (proto == NULL) + return; + + wpa_printf(MSG_INFO, "- Policy/RequiredProtoPortTuple//IPProtocol = %s", + proto); + + node = get_node(ctx->xml, tuple, "PortNumber"); + port = node ? xml_node_get_text(ctx->xml, node) : NULL; + if (port) { + wpa_printf(MSG_INFO, "- Policy/RequiredProtoPortTuple//PortNumber = %s", + port); + buflen = os_strlen(proto) + os_strlen(port) + 10; + buf = os_malloc(buflen); + if (buf) + os_snprintf(buf, buflen, "%s:%s", proto, port); + xml_node_get_text_free(ctx->xml, port); + } else { + buflen = os_strlen(proto) + 10; + buf = os_malloc(buflen); + if (buf) + os_snprintf(buf, buflen, "%s", proto); + } + + xml_node_get_text_free(ctx->xml, proto); + + if (buf == NULL) + return; + + if (set_cred(ctx->ifname, id, "req_conn_capab", buf) < 0) + wpa_printf(MSG_INFO, "Could not set req_conn_capab"); + + os_free(buf); +} + + +static void set_pps_cred_policy_required_proto_ports(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + xml_node_t *child; + + wpa_printf(MSG_INFO, "- Policy/RequiredProtoPortTuple"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + set_pps_cred_policy_required_proto_port(ctx, id, child); + } +} + + +static void set_pps_cred_policy_max_bss_load(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- Policy/MaximumBSSLoadValue - %s", str); + if (set_cred(ctx->ifname, id, "max_bss_load", str) < 0) + wpa_printf(MSG_INFO, "Failed to set cred max_bss_load limit"); + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_policy(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + xml_node_t *child; + const char *name; + + wpa_printf(MSG_INFO, "- Policy"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "PreferredRoamingPartnerList") == 0) + set_pps_cred_policy_prpl(ctx, id, child); + else if (os_strcasecmp(name, "MinBackhaulThreshold") == 0) + set_pps_cred_policy_min_backhaul_list(ctx, id, child); + else if (os_strcasecmp(name, "PolicyUpdate") == 0) + set_pps_cred_policy_update(ctx, id, child); + else if (os_strcasecmp(name, "SPExclusionList") == 0) + set_pps_cred_policy_spel(ctx, id, child); + else if (os_strcasecmp(name, "RequiredProtoPortTuple") == 0) + set_pps_cred_policy_required_proto_ports(ctx, id, child); + else if (os_strcasecmp(name, "MaximumBSSLoadValue") == 0) + set_pps_cred_policy_max_bss_load(ctx, id, child); + else + wpa_printf(MSG_INFO, "Unknown Policy node '%s'", name); + } +} + + +static void set_pps_cred_priority(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- CredentialPriority = %s", str); + if (set_cred(ctx->ifname, id, "sp_priority", str) < 0) + wpa_printf(MSG_INFO, "Failed to set cred sp_priority"); + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_aaa_server_trust_root(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + wpa_printf(MSG_INFO, "- AAAServerTrustRoot - TODO"); +} + + +static void set_pps_cred_sub_update(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + wpa_printf(MSG_INFO, "- SubscriptionUpdate"); + /* not used within wpa_supplicant */ +} + + +static void set_pps_cred_home_sp_network_id(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + xml_node_t *ssid_node, *hessid_node; + char *ssid, *hessid; + + ssid_node = get_node(ctx->xml, node, "SSID"); + if (ssid_node == NULL) { + wpa_printf(MSG_INFO, "Ignore HomeSP/NetworkID without mandatory SSID node"); + return; + } + + hessid_node = get_node(ctx->xml, node, "HESSID"); + + ssid = xml_node_get_text(ctx->xml, ssid_node); + if (ssid == NULL) + return; + hessid = hessid_node ? xml_node_get_text(ctx->xml, hessid_node) : NULL; + + wpa_printf(MSG_INFO, "- HomeSP/NetworkID//SSID = %s", ssid); + if (hessid) + wpa_printf(MSG_INFO, "- HomeSP/NetworkID//HESSID = %s", + hessid); + + /* TODO: Configure to wpa_supplicant */ + + xml_node_get_text_free(ctx->xml, ssid); + xml_node_get_text_free(ctx->xml, hessid); +} + + +static void set_pps_cred_home_sp_network_ids(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + xml_node_t *child; + + wpa_printf(MSG_INFO, "- HomeSP/NetworkID"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + set_pps_cred_home_sp_network_id(ctx, id, child); + } +} + + +static void set_pps_cred_home_sp_friendly_name(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- HomeSP/FriendlyName = %s", str); + /* not used within wpa_supplicant(?) */ + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_home_sp_icon_url(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- HomeSP/IconURL = %s", str); + /* not used within wpa_supplicant */ + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_home_sp_fqdn(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- HomeSP/FQDN = %s", str); + if (set_cred_quoted(ctx->ifname, id, "domain", str) < 0) + wpa_printf(MSG_INFO, "Failed to set cred domain"); + if (set_cred_quoted(ctx->ifname, id, "domain_suffix_match", str) < 0) + wpa_printf(MSG_INFO, "Failed to set cred domain_suffix_match"); + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_home_sp_oi(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + xml_node_t *child; + const char *name; + char *homeoi = NULL; + int required = 0; + char *str; + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (strcasecmp(name, "HomeOI") == 0 && !homeoi) { + homeoi = xml_node_get_text(ctx->xml, child); + wpa_printf(MSG_INFO, "- HomeSP/HomeOIList//HomeOI = %s", + homeoi); + } else if (strcasecmp(name, "HomeOIRequired") == 0) { + str = xml_node_get_text(ctx->xml, child); + wpa_printf(MSG_INFO, "- HomeSP/HomeOIList//HomeOIRequired = '%s'", + str); + if (str == NULL) + continue; + required = strcasecmp(str, "true") == 0; + xml_node_get_text_free(ctx->xml, str); + } else + wpa_printf(MSG_INFO, "Unknown HomeOIList node '%s'", + name); + } + + if (homeoi == NULL) { + wpa_printf(MSG_INFO, "- HomeSP/HomeOIList/ without HomeOI ignored"); + return; + } + + wpa_printf(MSG_INFO, "- HomeSP/HomeOIList/ '%s' required=%d", + homeoi, required); + + if (required) { + if (set_cred(ctx->ifname, id, "required_roaming_consortium", + homeoi) < 0) + wpa_printf(MSG_INFO, "Failed to set cred required_roaming_consortium"); + } else { + if (set_cred(ctx->ifname, id, "roaming_consortium", homeoi) < 0) + wpa_printf(MSG_INFO, "Failed to set cred roaming_consortium"); + } + + xml_node_get_text_free(ctx->xml, homeoi); +} + + +static void set_pps_cred_home_sp_oi_list(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + xml_node_t *child; + + wpa_printf(MSG_INFO, "- HomeSP/HomeOIList"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + set_pps_cred_home_sp_oi(ctx, id, child); + } +} + + +static void set_pps_cred_home_sp_other_partner(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + xml_node_t *child; + const char *name; + char *fqdn = NULL; + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "FQDN") == 0 && !fqdn) { + fqdn = xml_node_get_text(ctx->xml, child); + wpa_printf(MSG_INFO, "- HomeSP/OtherHomePartners//FQDN = %s", + fqdn); + } else + wpa_printf(MSG_INFO, "Unknown OtherHomePartners node '%s'", + name); + } + + if (fqdn == NULL) { + wpa_printf(MSG_INFO, "- HomeSP/OtherHomePartners/ without FQDN ignored"); + return; + } + + if (set_cred_quoted(ctx->ifname, id, "domain", fqdn) < 0) + wpa_printf(MSG_INFO, "Failed to set cred domain for OtherHomePartners node"); + + xml_node_get_text_free(ctx->xml, fqdn); +} + + +static void set_pps_cred_home_sp_other_partners(struct hs20_osu_client *ctx, + int id, + xml_node_t *node) +{ + xml_node_t *child; + + wpa_printf(MSG_INFO, "- HomeSP/OtherHomePartners"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + set_pps_cred_home_sp_other_partner(ctx, id, child); + } +} + + +static void set_pps_cred_home_sp_roaming_consortium_oi( + struct hs20_osu_client *ctx, int id, xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- HomeSP/RoamingConsortiumOI = %s", str); + if (set_cred_quoted(ctx->ifname, id, "roaming_consortiums", + str) < 0) + wpa_printf(MSG_INFO, "Failed to set cred roaming_consortiums"); + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_home_sp(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + xml_node_t *child; + const char *name; + + wpa_printf(MSG_INFO, "- HomeSP"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "NetworkID") == 0) + set_pps_cred_home_sp_network_ids(ctx, id, child); + else if (os_strcasecmp(name, "FriendlyName") == 0) + set_pps_cred_home_sp_friendly_name(ctx, id, child); + else if (os_strcasecmp(name, "IconURL") == 0) + set_pps_cred_home_sp_icon_url(ctx, id, child); + else if (os_strcasecmp(name, "FQDN") == 0) + set_pps_cred_home_sp_fqdn(ctx, id, child); + else if (os_strcasecmp(name, "HomeOIList") == 0) + set_pps_cred_home_sp_oi_list(ctx, id, child); + else if (os_strcasecmp(name, "OtherHomePartners") == 0) + set_pps_cred_home_sp_other_partners(ctx, id, child); + else if (os_strcasecmp(name, "RoamingConsortiumOI") == 0) + set_pps_cred_home_sp_roaming_consortium_oi(ctx, id, + child); + else + wpa_printf(MSG_INFO, "Unknown HomeSP node '%s'", name); + } +} + + +static void set_pps_cred_sub_params(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + wpa_printf(MSG_INFO, "- SubscriptionParameters"); + /* not used within wpa_supplicant */ +} + + +static void set_pps_cred_creation_date(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- Credential/CreationDate = %s", str); + /* not used within wpa_supplicant */ + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_expiration_date(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- Credential/ExpirationDate = %s", str); + /* not used within wpa_supplicant */ + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_username(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- Credential/UsernamePassword/Username = %s", + str); + if (set_cred_quoted(ctx->ifname, id, "username", str) < 0) + wpa_printf(MSG_INFO, "Failed to set cred username"); + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_password(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + int len, i; + char *pw, *hex, *pos, *end; + + pw = xml_node_get_base64_text(ctx->xml, node, &len); + if (pw == NULL) + return; + + wpa_printf(MSG_INFO, "- Credential/UsernamePassword/Password = %s", pw); + + hex = malloc(len * 2 + 1); + if (hex == NULL) { + free(pw); + return; + } + end = hex + len * 2 + 1; + pos = hex; + for (i = 0; i < len; i++) { + snprintf(pos, end - pos, "%02x", pw[i]); + pos += 2; + } + free(pw); + + if (set_cred(ctx->ifname, id, "password", hex) < 0) + wpa_printf(MSG_INFO, "Failed to set cred password"); + free(hex); +} + + +static void set_pps_cred_machine_managed(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- Credential/UsernamePassword/MachineManaged = %s", + str); + /* not used within wpa_supplicant */ + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_soft_token_app(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- Credential/UsernamePassword/SoftTokenApp = %s", + str); + /* not used within wpa_supplicant */ + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_able_to_share(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + if (str == NULL) + return; + wpa_printf(MSG_INFO, "- Credential/UsernamePassword/AbleToShare = %s", + str); + /* not used within wpa_supplicant */ + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_eap_method_eap_type(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + int type; + const char *eap_method = NULL; + + if (!str) + return; + wpa_printf(MSG_INFO, + "- Credential/UsernamePassword/EAPMethod/EAPType = %s", str); + type = atoi(str); + switch (type) { + case EAP_TYPE_TLS: + eap_method = "TLS"; + break; + case EAP_TYPE_TTLS: + eap_method = "TTLS"; + break; + case EAP_TYPE_PEAP: + eap_method = "PEAP"; + break; + case EAP_TYPE_PWD: + eap_method = "PWD"; + break; + } + xml_node_get_text_free(ctx->xml, str); + if (!eap_method) { + wpa_printf(MSG_INFO, "Unknown EAPType value"); + return; + } + + if (set_cred(ctx->ifname, id, "eap", eap_method) < 0) + wpa_printf(MSG_INFO, "Failed to set cred eap"); +} + + +static void set_pps_cred_eap_method_inner_method(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + const char *phase2 = NULL; + + if (!str) + return; + wpa_printf(MSG_INFO, + "- Credential/UsernamePassword/EAPMethod/InnerMethod = %s", + str); + if (os_strcmp(str, "PAP") == 0) + phase2 = "auth=PAP"; + else if (os_strcmp(str, "CHAP") == 0) + phase2 = "auth=CHAP"; + else if (os_strcmp(str, "MS-CHAP") == 0) + phase2 = "auth=MSCHAP"; + else if (os_strcmp(str, "MS-CHAP-V2") == 0) + phase2 = "auth=MSCHAPV2"; + xml_node_get_text_free(ctx->xml, str); + if (!phase2) { + wpa_printf(MSG_INFO, "Unknown InnerMethod value"); + return; + } + + if (set_cred_quoted(ctx->ifname, id, "phase2", phase2) < 0) + wpa_printf(MSG_INFO, "Failed to set cred phase2"); +} + + +static void set_pps_cred_eap_method(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + xml_node_t *child; + const char *name; + + wpa_printf(MSG_INFO, "- Credential/UsernamePassword/EAPMethod"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "EAPType") == 0) + set_pps_cred_eap_method_eap_type(ctx, id, child); + else if (os_strcasecmp(name, "InnerMethod") == 0) + set_pps_cred_eap_method_inner_method(ctx, id, child); + else + wpa_printf(MSG_INFO, "Unknown Credential/UsernamePassword/EAPMethod node '%s'", + name); + } +} + + +static void set_pps_cred_username_password(struct hs20_osu_client *ctx, int id, + xml_node_t *node) +{ + xml_node_t *child; + const char *name; + + wpa_printf(MSG_INFO, "- Credential/UsernamePassword"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "Username") == 0) + set_pps_cred_username(ctx, id, child); + else if (os_strcasecmp(name, "Password") == 0) + set_pps_cred_password(ctx, id, child); + else if (os_strcasecmp(name, "MachineManaged") == 0) + set_pps_cred_machine_managed(ctx, id, child); + else if (os_strcasecmp(name, "SoftTokenApp") == 0) + set_pps_cred_soft_token_app(ctx, id, child); + else if (os_strcasecmp(name, "AbleToShare") == 0) + set_pps_cred_able_to_share(ctx, id, child); + else if (os_strcasecmp(name, "EAPMethod") == 0) + set_pps_cred_eap_method(ctx, id, child); + else + wpa_printf(MSG_INFO, "Unknown Credential/UsernamePassword node '%s'", + name); + } +} + + +static void set_pps_cred_digital_cert(struct hs20_osu_client *ctx, int id, + xml_node_t *node, const char *fqdn) +{ + char buf[200], dir[200]; + int res; + + wpa_printf(MSG_INFO, "- Credential/DigitalCertificate"); + + if (getcwd(dir, sizeof(dir)) == NULL) + return; + + /* TODO: could build username from Subject of Subject AltName */ + if (set_cred_quoted(ctx->ifname, id, "username", "cert") < 0) { + wpa_printf(MSG_INFO, "Failed to set username"); + } + + res = os_snprintf(buf, sizeof(buf), "%s/SP/%s/client-cert.pem", dir, + fqdn); + if (os_snprintf_error(sizeof(buf), res)) + return; + if (os_file_exists(buf)) { + if (set_cred_quoted(ctx->ifname, id, "client_cert", buf) < 0) { + wpa_printf(MSG_INFO, "Failed to set client_cert"); + } + } + + res = os_snprintf(buf, sizeof(buf), "%s/SP/%s/client-key.pem", dir, + fqdn); + if (os_snprintf_error(sizeof(buf), res)) + return; + if (os_file_exists(buf)) { + if (set_cred_quoted(ctx->ifname, id, "private_key", buf) < 0) { + wpa_printf(MSG_INFO, "Failed to set private_key"); + } + } +} + + +static void set_pps_cred_realm(struct hs20_osu_client *ctx, int id, + xml_node_t *node, const char *fqdn, int sim) +{ + char *str = xml_node_get_text(ctx->xml, node); + char buf[200], dir[200]; + int res; + + if (str == NULL) + return; + + wpa_printf(MSG_INFO, "- Credential/Realm = %s", str); + if (set_cred_quoted(ctx->ifname, id, "realm", str) < 0) + wpa_printf(MSG_INFO, "Failed to set cred realm"); + xml_node_get_text_free(ctx->xml, str); + + if (sim) + return; + + if (getcwd(dir, sizeof(dir)) == NULL) + return; + res = os_snprintf(buf, sizeof(buf), "%s/SP/%s/aaa-ca.pem", dir, fqdn); + if (os_snprintf_error(sizeof(buf), res)) + return; + if (os_file_exists(buf)) { + if (set_cred_quoted(ctx->ifname, id, "ca_cert", buf) < 0) { + wpa_printf(MSG_INFO, "Failed to set CA cert"); + } + } +} + + +static void set_pps_cred_check_aaa_cert_status(struct hs20_osu_client *ctx, + int id, xml_node_t *node) +{ + char *str = xml_node_get_text(ctx->xml, node); + + if (str == NULL) + return; + + wpa_printf(MSG_INFO, "- Credential/CheckAAAServerCertStatus = %s", str); + if (os_strcasecmp(str, "true") == 0 && + set_cred(ctx->ifname, id, "ocsp", "2") < 0) + wpa_printf(MSG_INFO, "Failed to set cred ocsp"); + xml_node_get_text_free(ctx->xml, str); +} + + +static void set_pps_cred_sim(struct hs20_osu_client *ctx, int id, + xml_node_t *sim, xml_node_t *realm) +{ + xml_node_t *node; + char *imsi, *eaptype, *str, buf[20]; + int type; + int mnc_len = 3; + size_t imsi_len; + + node = get_node(ctx->xml, sim, "EAPType"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No SIM/EAPType node in credential"); + return; + } + eaptype = xml_node_get_text(ctx->xml, node); + if (eaptype == NULL) { + wpa_printf(MSG_INFO, "Could not extract SIM/EAPType"); + return; + } + wpa_printf(MSG_INFO, " - Credential/SIM/EAPType = %s", eaptype); + type = atoi(eaptype); + xml_node_get_text_free(ctx->xml, eaptype); + + switch (type) { + case EAP_TYPE_SIM: + if (set_cred(ctx->ifname, id, "eap", "SIM") < 0) + wpa_printf(MSG_INFO, "Could not set eap=SIM"); + break; + case EAP_TYPE_AKA: + if (set_cred(ctx->ifname, id, "eap", "AKA") < 0) + wpa_printf(MSG_INFO, "Could not set eap=SIM"); + break; + case EAP_TYPE_AKA_PRIME: + if (set_cred(ctx->ifname, id, "eap", "AKA'") < 0) + wpa_printf(MSG_INFO, "Could not set eap=SIM"); + break; + default: + wpa_printf(MSG_INFO, "Unsupported SIM/EAPType %d", type); + return; + } + + node = get_node(ctx->xml, sim, "IMSI"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No SIM/IMSI node in credential"); + return; + } + imsi = xml_node_get_text(ctx->xml, node); + if (imsi == NULL) { + wpa_printf(MSG_INFO, "Could not extract SIM/IMSI"); + return; + } + wpa_printf(MSG_INFO, " - Credential/SIM/IMSI = %s", imsi); + imsi_len = os_strlen(imsi); + if (imsi_len < 7 || imsi_len + 2 > sizeof(buf)) { + wpa_printf(MSG_INFO, "Invalid IMSI length"); + xml_node_get_text_free(ctx->xml, imsi); + return; + } + + str = xml_node_get_text(ctx->xml, node); + if (str) { + char *pos; + pos = os_strstr(str, "mnc"); + if (pos && os_strlen(pos) >= 6) { + if (os_strncmp(imsi + 3, pos + 3, 3) == 0) + mnc_len = 3; + else if (os_strncmp(imsi + 3, pos + 4, 2) == 0) + mnc_len = 2; + } + xml_node_get_text_free(ctx->xml, str); + } + + os_memcpy(buf, imsi, 3 + mnc_len); + buf[3 + mnc_len] = '-'; + os_strlcpy(buf + 3 + mnc_len + 1, imsi + 3 + mnc_len, + sizeof(buf) - 3 - mnc_len - 1); + + xml_node_get_text_free(ctx->xml, imsi); + + if (set_cred_quoted(ctx->ifname, id, "imsi", buf) < 0) + wpa_printf(MSG_INFO, "Could not set IMSI"); + + if (set_cred_quoted(ctx->ifname, id, "milenage", + "90dca4eda45b53cf0f12d7c9c3bc6a89:" + "cb9cccc4b9258e6dca4760379fb82581:000000000123") < + 0) + wpa_printf(MSG_INFO, "Could not set Milenage parameters"); +} + + +static void set_pps_cred_credential(struct hs20_osu_client *ctx, int id, + xml_node_t *node, const char *fqdn) +{ + xml_node_t *child, *sim, *realm; + const char *name; + + wpa_printf(MSG_INFO, "- Credential"); + + sim = get_node(ctx->xml, node, "SIM"); + realm = get_node(ctx->xml, node, "Realm"); + + xml_node_for_each_child(ctx->xml, child, node) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "CreationDate") == 0) + set_pps_cred_creation_date(ctx, id, child); + else if (os_strcasecmp(name, "ExpirationDate") == 0) + set_pps_cred_expiration_date(ctx, id, child); + else if (os_strcasecmp(name, "UsernamePassword") == 0) + set_pps_cred_username_password(ctx, id, child); + else if (os_strcasecmp(name, "DigitalCertificate") == 0) + set_pps_cred_digital_cert(ctx, id, child, fqdn); + else if (os_strcasecmp(name, "Realm") == 0) + set_pps_cred_realm(ctx, id, child, fqdn, sim != NULL); + else if (os_strcasecmp(name, "CheckAAAServerCertStatus") == 0) + set_pps_cred_check_aaa_cert_status(ctx, id, child); + else if (os_strcasecmp(name, "SIM") == 0) + set_pps_cred_sim(ctx, id, child, realm); + else + wpa_printf(MSG_INFO, "Unknown Credential node '%s'", + name); + } +} + + +static void set_pps_credential(struct hs20_osu_client *ctx, int id, + xml_node_t *cred, const char *fqdn) +{ + xml_node_t *child; + const char *name; + + xml_node_for_each_child(ctx->xml, child, cred) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "Policy") == 0) + set_pps_cred_policy(ctx, id, child); + else if (os_strcasecmp(name, "CredentialPriority") == 0) + set_pps_cred_priority(ctx, id, child); + else if (os_strcasecmp(name, "AAAServerTrustRoot") == 0) + set_pps_cred_aaa_server_trust_root(ctx, id, child); + else if (os_strcasecmp(name, "SubscriptionUpdate") == 0) + set_pps_cred_sub_update(ctx, id, child); + else if (os_strcasecmp(name, "HomeSP") == 0) + set_pps_cred_home_sp(ctx, id, child); + else if (os_strcasecmp(name, "SubscriptionParameters") == 0) + set_pps_cred_sub_params(ctx, id, child); + else if (os_strcasecmp(name, "Credential") == 0) + set_pps_cred_credential(ctx, id, child, fqdn); + else + wpa_printf(MSG_INFO, "Unknown credential node '%s'", + name); + } +} + + +static void set_pps(struct hs20_osu_client *ctx, xml_node_t *pps, + const char *fqdn) +{ + xml_node_t *child; + const char *name; + int id; + char *update_identifier = NULL; + + /* + * TODO: Could consider more complex mechanism that would remove + * credentials only if there are changes in the information sent to + * wpa_supplicant. + */ + remove_sp_creds(ctx, fqdn); + + xml_node_for_each_child(ctx->xml, child, pps) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "UpdateIdentifier") == 0) { + update_identifier = xml_node_get_text(ctx->xml, child); + if (update_identifier) { + wpa_printf(MSG_INFO, "- UpdateIdentifier = %s", + update_identifier); + break; + } + } + } + + xml_node_for_each_child(ctx->xml, child, pps) { + xml_node_for_each_check(ctx->xml, child); + name = xml_node_get_localname(ctx->xml, child); + if (os_strcasecmp(name, "UpdateIdentifier") == 0) + continue; + id = add_cred(ctx->ifname); + if (id < 0) { + wpa_printf(MSG_INFO, "Failed to add credential to wpa_supplicant"); + write_summary(ctx, "Failed to add credential to wpa_supplicant"); + break; + } + write_summary(ctx, "Add a credential to wpa_supplicant"); + if (update_identifier && + set_cred(ctx->ifname, id, "update_identifier", + update_identifier) < 0) + wpa_printf(MSG_INFO, "Failed to set update_identifier"); + if (set_cred_quoted(ctx->ifname, id, "provisioning_sp", fqdn) < + 0) + wpa_printf(MSG_INFO, "Failed to set provisioning_sp"); + wpa_printf(MSG_INFO, "credential localname: '%s'", name); + set_pps_credential(ctx, id, child, fqdn); + ctx->pps_cred_set = 1; + } + + xml_node_get_text_free(ctx->xml, update_identifier); +} + + +void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname) +{ + xml_node_t *pps; + const char *fqdn; + char *fqdn_buf = NULL, *pos; + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "Could not read or parse '%s'", pps_fname); + return; + } + + fqdn = os_strstr(pps_fname, "SP/"); + if (fqdn) { + fqdn_buf = os_strdup(fqdn + 3); + if (fqdn_buf == NULL) + return; + pos = os_strchr(fqdn_buf, '/'); + if (pos) + *pos = '\0'; + fqdn = fqdn_buf; + } else + fqdn = "wi-fi.org"; + + wpa_printf(MSG_INFO, "Set PPS MO info to wpa_supplicant - SP FQDN %s", + fqdn); + set_pps(ctx, pps, fqdn); + + os_free(fqdn_buf); + xml_node_free(ctx->xml, pps); +} + + +static int cmd_get_fqdn(struct hs20_osu_client *ctx, const char *pps_fname) +{ + xml_node_t *pps, *node; + char *fqdn = NULL; + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "Could not read or parse '%s'", pps_fname); + return -1; + } + + node = get_child_node(ctx->xml, pps, "HomeSP/FQDN"); + if (node) + fqdn = xml_node_get_text(ctx->xml, node); + + xml_node_free(ctx->xml, pps); + + if (fqdn) { + FILE *f = fopen("pps-fqdn", "w"); + if (f) { + fprintf(f, "%s", fqdn); + fclose(f); + } + xml_node_get_text_free(ctx->xml, fqdn); + return 0; + } + + xml_node_get_text_free(ctx->xml, fqdn); + return -1; +} + + +static void cmd_to_tnds(struct hs20_osu_client *ctx, const char *in_fname, + const char *out_fname, const char *urn, int use_path) +{ + xml_node_t *mo, *node; + + mo = node_from_file(ctx->xml, in_fname); + if (mo == NULL) { + wpa_printf(MSG_INFO, "Could not read or parse '%s'", in_fname); + return; + } + + node = mo_to_tnds(ctx->xml, mo, use_path, urn, NULL); + if (node) { + node_to_file(ctx->xml, out_fname, node); + xml_node_free(ctx->xml, node); + } + + xml_node_free(ctx->xml, mo); +} + + +static void cmd_from_tnds(struct hs20_osu_client *ctx, const char *in_fname, + const char *out_fname) +{ + xml_node_t *tnds, *mo; + + tnds = node_from_file(ctx->xml, in_fname); + if (tnds == NULL) { + wpa_printf(MSG_INFO, "Could not read or parse '%s'", in_fname); + return; + } + + mo = tnds_to_mo(ctx->xml, tnds); + if (mo) { + node_to_file(ctx->xml, out_fname, mo); + xml_node_free(ctx->xml, mo); + } + + xml_node_free(ctx->xml, tnds); +} + + +struct osu_icon { + int id; + char lang[4]; + char mime_type[256]; + char filename[256]; +}; + +struct osu_data { + char bssid[20]; + char url[256]; + unsigned int methods; + char osu_ssid[33]; + char osu_ssid2[33]; + char osu_nai[256]; + char osu_nai2[256]; + struct osu_lang_text friendly_name[MAX_OSU_VALS]; + size_t friendly_name_count; + struct osu_lang_text serv_desc[MAX_OSU_VALS]; + size_t serv_desc_count; + struct osu_icon icon[MAX_OSU_VALS]; + size_t icon_count; +}; + + +static struct osu_data * parse_osu_providers(const char *fname, size_t *count) +{ + FILE *f; + char buf[1000]; + struct osu_data *osu = NULL, *last = NULL; + size_t osu_count = 0; + char *pos, *end; + + f = fopen(fname, "r"); + if (f == NULL) { + wpa_printf(MSG_ERROR, "Could not open %s", fname); + return NULL; + } + + while (fgets(buf, sizeof(buf), f)) { + pos = strchr(buf, '\n'); + if (pos) + *pos = '\0'; + + if (strncmp(buf, "OSU-PROVIDER ", 13) == 0) { + last = realloc(osu, (osu_count + 1) * sizeof(*osu)); + if (last == NULL) + break; + osu = last; + last = &osu[osu_count++]; + memset(last, 0, sizeof(*last)); + snprintf(last->bssid, sizeof(last->bssid), "%s", + buf + 13); + continue; + } + if (!last) + continue; + + if (strncmp(buf, "uri=", 4) == 0) { + snprintf(last->url, sizeof(last->url), "%s", buf + 4); + continue; + } + + if (strncmp(buf, "methods=", 8) == 0) { + last->methods = strtol(buf + 8, NULL, 16); + continue; + } + + if (strncmp(buf, "osu_ssid=", 9) == 0) { + snprintf(last->osu_ssid, sizeof(last->osu_ssid), + "%s", buf + 9); + continue; + } + + if (strncmp(buf, "osu_ssid2=", 10) == 0) { + snprintf(last->osu_ssid2, sizeof(last->osu_ssid2), + "%s", buf + 10); + continue; + } + + if (os_strncmp(buf, "osu_nai=", 8) == 0) { + os_snprintf(last->osu_nai, sizeof(last->osu_nai), + "%s", buf + 8); + continue; + } + + if (os_strncmp(buf, "osu_nai2=", 9) == 0) { + os_snprintf(last->osu_nai2, sizeof(last->osu_nai2), + "%s", buf + 9); + continue; + } + + if (strncmp(buf, "friendly_name=", 14) == 0) { + struct osu_lang_text *txt; + if (last->friendly_name_count == MAX_OSU_VALS) + continue; + pos = strchr(buf + 14, ':'); + if (pos == NULL) + continue; + *pos++ = '\0'; + txt = &last->friendly_name[last->friendly_name_count++]; + snprintf(txt->lang, sizeof(txt->lang), "%s", buf + 14); + snprintf(txt->text, sizeof(txt->text), "%s", pos); + } + + if (strncmp(buf, "desc=", 5) == 0) { + struct osu_lang_text *txt; + if (last->serv_desc_count == MAX_OSU_VALS) + continue; + pos = strchr(buf + 5, ':'); + if (pos == NULL) + continue; + *pos++ = '\0'; + txt = &last->serv_desc[last->serv_desc_count++]; + snprintf(txt->lang, sizeof(txt->lang), "%s", buf + 5); + snprintf(txt->text, sizeof(txt->text), "%s", pos); + } + + if (strncmp(buf, "icon=", 5) == 0) { + struct osu_icon *icon; + if (last->icon_count == MAX_OSU_VALS) + continue; + icon = &last->icon[last->icon_count++]; + icon->id = atoi(buf + 5); + pos = strchr(buf, ':'); + if (pos == NULL) + continue; + pos = strchr(pos + 1, ':'); + if (pos == NULL) + continue; + pos = strchr(pos + 1, ':'); + if (pos == NULL) + continue; + pos++; + end = strchr(pos, ':'); + if (!end) + continue; + *end = '\0'; + snprintf(icon->lang, sizeof(icon->lang), "%s", pos); + pos = end + 1; + + end = strchr(pos, ':'); + if (end) + *end = '\0'; + snprintf(icon->mime_type, sizeof(icon->mime_type), + "%s", pos); + if (!pos) + continue; + pos = end + 1; + + end = strchr(pos, ':'); + if (end) + *end = '\0'; + snprintf(icon->filename, sizeof(icon->filename), + "%s", pos); + continue; + } + } + + fclose(f); + + *count = osu_count; + return osu; +} + + +static int osu_connect(struct hs20_osu_client *ctx, const char *bssid, + const char *ssid, const char *ssid2, const char *url, + unsigned int methods, int no_prod_assoc, + const char *osu_nai, const char *osu_nai2) +{ + int id; + const char *ifname = ctx->ifname; + char buf[200]; + struct wpa_ctrl *mon; + int res; + + if (ssid2 && ssid2[0] == '\0') + ssid2 = NULL; + + if (ctx->osu_ssid) { + if (os_strcmp(ssid, ctx->osu_ssid) == 0) { + wpa_printf(MSG_DEBUG, + "Enforced OSU SSID matches ANQP info"); + ssid2 = NULL; + } else if (ssid2 && os_strcmp(ssid2, ctx->osu_ssid) == 0) { + wpa_printf(MSG_DEBUG, + "Enforced OSU SSID matches RSN[OSEN] info"); + ssid = ssid2; + } else { + wpa_printf(MSG_INFO, "Enforced OSU SSID did not match"); + write_summary(ctx, "Enforced OSU SSID did not match"); + return -1; + } + } + + id = add_network(ifname); + if (id < 0) + return -1; + if (set_network_quoted(ifname, id, "ssid", ssid) < 0) + return -1; + if (ssid2) + osu_nai = osu_nai2; + if (osu_nai && os_strlen(osu_nai) > 0) { + char dir[255], fname[300]; + if (getcwd(dir, sizeof(dir)) == NULL) + return -1; + os_snprintf(fname, sizeof(fname), "%s/osu-ca.pem", dir); + + if (ssid2 && set_network_quoted(ifname, id, "ssid", ssid2) < 0) + return -1; + + if (set_network(ifname, id, "proto", "OSEN") < 0 || + set_network(ifname, id, "key_mgmt", "OSEN") < 0 || + set_network(ifname, id, "pairwise", "CCMP") < 0 || + set_network(ifname, id, "group", "GTK_NOT_USED CCMP") < 0 || + set_network(ifname, id, "eap", "WFA-UNAUTH-TLS") < 0 || + set_network(ifname, id, "ocsp", "2") < 0 || + set_network_quoted(ifname, id, "identity", osu_nai) < 0 || + set_network_quoted(ifname, id, "ca_cert", fname) < 0) + return -1; + } else if (ssid2) { + wpa_printf(MSG_INFO, "No OSU_NAI set for RSN[OSEN]"); + write_summary(ctx, "No OSU_NAI set for RSN[OSEN]"); + return -1; + } else { + if (set_network(ifname, id, "key_mgmt", "NONE") < 0) + return -1; + } + + mon = open_wpa_mon(ifname); + if (mon == NULL) + return -1; + + wpa_printf(MSG_INFO, "Associate with OSU SSID"); + write_summary(ctx, "Associate with OSU SSID"); + snprintf(buf, sizeof(buf), "SELECT_NETWORK %d", id); + if (wpa_command(ifname, buf) < 0) + return -1; + + res = get_wpa_cli_event(mon, "CTRL-EVENT-CONNECTED", + buf, sizeof(buf)); + + wpa_ctrl_detach(mon); + wpa_ctrl_close(mon); + + if (res < 0) { + wpa_printf(MSG_INFO, "Could not connect to OSU network"); + write_summary(ctx, "Could not connect to OSU network"); + wpa_printf(MSG_INFO, "Remove OSU network connection"); + snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id); + wpa_command(ifname, buf); + return -1; + } + + write_summary(ctx, "Waiting for IP address for subscription registration"); + if (wait_ip_addr(ifname, 15) < 0) { + wpa_printf(MSG_INFO, "Could not get IP address for WLAN - try connection anyway"); + } + + if (no_prod_assoc) { + if (res < 0) + return -1; + wpa_printf(MSG_INFO, "No production connection used for testing purposes"); + write_summary(ctx, "No production connection used for testing purposes"); + return 0; + } + + ctx->no_reconnect = 1; + if (methods & 0x02) { + wpa_printf(MSG_DEBUG, "Calling cmd_prov from osu_connect"); + res = cmd_prov(ctx, url); + } else if (methods & 0x01) { + wpa_printf(MSG_DEBUG, + "Calling cmd_oma_dm_prov from osu_connect"); + res = cmd_oma_dm_prov(ctx, url); + } + + wpa_printf(MSG_INFO, "Remove OSU network connection"); + write_summary(ctx, "Remove OSU network connection"); + snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id); + wpa_command(ifname, buf); + + if (res < 0) + return -1; + + wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration"); + write_summary(ctx, "Requesting reconnection with updated configuration"); + if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) { + wpa_printf(MSG_INFO, "Failed to request wpa_supplicant to reconnect"); + write_summary(ctx, "Failed to request wpa_supplicant to reconnect"); + return -1; + } + + return 0; +} + + +static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir, + int connect, int no_prod_assoc, + const char *friendly_name) +{ + char fname[255]; + FILE *f; + struct osu_data *osu = NULL, *last = NULL; + size_t osu_count = 0, i, j; + int ret; + + write_summary(ctx, "OSU provider selection"); + + if (dir == NULL) { + wpa_printf(MSG_INFO, "Missing dir parameter to osu_select"); + return -1; + } + + snprintf(fname, sizeof(fname), "%s/osu-providers.txt", dir); + osu = parse_osu_providers(fname, &osu_count); + if (osu == NULL) { + wpa_printf(MSG_INFO, "Could not find any OSU providers from %s", + fname); + write_result(ctx, "No OSU providers available"); + return -1; + } + + if (friendly_name) { + for (i = 0; i < osu_count; i++) { + last = &osu[i]; + for (j = 0; j < last->friendly_name_count; j++) { + if (os_strcmp(last->friendly_name[j].text, + friendly_name) == 0) + break; + } + if (j < last->friendly_name_count) + break; + } + if (i == osu_count) { + wpa_printf(MSG_INFO, "Requested operator friendly name '%s' not found in the list of available providers", + friendly_name); + write_summary(ctx, "Requested operator friendly name '%s' not found in the list of available providers", + friendly_name); + free(osu); + return -1; + } + + wpa_printf(MSG_INFO, "OSU Provider selected based on requested operator friendly name '%s'", + friendly_name); + write_summary(ctx, "OSU Provider selected based on requested operator friendly name '%s'", + friendly_name); + ret = i + 1; + goto selected; + } + + snprintf(fname, sizeof(fname), "%s/osu-providers.html", dir); + f = fopen(fname, "w"); + if (f == NULL) { + wpa_printf(MSG_INFO, "Could not open %s", fname); + free(osu); + return -1; + } + + fprintf(f, "" + "Select service operator" + "

Select service operator

\n"); + + if (osu_count == 0) + fprintf(f, "No online signup available\n"); + + for (i = 0; i < osu_count; i++) { + last = &osu[i]; +#ifdef ANDROID + fprintf(f, "

\n" + "" + "
", (int) i + 1); +#else /* ANDROID */ + fprintf(f, "

\n" + "" + "
", (int) i + 1); +#endif /* ANDROID */ + for (j = 0; j < last->icon_count; j++) { + fprintf(f, "\n", + last->icon[j].id, + strcasecmp(last->icon[j].mime_type, + "image/png") == 0 ? "png" : "icon"); + } + fprintf(f, ""); + for (j = 0; j < last->friendly_name_count; j++) { + fprintf(f, "[%s] %s
\n", + last->friendly_name[j].lang, + last->friendly_name[j].text); + } + fprintf(f, "
"); + for (j = 0; j < last->serv_desc_count; j++) { + fprintf(f, "[%s] %s
\n", + last->serv_desc[j].lang, + last->serv_desc[j].text); + } + fprintf(f, "

BSSID: %s
\n" + "SSID: %s
\n", + last->bssid, last->osu_ssid); + if (last->osu_ssid2[0]) + fprintf(f, "SSID2: %s
\n", last->osu_ssid2); + if (last->osu_nai[0]) + fprintf(f, "NAI: %s
\n", last->osu_nai); + if (last->osu_nai2[0]) + fprintf(f, "NAI2: %s
\n", last->osu_nai2); + fprintf(f, "URL: %s
\n" + "methods:%s%s
\n" + "

\n", + last->url, + last->methods & 0x01 ? " OMA-DM" : "", + last->methods & 0x02 ? " SOAP-XML-SPP" : ""); + } + + fprintf(f, "\n"); + + fclose(f); + + snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir); + write_summary(ctx, "Start web browser with OSU provider selection page"); + ret = hs20_web_browser(fname, 0); + +selected: + if (ret > 0 && (size_t) ret <= osu_count) { + char *data; + size_t data_len; + + wpa_printf(MSG_INFO, "Selected OSU id=%d", ret); + last = &osu[ret - 1]; + ret = 0; + wpa_printf(MSG_INFO, "BSSID: %s", last->bssid); + wpa_printf(MSG_INFO, "SSID: %s", last->osu_ssid); + if (last->osu_ssid2[0]) + wpa_printf(MSG_INFO, "SSID2: %s", last->osu_ssid2); + wpa_printf(MSG_INFO, "URL: %s", last->url); + write_summary(ctx, "Selected OSU provider id=%d BSSID=%s SSID=%s URL=%s", + ret, last->bssid, last->osu_ssid, last->url); + + ctx->friendly_name_count = last->friendly_name_count; + for (j = 0; j < last->friendly_name_count; j++) { + wpa_printf(MSG_INFO, "FRIENDLY_NAME: [%s]%s", + last->friendly_name[j].lang, + last->friendly_name[j].text); + os_strlcpy(ctx->friendly_name[j].lang, + last->friendly_name[j].lang, + sizeof(ctx->friendly_name[j].lang)); + os_strlcpy(ctx->friendly_name[j].text, + last->friendly_name[j].text, + sizeof(ctx->friendly_name[j].text)); + } + + ctx->icon_count = last->icon_count; + for (j = 0; j < last->icon_count; j++) { + char fname[256]; + + os_snprintf(fname, sizeof(fname), "%s/osu-icon-%d.%s", + dir, last->icon[j].id, + strcasecmp(last->icon[j].mime_type, + "image/png") == 0 ? + "png" : "icon"); + wpa_printf(MSG_INFO, "ICON: %s (%s)", + fname, last->icon[j].filename); + os_strlcpy(ctx->icon_filename[j], + last->icon[j].filename, + sizeof(ctx->icon_filename[j])); + + data = os_readfile(fname, &data_len); + if (data) { + sha256_vector(1, (const u8 **) &data, &data_len, + ctx->icon_hash[j]); + os_free(data); + } + } + + if (connect == 2) { + if (last->methods & 0x02) { + wpa_printf(MSG_DEBUG, + "Calling cmd_prov from cmd_osu_select"); + ret = cmd_prov(ctx, last->url); + } else if (last->methods & 0x01) { + wpa_printf(MSG_DEBUG, + "Calling cmd_oma_dm_prov from cmd_osu_select"); + ret = cmd_oma_dm_prov(ctx, last->url); + } else { + wpa_printf(MSG_DEBUG, + "No supported OSU provisioning method"); + ret = -1; + } + } else if (connect) { + ret = osu_connect(ctx, last->bssid, last->osu_ssid, + last->osu_ssid2, + last->url, last->methods, + no_prod_assoc, last->osu_nai, + last->osu_nai2); + } + } else + ret = -1; + + free(osu); + + return ret; +} + + +static int cmd_signup(struct hs20_osu_client *ctx, int no_prod_assoc, + const char *friendly_name) +{ + char dir[255]; + char fname[300], buf[400]; + struct wpa_ctrl *mon; + const char *ifname; + int res; + + ifname = ctx->ifname; + + if (getcwd(dir, sizeof(dir)) == NULL) + return -1; + + snprintf(fname, sizeof(fname), "%s/osu-info", dir); + if (mkdir(fname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 && + errno != EEXIST) { + wpa_printf(MSG_INFO, "mkdir(%s) failed: %s", + fname, strerror(errno)); + return -1; + } + + android_update_permission(fname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + snprintf(buf, sizeof(buf), "SET osu_dir %s", fname); + if (wpa_command(ifname, buf) < 0) { + wpa_printf(MSG_INFO, "Failed to configure osu_dir to wpa_supplicant"); + return -1; + } + + mon = open_wpa_mon(ifname); + if (mon == NULL) + return -1; + + wpa_printf(MSG_INFO, "Starting OSU fetch"); + write_summary(ctx, "Starting OSU provider information fetch"); + if (wpa_command(ifname, "FETCH_OSU") < 0) { + wpa_printf(MSG_INFO, "Could not start OSU fetch"); + wpa_ctrl_detach(mon); + wpa_ctrl_close(mon); + return -1; + } + res = get_wpa_cli_event(mon, "OSU provider fetch completed", + buf, sizeof(buf)); + + wpa_ctrl_detach(mon); + wpa_ctrl_close(mon); + + if (res < 0) { + wpa_printf(MSG_INFO, "OSU fetch did not complete"); + write_summary(ctx, "OSU fetch did not complete"); + return -1; + } + wpa_printf(MSG_INFO, "OSU provider fetch completed"); + + return cmd_osu_select(ctx, fname, 1, no_prod_assoc, friendly_name); +} + + +static int cmd_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, const char *ca_fname) +{ + xml_node_t *pps, *node; + char pps_fname_buf[300]; + char ca_fname_buf[200]; + char *cred_username = NULL; + char *cred_password = NULL; + char *sub_rem_uri = NULL; + char client_cert_buf[200]; + char *client_cert = NULL; + char client_key_buf[200]; + char *client_key = NULL; + int spp; + + wpa_printf(MSG_INFO, "Subscription remediation requested with Server URL: %s", + address); + + if (!pps_fname) { + char buf[256]; + wpa_printf(MSG_INFO, "Determining PPS file based on Home SP information"); + if (os_strncmp(address, "fqdn=", 5) == 0) { + wpa_printf(MSG_INFO, "Use requested FQDN from command line"); + os_snprintf(buf, sizeof(buf), "%s", address + 5); + address = NULL; + } else if (get_wpa_status(ctx->ifname, "provisioning_sp", buf, + sizeof(buf)) < 0) { + wpa_printf(MSG_INFO, "Could not get provisioning Home SP FQDN from wpa_supplicant"); + return -1; + } + os_free(ctx->fqdn); + ctx->fqdn = os_strdup(buf); + if (ctx->fqdn == NULL) + return -1; + wpa_printf(MSG_INFO, "Home SP FQDN for current credential: %s", + buf); + os_snprintf(pps_fname_buf, sizeof(pps_fname_buf), + "SP/%s/pps.xml", ctx->fqdn); + pps_fname = pps_fname_buf; + + os_snprintf(ca_fname_buf, sizeof(ca_fname_buf), "SP/%s/ca.pem", + ctx->fqdn); + ca_fname = ca_fname_buf; + } + + if (!os_file_exists(pps_fname)) { + wpa_printf(MSG_INFO, "PPS file '%s' does not exist or is not accessible", + pps_fname); + return -1; + } + wpa_printf(MSG_INFO, "Using PPS file: %s", pps_fname); + + if (ca_fname && !os_file_exists(ca_fname)) { + wpa_printf(MSG_INFO, "CA file '%s' does not exist or is not accessible", + ca_fname); + return -1; + } + wpa_printf(MSG_INFO, "Using server trust root: %s", ca_fname); + ctx->ca_fname = ca_fname; + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "Could not read PPS MO"); + return -1; + } + + if (!ctx->fqdn) { + char *tmp; + node = get_child_node(ctx->xml, pps, "HomeSP/FQDN"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No HomeSP/FQDN found from PPS"); + return -1; + } + tmp = xml_node_get_text(ctx->xml, node); + if (tmp == NULL) { + wpa_printf(MSG_INFO, "No HomeSP/FQDN text found from PPS"); + return -1; + } + ctx->fqdn = os_strdup(tmp); + xml_node_get_text_free(ctx->xml, tmp); + if (!ctx->fqdn) { + wpa_printf(MSG_INFO, "No FQDN known"); + return -1; + } + } + + node = get_child_node(ctx->xml, pps, + "SubscriptionUpdate/UpdateMethod"); + if (node) { + char *tmp; + tmp = xml_node_get_text(ctx->xml, node); + if (tmp && os_strcasecmp(tmp, "OMA-DM-ClientInitiated") == 0) + spp = 0; + else + spp = 1; + } else { + wpa_printf(MSG_INFO, "No UpdateMethod specified - assume SPP"); + spp = 1; + } + + get_user_pw(ctx, pps, "SubscriptionUpdate/UsernamePassword", + &cred_username, &cred_password); + if (cred_username) + wpa_printf(MSG_INFO, "Using username: %s", cred_username); + if (cred_password) + wpa_printf(MSG_DEBUG, "Using password: %s", cred_password); + + if (cred_username == NULL && cred_password == NULL && + get_child_node(ctx->xml, pps, "Credential/DigitalCertificate")) { + wpa_printf(MSG_INFO, "Using client certificate"); + os_snprintf(client_cert_buf, sizeof(client_cert_buf), + "SP/%s/client-cert.pem", ctx->fqdn); + client_cert = client_cert_buf; + os_snprintf(client_key_buf, sizeof(client_key_buf), + "SP/%s/client-key.pem", ctx->fqdn); + client_key = client_key_buf; + ctx->client_cert_present = 1; + } + + node = get_child_node(ctx->xml, pps, "SubscriptionUpdate/URI"); + if (node) { + sub_rem_uri = xml_node_get_text(ctx->xml, node); + if (sub_rem_uri && + (!address || os_strcmp(address, sub_rem_uri) != 0)) { + wpa_printf(MSG_INFO, "Override sub rem URI based on PPS: %s", + sub_rem_uri); + address = sub_rem_uri; + } + } + if (!address) { + wpa_printf(MSG_INFO, "Server URL not known"); + return -1; + } + + write_summary(ctx, "Wait for IP address for subscriptiom remediation"); + wpa_printf(MSG_INFO, "Wait for IP address before starting subscription remediation"); + + if (wait_ip_addr(ctx->ifname, 15) < 0) { + wpa_printf(MSG_INFO, "Could not get IP address for WLAN - try connection anyway"); + } + + if (spp) + spp_sub_rem(ctx, address, pps_fname, + client_cert, client_key, + cred_username, cred_password, pps); + else + oma_dm_sub_rem(ctx, address, pps_fname, + client_cert, client_key, + cred_username, cred_password, pps); + + xml_node_get_text_free(ctx->xml, sub_rem_uri); + xml_node_get_text_free(ctx->xml, cred_username); + str_clear_free(cred_password); + xml_node_free(ctx->xml, pps); + return 0; +} + + +static int cmd_pol_upd(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, const char *ca_fname) +{ + xml_node_t *pps; + xml_node_t *node; + char pps_fname_buf[300]; + char ca_fname_buf[200]; + char *uri = NULL; + char *cred_username = NULL; + char *cred_password = NULL; + char client_cert_buf[200]; + char *client_cert = NULL; + char client_key_buf[200]; + char *client_key = NULL; + int spp; + + wpa_printf(MSG_INFO, "Policy update requested"); + + if (!pps_fname) { + char buf[256]; + int res; + + wpa_printf(MSG_INFO, "Determining PPS file based on Home SP information"); + if (address && os_strncmp(address, "fqdn=", 5) == 0) { + wpa_printf(MSG_INFO, "Use requested FQDN from command line"); + os_snprintf(buf, sizeof(buf), "%s", address + 5); + address = NULL; + } else if (get_wpa_status(ctx->ifname, "provisioning_sp", buf, + sizeof(buf)) < 0) { + wpa_printf(MSG_INFO, "Could not get provisioning Home SP FQDN from wpa_supplicant"); + return -1; + } + os_free(ctx->fqdn); + ctx->fqdn = os_strdup(buf); + if (ctx->fqdn == NULL) + return -1; + wpa_printf(MSG_INFO, "Home SP FQDN for current credential: %s", + buf); + os_snprintf(pps_fname_buf, sizeof(pps_fname_buf), + "SP/%s/pps.xml", ctx->fqdn); + pps_fname = pps_fname_buf; + + res = os_snprintf(ca_fname_buf, sizeof(ca_fname_buf), + "SP/%s/ca.pem", buf); + if (os_snprintf_error(sizeof(ca_fname_buf), res)) { + os_free(ctx->fqdn); + ctx->fqdn = NULL; + return -1; + } + ca_fname = ca_fname_buf; + } + + if (!os_file_exists(pps_fname)) { + wpa_printf(MSG_INFO, "PPS file '%s' does not exist or is not accessible", + pps_fname); + return -1; + } + wpa_printf(MSG_INFO, "Using PPS file: %s", pps_fname); + + if (ca_fname && !os_file_exists(ca_fname)) { + wpa_printf(MSG_INFO, "CA file '%s' does not exist or is not accessible", + ca_fname); + return -1; + } + wpa_printf(MSG_INFO, "Using server trust root: %s", ca_fname); + ctx->ca_fname = ca_fname; + + pps = node_from_file(ctx->xml, pps_fname); + if (pps == NULL) { + wpa_printf(MSG_INFO, "Could not read PPS MO"); + return -1; + } + + if (!ctx->fqdn) { + char *tmp; + node = get_child_node(ctx->xml, pps, "HomeSP/FQDN"); + if (node == NULL) { + wpa_printf(MSG_INFO, "No HomeSP/FQDN found from PPS"); + return -1; + } + tmp = xml_node_get_text(ctx->xml, node); + if (tmp == NULL) { + wpa_printf(MSG_INFO, "No HomeSP/FQDN text found from PPS"); + return -1; + } + ctx->fqdn = os_strdup(tmp); + xml_node_get_text_free(ctx->xml, tmp); + if (!ctx->fqdn) { + wpa_printf(MSG_INFO, "No FQDN known"); + return -1; + } + } + + node = get_child_node(ctx->xml, pps, + "Policy/PolicyUpdate/UpdateMethod"); + if (node) { + char *tmp; + tmp = xml_node_get_text(ctx->xml, node); + if (tmp && os_strcasecmp(tmp, "OMA-DM-ClientInitiated") == 0) + spp = 0; + else + spp = 1; + } else { + wpa_printf(MSG_INFO, "No UpdateMethod specified - assume SPP"); + spp = 1; + } + + get_user_pw(ctx, pps, "Policy/PolicyUpdate/UsernamePassword", + &cred_username, &cred_password); + if (cred_username) + wpa_printf(MSG_INFO, "Using username: %s", cred_username); + if (cred_password) + wpa_printf(MSG_DEBUG, "Using password: %s", cred_password); + + if (cred_username == NULL && cred_password == NULL && + get_child_node(ctx->xml, pps, "Credential/DigitalCertificate")) { + wpa_printf(MSG_INFO, "Using client certificate"); + os_snprintf(client_cert_buf, sizeof(client_cert_buf), + "SP/%s/client-cert.pem", ctx->fqdn); + client_cert = client_cert_buf; + os_snprintf(client_key_buf, sizeof(client_key_buf), + "SP/%s/client-key.pem", ctx->fqdn); + client_key = client_key_buf; + } + + if (!address) { + node = get_child_node(ctx->xml, pps, "Policy/PolicyUpdate/URI"); + if (node) { + uri = xml_node_get_text(ctx->xml, node); + wpa_printf(MSG_INFO, "URI based on PPS: %s", uri); + address = uri; + } + } + if (!address) { + wpa_printf(MSG_INFO, "Server URL not known"); + return -1; + } + + if (spp) + spp_pol_upd(ctx, address, pps_fname, + client_cert, client_key, + cred_username, cred_password, pps); + else + oma_dm_pol_upd(ctx, address, pps_fname, + client_cert, client_key, + cred_username, cred_password, pps); + + xml_node_get_text_free(ctx->xml, uri); + xml_node_get_text_free(ctx->xml, cred_username); + str_clear_free(cred_password); + xml_node_free(ctx->xml, pps); + + return 0; +} + + +static char * get_hostname(const char *url) +{ + const char *pos, *end, *end2; + char *ret; + + if (url == NULL) + return NULL; + + pos = os_strchr(url, '/'); + if (pos == NULL) + return NULL; + pos++; + if (*pos != '/') + return NULL; + pos++; + + end = os_strchr(pos, '/'); + end2 = os_strchr(pos, ':'); + if ((end && end2 && end2 < end) || (!end && end2)) + end = end2; + if (end) + end--; + else { + end = pos; + while (*end) + end++; + if (end > pos) + end--; + } + + ret = os_malloc(end - pos + 2); + if (ret == NULL) + return NULL; + + os_memcpy(ret, pos, end - pos + 1); + ret[end - pos + 1] = '\0'; + + return ret; +} + + +static int osu_cert_cb(void *_ctx, struct http_cert *cert) +{ + struct hs20_osu_client *ctx = _ctx; + size_t i, j; + int found; + char *host = NULL; + + wpa_printf(MSG_INFO, "osu_cert_cb(osu_cert_validation=%d, url=%s)", + !ctx->no_osu_cert_validation, ctx->server_url); + + host = get_hostname(ctx->server_url); + + for (i = 0; i < ctx->server_dnsname_count; i++) + os_free(ctx->server_dnsname[i]); + os_free(ctx->server_dnsname); + ctx->server_dnsname = os_calloc(cert->num_dnsname, sizeof(char *)); + ctx->server_dnsname_count = 0; + + found = 0; + for (i = 0; i < cert->num_dnsname; i++) { + if (ctx->server_dnsname) { + ctx->server_dnsname[ctx->server_dnsname_count] = + os_strdup(cert->dnsname[i]); + if (ctx->server_dnsname[ctx->server_dnsname_count]) + ctx->server_dnsname_count++; + } + if (host && os_strcasecmp(host, cert->dnsname[i]) == 0) + found = 1; + wpa_printf(MSG_INFO, "dNSName '%s'", cert->dnsname[i]); + } + + if (host && !found) { + wpa_printf(MSG_INFO, "Server name from URL (%s) did not match any dNSName - abort connection", + host); + write_result(ctx, "Server name from URL (%s) did not match any dNSName - abort connection", + host); + os_free(host); + return -1; + } + + os_free(host); + + for (i = 0; i < cert->num_othername; i++) { + if (os_strcmp(cert->othername[i].oid, + "1.3.6.1.4.1.40808.1.1.1") == 0) { + wpa_hexdump_ascii(MSG_INFO, + "id-wfa-hotspot-friendlyName", + cert->othername[i].data, + cert->othername[i].len); + } + } + + for (j = 0; !ctx->no_osu_cert_validation && + j < ctx->friendly_name_count; j++) { + int found = 0; + for (i = 0; i < cert->num_othername; i++) { + if (os_strcmp(cert->othername[i].oid, + "1.3.6.1.4.1.40808.1.1.1") != 0) + continue; + if (cert->othername[i].len < 3) + continue; + if (os_strncasecmp((char *) cert->othername[i].data, + ctx->friendly_name[j].lang, 3) != 0) + continue; + if (os_strncmp((char *) cert->othername[i].data + 3, + ctx->friendly_name[j].text, + cert->othername[i].len - 3) == 0) { + found = 1; + break; + } + } + + if (!found) { + wpa_printf(MSG_INFO, "No friendly name match found for '[%s]%s'", + ctx->friendly_name[j].lang, + ctx->friendly_name[j].text); + write_result(ctx, "No friendly name match found for '[%s]%s'", + ctx->friendly_name[j].lang, + ctx->friendly_name[j].text); + return -1; + } + } + + for (i = 0; i < cert->num_logo; i++) { + struct http_logo *logo = &cert->logo[i]; + + wpa_printf(MSG_INFO, "logo hash alg %s uri '%s'", + logo->alg_oid, logo->uri); + wpa_hexdump_ascii(MSG_INFO, "hashValue", + logo->hash, logo->hash_len); + } + + for (j = 0; !ctx->no_osu_cert_validation && j < ctx->icon_count; j++) { + int found = 0; + char *name = ctx->icon_filename[j]; + size_t name_len = os_strlen(name); + + wpa_printf(MSG_INFO, + "[%zu] Looking for icon file name '%s' match", + j, name); + for (i = 0; i < cert->num_logo; i++) { + struct http_logo *logo = &cert->logo[i]; + size_t uri_len = os_strlen(logo->uri); + char *pos; + + wpa_printf(MSG_INFO, + "[%zu] Comparing to '%s' uri_len=%d name_len=%d", + i, logo->uri, (int) uri_len, (int) name_len); + if (uri_len < 1 + name_len) { + wpa_printf(MSG_INFO, "URI Length is too short"); + continue; + } + pos = &logo->uri[uri_len - name_len - 1]; + if (*pos != '/') + continue; + pos++; + if (os_strcmp(pos, name) == 0) { + found = 1; + break; + } + } + + if (!found) { + wpa_printf(MSG_INFO, "No icon filename match found for '%s'", + name); + write_result(ctx, + "No icon filename match found for '%s'", + name); + return -1; + } + } + + for (j = 0; !ctx->no_osu_cert_validation && j < ctx->icon_count; j++) { + int found = 0; + + for (i = 0; i < cert->num_logo; i++) { + struct http_logo *logo = &cert->logo[i]; + + if (logo->hash_len != 32) { + wpa_printf(MSG_INFO, + "[%zu][%zu] Icon hash length invalid (should be 32): %d", + j, i, (int) logo->hash_len); + continue; + } + if (os_memcmp(logo->hash, ctx->icon_hash[j], 32) == 0) { + found = 1; + break; + } + + wpa_printf(MSG_DEBUG, + "[%zu][%zu] Icon hash did not match", j, i); + wpa_hexdump_ascii(MSG_DEBUG, "logo->hash", + logo->hash, 32); + wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]", + ctx->icon_hash[j], 32); + } + + if (!found) { + wpa_printf(MSG_INFO, + "No icon hash match (by hash) found"); + write_result(ctx, + "No icon hash match (by hash) found"); + return -1; + } + } + + return 0; +} + + +static int init_ctx(struct hs20_osu_client *ctx) +{ + xml_node_t *devinfo, *devid; + + os_memset(ctx, 0, sizeof(*ctx)); + ctx->ifname = "wlan0"; + ctx->xml = xml_node_init_ctx(ctx, NULL); + if (ctx->xml == NULL) + return -1; + + devinfo = node_from_file(ctx->xml, "devinfo.xml"); + if (devinfo) { + devid = get_node(ctx->xml, devinfo, "DevId"); + if (devid) { + char *tmp = xml_node_get_text(ctx->xml, devid); + + if (tmp) { + ctx->devid = os_strdup(tmp); + xml_node_get_text_free(ctx->xml, tmp); + } + } + xml_node_free(ctx->xml, devinfo); + } + + ctx->http = http_init_ctx(ctx, ctx->xml); + if (ctx->http == NULL) { + xml_node_deinit_ctx(ctx->xml); + return -1; + } + http_ocsp_set(ctx->http, 2); + http_set_cert_cb(ctx->http, osu_cert_cb, ctx); + + return 0; +} + + +static void deinit_ctx(struct hs20_osu_client *ctx) +{ + size_t i; + + http_deinit_ctx(ctx->http); + xml_node_deinit_ctx(ctx->xml); + os_free(ctx->fqdn); + os_free(ctx->server_url); + os_free(ctx->devid); + + for (i = 0; i < ctx->server_dnsname_count; i++) + os_free(ctx->server_dnsname[i]); + os_free(ctx->server_dnsname); +} + + +static void check_workarounds(struct hs20_osu_client *ctx) +{ + FILE *f; + char buf[100]; + unsigned long int val = 0; + + f = fopen("hs20-osu-client.workarounds", "r"); + if (f == NULL) + return; + + if (fgets(buf, sizeof(buf), f)) + val = strtoul(buf, NULL, 16); + + fclose(f); + + if (val) { + wpa_printf(MSG_INFO, "Workarounds enabled: 0x%lx", val); + ctx->workarounds = val; + if (ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) + http_ocsp_set(ctx->http, 1); + } +} + + +static void usage(void) +{ + printf("usage: hs20-osu-client [-dddqqKtT] [-S] \\\n" + " [-w] " + "[-r] [-f] \\\n" + " [-s] \\\n" + " [-x] \\\n" + " [arguments..]\n" + "commands:\n" + "- to_tnds [URN]\n" + "- to_tnds2 \n" + "- from_tnds \n" + "- set_pps \n" + "- get_fqdn \n" + "- pol_upd [Server URL] [PPS] [CA cert]\n" + "- sub_rem [PPS] [CA cert]\n" + "- prov [CA cert]\n" + "- oma_dm_prov [CA cert]\n" + "- sim_prov [CA cert]\n" + "- oma_dm_sim_prov [CA cert]\n" + "- signup [CA cert]\n" + "- dl_osu_ca \n" + "- dl_polupd_ca \n" + "- dl_aaa_ca \n" + "- browser \n" + "- parse_cert \n" + "- osu_select [CA cert]\n"); +} + + +int main(int argc, char *argv[]) +{ + struct hs20_osu_client ctx; + int c; + int ret = 0; + int no_prod_assoc = 0; + const char *friendly_name = NULL; + const char *wpa_debug_file_path = NULL; + extern char *wpas_ctrl_path; + extern int wpa_debug_level; + extern int wpa_debug_show_keys; + extern int wpa_debug_timestamp; + + if (init_ctx(&ctx) < 0) + return -1; + + for (;;) { + c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tTw:x:"); + if (c < 0) + break; + switch (c) { + case 'd': + if (wpa_debug_level > 0) + wpa_debug_level--; + break; + case 'f': + wpa_debug_file_path = optarg; + break; + case 'K': + wpa_debug_show_keys++; + break; + case 'N': + no_prod_assoc = 1; + break; + case 'o': + ctx.osu_ssid = optarg; + break; + case 'O': + friendly_name = optarg; + break; + case 'q': + wpa_debug_level++; + break; + case 'r': + ctx.result_file = optarg; + break; + case 's': + ctx.summary_file = optarg; + break; + case 'S': + ctx.ifname = optarg; + break; + case 't': + wpa_debug_timestamp++; + break; + case 'T': + ctx.ignore_tls = 1; + break; + case 'w': + wpas_ctrl_path = optarg; + break; + case 'x': + spp_xsd_fname = optarg; + break; + case 'h': + default: + usage(); + exit(0); + break; + } + } + + if (argc - optind < 1) { + usage(); + exit(0); + } + + wpa_debug_open_file(wpa_debug_file_path); + +#ifdef __linux__ + setlinebuf(stdout); +#endif /* __linux__ */ + + if (ctx.result_file) + unlink(ctx.result_file); + wpa_printf(MSG_DEBUG, "===[hs20-osu-client START - command: %s ]======" + "================", argv[optind]); + check_workarounds(&ctx); + + if (strcmp(argv[optind], "to_tnds") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_to_tnds(&ctx, argv[optind + 1], argv[optind + 2], + argc > optind + 3 ? argv[optind + 3] : NULL, + 0); + } else if (strcmp(argv[optind], "to_tnds2") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_to_tnds(&ctx, argv[optind + 1], argv[optind + 2], + argc > optind + 3 ? argv[optind + 3] : NULL, + 1); + } else if (strcmp(argv[optind], "from_tnds") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_from_tnds(&ctx, argv[optind + 1], argv[optind + 2]); + } else if (strcmp(argv[optind], "sub_rem") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + ret = cmd_sub_rem(&ctx, argv[optind + 1], + argc > optind + 2 ? argv[optind + 2] : NULL, + argc > optind + 3 ? argv[optind + 3] : NULL); + } else if (strcmp(argv[optind], "pol_upd") == 0) { + ret = cmd_pol_upd(&ctx, + argc > optind + 1 ? argv[optind + 1] : NULL, + argc > optind + 2 ? argv[optind + 2] : NULL, + argc > optind + 3 ? argv[optind + 3] : NULL); + } else if (strcmp(argv[optind], "prov") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + ctx.ca_fname = argv[optind + 2]; + wpa_printf(MSG_DEBUG, "Calling cmd_prov from main"); + cmd_prov(&ctx, argv[optind + 1]); + } else if (strcmp(argv[optind], "sim_prov") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + ctx.ca_fname = argv[optind + 2]; + cmd_sim_prov(&ctx, argv[optind + 1]); + } else if (strcmp(argv[optind], "dl_osu_ca") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_dl_osu_ca(&ctx, argv[optind + 1], argv[optind + 2]); + } else if (strcmp(argv[optind], "dl_polupd_ca") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_dl_polupd_ca(&ctx, argv[optind + 1], argv[optind + 2]); + } else if (strcmp(argv[optind], "dl_aaa_ca") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_dl_aaa_ca(&ctx, argv[optind + 1], argv[optind + 2]); + } else if (strcmp(argv[optind], "osu_select") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + ctx.ca_fname = argc > optind + 2 ? argv[optind + 2] : NULL; + cmd_osu_select(&ctx, argv[optind + 1], 2, 1, NULL); + } else if (strcmp(argv[optind], "signup") == 0) { + ctx.ca_fname = argc > optind + 1 ? argv[optind + 1] : NULL; + ret = cmd_signup(&ctx, no_prod_assoc, friendly_name); + } else if (strcmp(argv[optind], "set_pps") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_set_pps(&ctx, argv[optind + 1]); + } else if (strcmp(argv[optind], "get_fqdn") == 0) { + if (argc - optind < 1) { + usage(); + exit(0); + } + ret = cmd_get_fqdn(&ctx, argv[optind + 1]); + } else if (strcmp(argv[optind], "oma_dm_prov") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + ctx.ca_fname = argv[optind + 2]; + cmd_oma_dm_prov(&ctx, argv[optind + 1]); + } else if (strcmp(argv[optind], "oma_dm_sim_prov") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + ctx.ca_fname = argv[optind + 2]; + if (cmd_oma_dm_sim_prov(&ctx, argv[optind + 1]) < 0) { + write_summary(&ctx, "Failed to complete OMA DM SIM provisioning"); + return -1; + } + } else if (strcmp(argv[optind], "oma_dm_add") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_oma_dm_add(&ctx, argv[optind + 1], argv[optind + 2]); + } else if (strcmp(argv[optind], "oma_dm_replace") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + cmd_oma_dm_replace(&ctx, argv[optind + 1], argv[optind + 2]); + } else if (strcmp(argv[optind], "est_csr") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + mkdir("Cert", S_IRWXU); + est_build_csr(&ctx, argv[optind + 1]); + } else if (strcmp(argv[optind], "browser") == 0) { + int ret; + + if (argc - optind < 2) { + usage(); + exit(0); + } + + wpa_printf(MSG_INFO, "Launch web browser to URL %s", + argv[optind + 1]); + ret = hs20_web_browser(argv[optind + 1], ctx.ignore_tls); + wpa_printf(MSG_INFO, "Web browser result: %d", ret); + } else if (strcmp(argv[optind], "parse_cert") == 0) { + if (argc - optind < 2) { + usage(); + exit(0); + } + + wpa_debug_level = MSG_MSGDUMP; + http_parse_x509_certificate(ctx.http, argv[optind + 1]); + wpa_debug_level = MSG_INFO; + } else { + wpa_printf(MSG_INFO, "Unknown command '%s'", argv[optind]); + } + + deinit_ctx(&ctx); + wpa_printf(MSG_DEBUG, + "===[hs20-osu-client END ]======================"); + + wpa_debug_close_file(); + + return ret; +} diff --git a/hs20/client/osu_client.h b/hs20/client/osu_client.h new file mode 100644 index 000000000000..9b45b03febe2 --- /dev/null +++ b/hs20/client/osu_client.h @@ -0,0 +1,121 @@ +/* + * Hotspot 2.0 - OSU client + * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef OSU_CLIENT_H +#define OSU_CLIENT_H + +#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp" + +#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0" +#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0" +#define URN_HS20_DEVDETAIL_EXT "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0" +#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0" + + +#define MAX_OSU_VALS 10 + +struct osu_lang_text { + char lang[4]; + char text[253]; +}; + +struct hs20_osu_client { + struct xml_node_ctx *xml; + struct http_ctx *http; + int no_reconnect; + char pps_fname[300]; + char *devid; + const char *result_file; + const char *summary_file; + const char *ifname; + const char *ca_fname; + int no_osu_cert_validation; /* for EST operations */ + char *fqdn; + char *server_url; + struct osu_lang_text friendly_name[MAX_OSU_VALS]; + size_t friendly_name_count; + size_t icon_count; + char icon_filename[MAX_OSU_VALS][256]; + u8 icon_hash[MAX_OSU_VALS][32]; + int pps_cred_set; + int pps_updated; + int client_cert_present; + char **server_dnsname; + size_t server_dnsname_count; + const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */ +#define WORKAROUND_OCSP_OPTIONAL 0x00000001 + unsigned long int workarounds; + int ignore_tls; /* whether to ignore TLS validation issues with HTTPS + * server certificate */ +}; + + +/* osu_client.c */ + +void write_result(struct hs20_osu_client *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +void debug_dump_node(struct hs20_osu_client *ctx, const char *title, + xml_node_t *node); +int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert); +int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri, + xml_node_t *add_mo, char *fname, size_t fname_len); +void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps, + const char *alt_loc, char **user, char **pw); +int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname, + xml_node_t *pps); +void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname); + + +/* spp_client.c */ + +void spp_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +void spp_pol_upd(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +int cmd_prov(struct hs20_osu_client *ctx, const char *url); +int cmd_sim_prov(struct hs20_osu_client *ctx, const char *url); + + +/* oma_dm_client.c */ + +int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url); +int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url); +void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +void cmd_oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname); +void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname, + const char *add_fname); +void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname, + const char *replace_fname); + +/* est.c */ + +int est_load_cacerts(struct hs20_osu_client *ctx, const char *url); +int est_build_csr(struct hs20_osu_client *ctx, const char *url); +int est_simple_enroll(struct hs20_osu_client *ctx, const char *url, + const char *user, const char *pw); + +#endif /* OSU_CLIENT_H */ diff --git a/hs20/client/spp_client.c b/hs20/client/spp_client.c new file mode 100644 index 000000000000..39d10e0362f6 --- /dev/null +++ b/hs20/client/spp_client.c @@ -0,0 +1,1004 @@ +/* + * Hotspot 2.0 SPP client + * Copyright (c) 2012-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" +#include + +#include "common.h" +#include "browser.h" +#include "wpa_ctrl.h" +#include "wpa_helpers.h" +#include "xml-utils.h" +#include "http-utils.h" +#include "utils/base64.h" +#include "crypto/crypto.h" +#include "crypto/sha256.h" +#include "osu_client.h" + + +extern const char *spp_xsd_fname; + +static int hs20_spp_update_response(struct hs20_osu_client *ctx, + const char *session_id, + const char *spp_status, + const char *error_code); +static void hs20_policy_update_complete( + struct hs20_osu_client *ctx, const char *pps_fname); + + +static char * get_spp_attr_value(struct xml_node_ctx *ctx, xml_node_t *node, + char *attr_name) +{ + return xml_node_get_attr_value_ns(ctx, node, SPP_NS_URI, attr_name); +} + + +static int hs20_spp_validate(struct hs20_osu_client *ctx, xml_node_t *node, + const char *expected_name) +{ + struct xml_node_ctx *xctx = ctx->xml; + const char *name; + char *err; + int ret; + + if (!xml_node_is_element(xctx, node)) + return -1; + + name = xml_node_get_localname(xctx, node); + if (name == NULL) + return -1; + + if (strcmp(expected_name, name) != 0) { + wpa_printf(MSG_INFO, "Unexpected SOAP method name '%s' (expected '%s')", + name, expected_name); + write_summary(ctx, "Unexpected SOAP method name '%s' (expected '%s')", + name, expected_name); + return -1; + } + + ret = xml_validate(xctx, node, spp_xsd_fname, &err); + if (ret < 0) { + wpa_printf(MSG_INFO, "XML schema validation error(s)\n%s", err); + write_summary(ctx, "SPP XML schema validation failed"); + os_free(err); + } + return ret; +} + + +static void add_mo_container(struct xml_node_ctx *ctx, xml_namespace_t *ns, + xml_node_t *parent, const char *urn, + const char *fname) +{ + xml_node_t *node; + xml_node_t *fnode, *tnds; + char *str; + + errno = 0; + fnode = node_from_file(ctx, fname); + if (!fnode) { + wpa_printf(MSG_ERROR, + "Failed to create XML node from file: %s, possible error: %s", + fname, strerror(errno)); + return; + } + tnds = mo_to_tnds(ctx, fnode, 0, urn, "syncml:dmddf1.2"); + xml_node_free(ctx, fnode); + if (!tnds) + return; + + str = xml_node_to_str(ctx, tnds); + xml_node_free(ctx, tnds); + if (str == NULL) + return; + + node = xml_node_create_text(ctx, parent, ns, "moContainer", str); + if (node) + xml_node_add_attr(ctx, node, ns, "moURN", urn); + os_free(str); +} + + +static xml_node_t * build_spp_post_dev_data(struct hs20_osu_client *ctx, + xml_namespace_t **ret_ns, + const char *session_id, + const char *reason) +{ + xml_namespace_t *ns; + xml_node_t *spp_node; + + write_summary(ctx, "Building sppPostDevData requestReason='%s'", + reason); + spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, + "sppPostDevData"); + if (spp_node == NULL) + return NULL; + if (ret_ns) + *ret_ns = ns; + + xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); + xml_node_add_attr(ctx->xml, spp_node, NULL, "requestReason", reason); + if (session_id) + xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", + session_id); + xml_node_add_attr(ctx->xml, spp_node, NULL, "redirectURI", + "http://localhost:12345/"); + + xml_node_create_text(ctx->xml, spp_node, ns, "supportedSPPVersions", + "1.0"); + xml_node_create_text(ctx->xml, spp_node, ns, "supportedMOList", + URN_HS20_PPS " " URN_OMA_DM_DEVINFO " " + URN_OMA_DM_DEVDETAIL " " URN_HS20_DEVDETAIL_EXT); + + add_mo_container(ctx->xml, ns, spp_node, URN_OMA_DM_DEVINFO, + "devinfo.xml"); + add_mo_container(ctx->xml, ns, spp_node, URN_OMA_DM_DEVDETAIL, + "devdetail.xml"); + + return spp_node; +} + + +static int process_update_node(struct hs20_osu_client *ctx, xml_node_t *pps, + xml_node_t *update) +{ + xml_node_t *node, *parent, *tnds, *unode; + char *str; + const char *name; + char *uri, *pos; + char *cdata, *cdata_end; + size_t fqdn_len; + + wpa_printf(MSG_INFO, "Processing updateNode"); + debug_dump_node(ctx, "updateNode", update); + + uri = get_spp_attr_value(ctx->xml, update, "managementTreeURI"); + if (uri == NULL) { + wpa_printf(MSG_INFO, "No managementTreeURI present"); + return -1; + } + wpa_printf(MSG_INFO, "managementTreeUri: '%s'", uri); + + name = os_strrchr(uri, '/'); + if (name == NULL) { + wpa_printf(MSG_INFO, "Unexpected URI"); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + name++; + wpa_printf(MSG_INFO, "Update interior node: '%s'", name); + + str = xml_node_get_text(ctx->xml, update); + if (str == NULL) { + wpa_printf(MSG_INFO, "Could not extract MO text"); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + wpa_printf(MSG_DEBUG, "[hs20] nodeContainer text: '%s'", str); + cdata = strstr(str, ""); + if (cdata && cdata_end && cdata_end > cdata && + cdata < strstr(str, "MgmtTree") && + cdata_end > strstr(str, "/MgmtTree")) { + char *tmp; + wpa_printf(MSG_DEBUG, "[hs20] Removing extra CDATA container"); + tmp = strdup(cdata + 9); + if (tmp) { + cdata_end = strstr(tmp, "]]>"); + if (cdata_end) + *cdata_end = '\0'; + wpa_printf(MSG_DEBUG, "[hs20] nodeContainer text with CDATA container removed: '%s'", + tmp); + tnds = xml_node_from_buf(ctx->xml, tmp); + free(tmp); + } else + tnds = NULL; + } else + tnds = xml_node_from_buf(ctx->xml, str); + xml_node_get_text_free(ctx->xml, str); + if (tnds == NULL) { + wpa_printf(MSG_INFO, "[hs20] Could not parse nodeContainer text"); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + + unode = tnds_to_mo(ctx->xml, tnds); + xml_node_free(ctx->xml, tnds); + if (unode == NULL) { + wpa_printf(MSG_INFO, "[hs20] Could not parse nodeContainer TNDS text"); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + + debug_dump_node(ctx, "Parsed TNDS", unode); + + if (get_node_uri(ctx->xml, unode, name) == NULL) { + wpa_printf(MSG_INFO, "[hs20] %s node not found", name); + xml_node_free(ctx->xml, unode); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + + if (os_strncasecmp(uri, "./Wi-Fi/", 8) != 0) { + wpa_printf(MSG_INFO, "Do not allow update outside ./Wi-Fi"); + xml_node_free(ctx->xml, unode); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + pos = uri + 8; + + if (ctx->fqdn == NULL) { + wpa_printf(MSG_INFO, "FQDN not known"); + xml_node_free(ctx->xml, unode); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + fqdn_len = os_strlen(ctx->fqdn); + if (os_strncasecmp(pos, ctx->fqdn, fqdn_len) != 0 || + pos[fqdn_len] != '/') { + wpa_printf(MSG_INFO, "Do not allow update outside ./Wi-Fi/%s", + ctx->fqdn); + xml_node_free(ctx->xml, unode); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + pos += fqdn_len + 1; + + if (os_strncasecmp(pos, "PerProviderSubscription/", 24) != 0) { + wpa_printf(MSG_INFO, "Do not allow update outside ./Wi-Fi/%s/PerProviderSubscription", + ctx->fqdn); + xml_node_free(ctx->xml, unode); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + pos += 24; + + wpa_printf(MSG_INFO, "Update command for PPS node %s", pos); + + node = get_node(ctx->xml, pps, pos); + if (node) { + parent = xml_node_get_parent(ctx->xml, node); + xml_node_detach(ctx->xml, node); + wpa_printf(MSG_INFO, "Replace '%s' node", name); + } else { + char *pos2; + pos2 = os_strrchr(pos, '/'); + if (pos2 == NULL) { + parent = pps; + } else { + *pos2 = '\0'; + parent = get_node(ctx->xml, pps, pos); + } + if (parent == NULL) { + wpa_printf(MSG_INFO, "Could not find parent %s", pos); + xml_node_free(ctx->xml, unode); + xml_node_get_attr_value_free(ctx->xml, uri); + return -1; + } + wpa_printf(MSG_INFO, "Add '%s' node", name); + } + xml_node_add_child(ctx->xml, parent, unode); + + xml_node_get_attr_value_free(ctx->xml, uri); + + return 0; +} + + +static int update_pps(struct hs20_osu_client *ctx, xml_node_t *update, + const char *pps_fname, xml_node_t *pps) +{ + wpa_printf(MSG_INFO, "Updating PPS based on updateNode element(s)"); + xml_node_for_each_sibling(ctx->xml, update) { + xml_node_for_each_check(ctx->xml, update); + if (process_update_node(ctx, pps, update) < 0) + return -1; + } + + return update_pps_file(ctx, pps_fname, pps); +} + + +static void hs20_sub_rem_complete(struct hs20_osu_client *ctx, + const char *pps_fname) +{ + /* + * Update wpa_supplicant credentials and reconnect using updated + * information. + */ + wpa_printf(MSG_INFO, "Updating wpa_supplicant credentials"); + cmd_set_pps(ctx, pps_fname); + + if (ctx->no_reconnect) + return; + + wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration"); + if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) + wpa_printf(MSG_ERROR, "Failed to request wpa_supplicant to reconnect"); +} + + +static xml_node_t * hs20_spp_upload_mo(struct hs20_osu_client *ctx, + xml_node_t *cmd, + const char *session_id, + const char *pps_fname) +{ + xml_namespace_t *ns; + xml_node_t *node, *ret_node; + char *urn; + + urn = get_spp_attr_value(ctx->xml, cmd, "moURN"); + if (!urn) { + wpa_printf(MSG_INFO, "No URN included"); + return NULL; + } + wpa_printf(MSG_INFO, "Upload MO request - URN=%s", urn); + if (strcasecmp(urn, URN_HS20_PPS) != 0) { + wpa_printf(MSG_INFO, "Unsupported moURN"); + xml_node_get_attr_value_free(ctx->xml, urn); + return NULL; + } + xml_node_get_attr_value_free(ctx->xml, urn); + + if (!pps_fname) { + wpa_printf(MSG_INFO, "PPS file name no known"); + return NULL; + } + + node = build_spp_post_dev_data(ctx, &ns, session_id, + "MO upload"); + if (node == NULL) + return NULL; + add_mo_container(ctx->xml, ns, node, URN_HS20_PPS, pps_fname); + + ret_node = soap_send_receive(ctx->http, node); + if (ret_node == NULL) + return NULL; + + debug_dump_node(ctx, "Received response to MO upload", ret_node); + + if (hs20_spp_validate(ctx, ret_node, "sppPostDevDataResponse") < 0) { + wpa_printf(MSG_INFO, "SPP validation failed"); + xml_node_free(ctx->xml, ret_node); + return NULL; + } + + return ret_node; +} + + +static int hs20_add_mo(struct hs20_osu_client *ctx, xml_node_t *add_mo, + char *fname, size_t fname_len) +{ + char *uri, *urn; + int ret; + + debug_dump_node(ctx, "Received addMO", add_mo); + + urn = get_spp_attr_value(ctx->xml, add_mo, "moURN"); + if (urn == NULL) { + wpa_printf(MSG_INFO, "[hs20] No moURN in addMO"); + return -1; + } + wpa_printf(MSG_INFO, "addMO - moURN: '%s'", urn); + if (strcasecmp(urn, URN_HS20_PPS) != 0) { + wpa_printf(MSG_INFO, "[hs20] Unsupported MO in addMO"); + xml_node_get_attr_value_free(ctx->xml, urn); + return -1; + } + xml_node_get_attr_value_free(ctx->xml, urn); + + uri = get_spp_attr_value(ctx->xml, add_mo, "managementTreeURI"); + if (uri == NULL) { + wpa_printf(MSG_INFO, "[hs20] No managementTreeURI in addMO"); + return -1; + } + wpa_printf(MSG_INFO, "addMO - managementTreeURI: '%s'", uri); + + ret = hs20_add_pps_mo(ctx, uri, add_mo, fname, fname_len); + xml_node_get_attr_value_free(ctx->xml, uri); + return ret; +} + + +static int process_spp_user_input_response(struct hs20_osu_client *ctx, + const char *session_id, + xml_node_t *add_mo) +{ + int ret; + char fname[300]; + + debug_dump_node(ctx, "addMO", add_mo); + + wpa_printf(MSG_INFO, "Subscription registration completed"); + + if (hs20_add_mo(ctx, add_mo, fname, sizeof(fname)) < 0) { + wpa_printf(MSG_INFO, "Could not add MO"); + ret = hs20_spp_update_response( + ctx, session_id, + "Error occurred", + "MO addition or update failed"); + return 0; + } + + ret = hs20_spp_update_response(ctx, session_id, "OK", NULL); + if (ret == 0) + hs20_sub_rem_complete(ctx, fname); + + return 0; +} + + +static xml_node_t * hs20_spp_user_input_completed(struct hs20_osu_client *ctx, + const char *session_id) +{ + xml_node_t *node, *ret_node; + + node = build_spp_post_dev_data(ctx, NULL, session_id, + "User input completed"); + if (node == NULL) + return NULL; + + ret_node = soap_send_receive(ctx->http, node); + if (!ret_node) { + if (soap_reinit_client(ctx->http) < 0) + return NULL; + wpa_printf(MSG_INFO, "Try to finish with re-opened connection"); + node = build_spp_post_dev_data(ctx, NULL, session_id, + "User input completed"); + if (node == NULL) + return NULL; + ret_node = soap_send_receive(ctx->http, node); + if (ret_node == NULL) + return NULL; + wpa_printf(MSG_INFO, "Continue with new connection"); + } + + if (hs20_spp_validate(ctx, ret_node, "sppPostDevDataResponse") < 0) { + wpa_printf(MSG_INFO, "SPP validation failed"); + xml_node_free(ctx->xml, ret_node); + return NULL; + } + + return ret_node; +} + + +static xml_node_t * hs20_spp_get_certificate(struct hs20_osu_client *ctx, + xml_node_t *cmd, + const char *session_id, + const char *pps_fname) +{ + xml_namespace_t *ns; + xml_node_t *node, *ret_node; + int res; + + wpa_printf(MSG_INFO, "Client certificate enrollment"); + + res = osu_get_certificate(ctx, cmd); + if (res < 0) + wpa_printf(MSG_INFO, "EST simpleEnroll failed"); + + node = build_spp_post_dev_data(ctx, &ns, session_id, + res == 0 ? + "Certificate enrollment completed" : + "Certificate enrollment failed"); + if (node == NULL) + return NULL; + + ret_node = soap_send_receive(ctx->http, node); + if (ret_node == NULL) + return NULL; + + debug_dump_node(ctx, "Received response to certificate enrollment " + "completed", ret_node); + + if (hs20_spp_validate(ctx, ret_node, "sppPostDevDataResponse") < 0) { + wpa_printf(MSG_INFO, "SPP validation failed"); + xml_node_free(ctx->xml, ret_node); + return NULL; + } + + return ret_node; +} + + +static int hs20_spp_exec(struct hs20_osu_client *ctx, xml_node_t *exec, + const char *session_id, const char *pps_fname, + xml_node_t *pps, xml_node_t **ret_node) +{ + xml_node_t *cmd; + const char *name; + char *uri; + char *id = strdup(session_id); + + if (id == NULL) + return -1; + + *ret_node = NULL; + + debug_dump_node(ctx, "exec", exec); + + xml_node_for_each_child(ctx->xml, cmd, exec) { + xml_node_for_each_check(ctx->xml, cmd); + break; + } + if (!cmd) { + wpa_printf(MSG_INFO, "exec command element not found (cmd=%p)", + cmd); + free(id); + return -1; + } + + name = xml_node_get_localname(ctx->xml, cmd); + + if (strcasecmp(name, "launchBrowserToURI") == 0) { + int res; + uri = xml_node_get_text(ctx->xml, cmd); + if (!uri) { + wpa_printf(MSG_INFO, "No URI found"); + free(id); + return -1; + } + wpa_printf(MSG_INFO, "Launch browser to URI '%s'", uri); + write_summary(ctx, "Launch browser to URI '%s'", uri); + res = hs20_web_browser(uri, 1); + xml_node_get_text_free(ctx->xml, uri); + if (res > 0) { + wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'", + id); + write_summary(ctx, "User response in browser completed successfully"); + *ret_node = hs20_spp_user_input_completed(ctx, id); + free(id); + return *ret_node ? 0 : -1; + } else { + wpa_printf(MSG_INFO, "Failed to receive user response"); + write_summary(ctx, "Failed to receive user response"); + hs20_spp_update_response( + ctx, id, "Error occurred", "Other"); + free(id); + return -1; + } + return 0; + } + + if (strcasecmp(name, "uploadMO") == 0) { + if (pps_fname == NULL) + return -1; + *ret_node = hs20_spp_upload_mo(ctx, cmd, id, + pps_fname); + free(id); + return *ret_node ? 0 : -1; + } + + if (strcasecmp(name, "getCertificate") == 0) { + *ret_node = hs20_spp_get_certificate(ctx, cmd, id, + pps_fname); + free(id); + return *ret_node ? 0 : -1; + } + + wpa_printf(MSG_INFO, "Unsupported exec command: '%s'", name); + free(id); + return -1; +} + + +enum spp_post_dev_data_use { + SPP_SUBSCRIPTION_REMEDIATION, + SPP_POLICY_UPDATE, + SPP_SUBSCRIPTION_REGISTRATION, +}; + +static void process_spp_post_dev_data_response( + struct hs20_osu_client *ctx, + enum spp_post_dev_data_use use, xml_node_t *node, + const char *pps_fname, xml_node_t *pps) +{ + xml_node_t *child; + char *status = NULL; + xml_node_t *update = NULL, *exec = NULL, *add_mo = NULL, *no_mo = NULL; + char *session_id = NULL; + + debug_dump_node(ctx, "sppPostDevDataResponse node", node); + + status = get_spp_attr_value(ctx->xml, node, "sppStatus"); + if (status == NULL) { + wpa_printf(MSG_INFO, "No sppStatus attribute"); + goto out; + } + write_summary(ctx, "Received sppPostDevDataResponse sppStatus='%s'", + status); + + session_id = get_spp_attr_value(ctx->xml, node, "sessionID"); + if (session_id == NULL) { + wpa_printf(MSG_INFO, "No sessionID attribute"); + goto out; + } + + wpa_printf(MSG_INFO, "[hs20] sppPostDevDataResponse - sppStatus: '%s' sessionID: '%s'", + status, session_id); + + xml_node_for_each_child(ctx->xml, child, node) { + const char *name; + xml_node_for_each_check(ctx->xml, child); + debug_dump_node(ctx, "child", child); + name = xml_node_get_localname(ctx->xml, child); + wpa_printf(MSG_INFO, "localname: '%s'", name); + if (!update && strcasecmp(name, "updateNode") == 0) + update = child; + if (!exec && strcasecmp(name, "exec") == 0) + exec = child; + if (!add_mo && strcasecmp(name, "addMO") == 0) + add_mo = child; + if (!no_mo && strcasecmp(name, "noMOUpdate") == 0) + no_mo = child; + } + + if (use == SPP_SUBSCRIPTION_REMEDIATION && + strcasecmp(status, + "Remediation complete, request sppUpdateResponse") == 0) + { + int res, ret; + if (!update && !no_mo) { + wpa_printf(MSG_INFO, "No updateNode or noMOUpdate element"); + goto out; + } + wpa_printf(MSG_INFO, "Subscription remediation completed"); + res = update_pps(ctx, update, pps_fname, pps); + if (res < 0) + wpa_printf(MSG_INFO, "Failed to update PPS MO"); + ret = hs20_spp_update_response( + ctx, session_id, + res < 0 ? "Error occurred" : "OK", + res < 0 ? "MO addition or update failed" : NULL); + if (res == 0 && ret == 0) + hs20_sub_rem_complete(ctx, pps_fname); + goto out; + } + + if (use == SPP_SUBSCRIPTION_REMEDIATION && + strcasecmp(status, "Exchange complete, release TLS connection") == + 0) { + if (!no_mo) { + wpa_printf(MSG_INFO, "No noMOUpdate element"); + goto out; + } + wpa_printf(MSG_INFO, "Subscription remediation completed (no MO update)"); + goto out; + } + + if (use == SPP_POLICY_UPDATE && + strcasecmp(status, "Update complete, request sppUpdateResponse") == + 0) { + int res, ret; + wpa_printf(MSG_INFO, "Policy update received - update PPS"); + res = update_pps(ctx, update, pps_fname, pps); + ret = hs20_spp_update_response( + ctx, session_id, + res < 0 ? "Error occurred" : "OK", + res < 0 ? "MO addition or update failed" : NULL); + if (res == 0 && ret == 0) + hs20_policy_update_complete(ctx, pps_fname); + goto out; + } + + if (use == SPP_SUBSCRIPTION_REGISTRATION && + strcasecmp(status, "Provisioning complete, request " + "sppUpdateResponse") == 0) { + if (!add_mo) { + wpa_printf(MSG_INFO, "No addMO element - not sure what to do next"); + goto out; + } + process_spp_user_input_response(ctx, session_id, add_mo); + node = NULL; + goto out; + } + + if (strcasecmp(status, "No update available at this time") == 0) { + wpa_printf(MSG_INFO, "No update available at this time"); + goto out; + } + + if (strcasecmp(status, "OK") == 0) { + int res; + xml_node_t *ret; + + if (!exec) { + wpa_printf(MSG_INFO, "No exec element - not sure what to do next"); + goto out; + } + res = hs20_spp_exec(ctx, exec, session_id, + pps_fname, pps, &ret); + /* xml_node_free(ctx->xml, node); */ + node = NULL; + if (res == 0 && ret) + process_spp_post_dev_data_response(ctx, use, + ret, pps_fname, pps); + goto out; + } + + if (strcasecmp(status, "Error occurred") == 0) { + xml_node_t *err; + char *code = NULL; + err = get_node(ctx->xml, node, "sppError"); + if (err) + code = xml_node_get_attr_value(ctx->xml, err, + "errorCode"); + wpa_printf(MSG_INFO, "Error occurred - errorCode=%s", + code ? code : "N/A"); + xml_node_get_attr_value_free(ctx->xml, code); + goto out; + } + + wpa_printf(MSG_INFO, + "[hs20] Unsupported sppPostDevDataResponse sppStatus '%s'", + status); +out: + xml_node_get_attr_value_free(ctx->xml, status); + xml_node_get_attr_value_free(ctx->xml, session_id); + xml_node_free(ctx->xml, node); +} + + +static int spp_post_dev_data(struct hs20_osu_client *ctx, + enum spp_post_dev_data_use use, + const char *reason, + const char *pps_fname, xml_node_t *pps) +{ + xml_node_t *payload; + xml_node_t *ret_node; + + payload = build_spp_post_dev_data(ctx, NULL, NULL, reason); + if (payload == NULL) + return -1; + + ret_node = soap_send_receive(ctx->http, payload); + if (!ret_node) { + const char *err = http_get_err(ctx->http); + if (err) { + wpa_printf(MSG_INFO, "HTTP error: %s", err); + write_result(ctx, "HTTP error: %s", err); + } else { + write_summary(ctx, "Failed to send SOAP message"); + } + return -1; + } + + if (hs20_spp_validate(ctx, ret_node, "sppPostDevDataResponse") < 0) { + wpa_printf(MSG_INFO, "SPP validation failed"); + xml_node_free(ctx->xml, ret_node); + return -1; + } + + process_spp_post_dev_data_response(ctx, use, ret_node, + pps_fname, pps); + return 0; +} + + +void spp_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps) +{ + wpa_printf(MSG_INFO, "SPP subscription remediation"); + write_summary(ctx, "SPP subscription remediation"); + + os_free(ctx->server_url); + ctx->server_url = os_strdup(address); + + if (soap_init_client(ctx->http, address, ctx->ca_fname, + cred_username, cred_password, client_cert, + client_key) == 0) { + spp_post_dev_data(ctx, SPP_SUBSCRIPTION_REMEDIATION, + "Subscription remediation", pps_fname, pps); + } +} + + +static void hs20_policy_update_complete(struct hs20_osu_client *ctx, + const char *pps_fname) +{ + wpa_printf(MSG_INFO, "Policy update completed"); + + /* + * Update wpa_supplicant credentials and reconnect using updated + * information. + */ + wpa_printf(MSG_INFO, "Updating wpa_supplicant credentials"); + cmd_set_pps(ctx, pps_fname); + + wpa_printf(MSG_INFO, "Requesting reconnection with updated configuration"); + if (wpa_command(ctx->ifname, "INTERWORKING_SELECT auto") < 0) + wpa_printf(MSG_ERROR, "Failed to request wpa_supplicant to reconnect"); +} + + +static int process_spp_exchange_complete(struct hs20_osu_client *ctx, + xml_node_t *node) +{ + char *status, *session_id; + + debug_dump_node(ctx, "sppExchangeComplete", node); + + status = get_spp_attr_value(ctx->xml, node, "sppStatus"); + if (status == NULL) { + wpa_printf(MSG_INFO, "No sppStatus attribute"); + return -1; + } + write_summary(ctx, "Received sppExchangeComplete sppStatus='%s'", + status); + + session_id = get_spp_attr_value(ctx->xml, node, "sessionID"); + if (session_id == NULL) { + wpa_printf(MSG_INFO, "No sessionID attribute"); + xml_node_get_attr_value_free(ctx->xml, status); + return -1; + } + + wpa_printf(MSG_INFO, "[hs20] sppStatus: '%s' sessionID: '%s'", + status, session_id); + xml_node_get_attr_value_free(ctx->xml, session_id); + + if (strcasecmp(status, "Exchange complete, release TLS connection") == + 0) { + xml_node_get_attr_value_free(ctx->xml, status); + return 0; + } + + wpa_printf(MSG_INFO, "Unexpected sppStatus '%s'", status); + write_summary(ctx, "Unexpected sppStatus '%s'", status); + xml_node_get_attr_value_free(ctx->xml, status); + return -1; +} + + +static xml_node_t * build_spp_update_response(struct hs20_osu_client *ctx, + const char *session_id, + const char *spp_status, + const char *error_code) +{ + xml_namespace_t *ns; + xml_node_t *spp_node, *node; + + spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, + "sppUpdateResponse"); + if (spp_node == NULL) + return NULL; + + xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); + xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); + xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", spp_status); + + if (error_code) { + node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); + if (node) + xml_node_add_attr(ctx->xml, node, NULL, "errorCode", + error_code); + } + + return spp_node; +} + + +static int hs20_spp_update_response(struct hs20_osu_client *ctx, + const char *session_id, + const char *spp_status, + const char *error_code) +{ + xml_node_t *node, *ret_node; + int ret; + + write_summary(ctx, "Building sppUpdateResponse sppStatus='%s' error_code='%s'", + spp_status, error_code); + node = build_spp_update_response(ctx, session_id, spp_status, + error_code); + if (node == NULL) + return -1; + ret_node = soap_send_receive(ctx->http, node); + if (!ret_node) { + if (soap_reinit_client(ctx->http) < 0) + return -1; + wpa_printf(MSG_INFO, "Try to finish with re-opened connection"); + node = build_spp_update_response(ctx, session_id, spp_status, + error_code); + if (node == NULL) + return -1; + ret_node = soap_send_receive(ctx->http, node); + if (ret_node == NULL) + return -1; + wpa_printf(MSG_INFO, "Continue with new connection"); + } + + if (hs20_spp_validate(ctx, ret_node, "sppExchangeComplete") < 0) { + wpa_printf(MSG_INFO, "SPP validation failed"); + xml_node_free(ctx->xml, ret_node); + return -1; + } + + ret = process_spp_exchange_complete(ctx, ret_node); + xml_node_free(ctx->xml, ret_node); + return ret; +} + + +void spp_pol_upd(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps) +{ + wpa_printf(MSG_INFO, "SPP policy update"); + write_summary(ctx, "SPP policy update"); + + os_free(ctx->server_url); + ctx->server_url = os_strdup(address); + + if (soap_init_client(ctx->http, address, ctx->ca_fname, cred_username, + cred_password, client_cert, client_key) == 0) { + spp_post_dev_data(ctx, SPP_POLICY_UPDATE, "Policy update", + pps_fname, pps); + } +} + + +int cmd_prov(struct hs20_osu_client *ctx, const char *url) +{ + unlink("Cert/est_cert.der"); + unlink("Cert/est_cert.pem"); + + if (url == NULL) { + wpa_printf(MSG_INFO, "Invalid prov command (missing URL)"); + return -1; + } + + wpa_printf(MSG_INFO, + "Credential provisioning requested - URL: %s ca_fname: %s", + url, ctx->ca_fname ? ctx->ca_fname : "N/A"); + + os_free(ctx->server_url); + ctx->server_url = os_strdup(url); + + if (soap_init_client(ctx->http, url, ctx->ca_fname, NULL, NULL, NULL, + NULL) < 0) + return -1; + spp_post_dev_data(ctx, SPP_SUBSCRIPTION_REGISTRATION, + "Subscription registration", NULL, NULL); + + return ctx->pps_cred_set ? 0 : -1; +} + + +int cmd_sim_prov(struct hs20_osu_client *ctx, const char *url) +{ + if (url == NULL) { + wpa_printf(MSG_INFO, "Invalid prov command (missing URL)"); + return -1; + } + + wpa_printf(MSG_INFO, "SIM provisioning requested"); + + os_free(ctx->server_url); + ctx->server_url = os_strdup(url); + + wpa_printf(MSG_INFO, "Wait for IP address before starting SIM provisioning"); + + if (wait_ip_addr(ctx->ifname, 15) < 0) { + wpa_printf(MSG_INFO, "Could not get IP address for WLAN - try connection anyway"); + } + + if (soap_init_client(ctx->http, url, ctx->ca_fname, NULL, NULL, NULL, + NULL) < 0) + return -1; + spp_post_dev_data(ctx, SPP_SUBSCRIPTION_REGISTRATION, + "Subscription provisioning", NULL, NULL); + + return ctx->pps_cred_set ? 0 : -1; +} diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk new file mode 100644 index 000000000000..7e597f396a07 --- /dev/null +++ b/wpa_supplicant/Android.mk @@ -0,0 +1,1827 @@ +# +# Copyright (C) 2008 The Android Open Source Project +# +# This software may be distributed under the terms of the BSD license. +# See README for more details. +# + +LOCAL_PATH := $(call my-dir) +PKG_CONFIG ?= pkg-config + +ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),) + CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y +endif + +include $(LOCAL_PATH)/android.config + +# To ignore possible wrong network configurations +L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS + +L_CFLAGS += -DVERSION_STR_POSTFIX=\"-$(PLATFORM_VERSION)\" + +# Set Android log name +L_CFLAGS += -DANDROID_LOG_NAME=\"wpa_supplicant\" + +# Disable unused parameter warnings +L_CFLAGS += -Wno-unused-parameter + +# Set Android extended P2P functionality +L_CFLAGS += -DANDROID_P2P + +ifeq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB),) +L_CFLAGS += -DANDROID_LIB_STUB +endif + +ifneq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB_EVENT),) +L_CFLAGS += -DANDROID_LIB_EVENT +endif + +# Disable roaming in wpa_supplicant +ifdef CONFIG_NO_ROAMING +L_CFLAGS += -DCONFIG_NO_ROAMING +endif + +# Use Android specific directory for control interface sockets +L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\" +L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/misc/wifi/sockets\" + +# Use Android specific directory for wpa_cli command completion history +L_CFLAGS += -DCONFIG_WPA_CLI_HISTORY_DIR=\"/data/misc/wifi\" + +# To force sizeof(enum) = 4 +ifeq ($(TARGET_ARCH),arm) +L_CFLAGS += -mabi=aapcs-linux +endif + +# C++ flags for binder interface +L_CPPFLAGS := -std=c++11 -Wall -Werror +# TODO: Remove these allowed warnings later. +L_CPPFLAGS += -Wno-unused-variable -Wno-unused-parameter +L_CPPFLAGS += -Wno-unused-private-field + +INCLUDES = $(LOCAL_PATH) +INCLUDES += $(LOCAL_PATH)/src +INCLUDES += $(LOCAL_PATH)/src/common +# INCLUDES += $(LOCAL_PATH)/src/crypto # To force proper includes +INCLUDES += $(LOCAL_PATH)/src/drivers +INCLUDES += $(LOCAL_PATH)/src/eap_common +INCLUDES += $(LOCAL_PATH)/src/eapol_supp +INCLUDES += $(LOCAL_PATH)/src/eap_peer +INCLUDES += $(LOCAL_PATH)/src/eap_server +INCLUDES += $(LOCAL_PATH)/src/hlr_auc_gw +INCLUDES += $(LOCAL_PATH)/src/l2_packet +INCLUDES += $(LOCAL_PATH)/src/radius +INCLUDES += $(LOCAL_PATH)/src/rsn_supp +INCLUDES += $(LOCAL_PATH)/src/tls +INCLUDES += $(LOCAL_PATH)/src/utils +INCLUDES += $(LOCAL_PATH)/src/wps +INCLUDES += system/security/keystore/include +ifdef CONFIG_DRIVER_NL80211 +ifneq ($(wildcard external/libnl),) +INCLUDES += external/libnl/include +else +INCLUDES += external/libnl-headers +endif +endif + +ifdef CONFIG_FIPS +CONFIG_NO_RANDOM_POOL= +CONFIG_OPENSSL_CMAC=y +endif + +OBJS = config.c +OBJS += notify.c +OBJS += bss.c +OBJS += eap_register.c +OBJS += src/utils/common.c +OBJS += src/utils/config.c +OBJS += src/utils/wpa_debug.c +OBJS += src/utils/wpabuf.c +OBJS += src/utils/bitfield.c +OBJS += src/utils/ip_addr.c +OBJS += src/utils/crc32.c +OBJS += wmm_ac.c +OBJS += op_classes.c +OBJS += rrm.c +OBJS += twt.c +OBJS += robust_av.c +OBJS_p = wpa_passphrase.c +OBJS_p += src/utils/common.c +OBJS_p += src/utils/wpa_debug.c +OBJS_p += src/utils/wpabuf.c +OBJS_c = wpa_cli.c src/common/wpa_ctrl.c +OBJS_c += src/utils/wpa_debug.c +OBJS_c += src/utils/common.c +OBJS_c += src/common/cli.c +OBJS_d = +OBJS_priv = + +ifndef CONFIG_OS +ifdef CONFIG_NATIVE_WINDOWS +CONFIG_OS=win32 +else +CONFIG_OS=unix +endif +endif + +ifeq ($(CONFIG_OS), internal) +L_CFLAGS += -DOS_NO_C_LIB_DEFINES +endif + +OBJS += src/utils/os_$(CONFIG_OS).c +OBJS_p += src/utils/os_$(CONFIG_OS).c +OBJS_c += src/utils/os_$(CONFIG_OS).c + +ifdef CONFIG_WPA_TRACE +L_CFLAGS += -DWPA_TRACE +OBJS += src/utils/trace.c +OBJS_p += src/utils/trace.c +OBJS_c += src/utils/trace.c +LDFLAGS += -rdynamic +L_CFLAGS += -funwind-tables +ifdef CONFIG_WPA_TRACE_BFD +L_CFLAGS += -DWPA_TRACE_BFD +LIBS += -lbfd +LIBS_p += -lbfd +LIBS_c += -lbfd +endif +endif + +ifndef CONFIG_ELOOP +CONFIG_ELOOP=eloop +endif +OBJS += src/utils/$(CONFIG_ELOOP).c +OBJS_c += src/utils/$(CONFIG_ELOOP).c + +ifdef CONFIG_ELOOP_POLL +L_CFLAGS += -DCONFIG_ELOOP_POLL +endif + +ifdef CONFIG_ELOOP_EPOLL +L_CFLAGS += -DCONFIG_ELOOP_EPOLL +endif + +ifdef CONFIG_EAPOL_TEST +L_CFLAGS += -Werror -DEAPOL_TEST +endif + +ifdef CONFIG_HT_OVERRIDES +L_CFLAGS += -DCONFIG_HT_OVERRIDES +endif + +ifdef CONFIG_VHT_OVERRIDES +L_CFLAGS += -DCONFIG_VHT_OVERRIDES +endif + +ifdef CONFIG_HE_OVERRIDES +L_CFLAGS += -DCONFIG_HE_OVERRIDES +endif + +ifndef CONFIG_BACKEND +CONFIG_BACKEND=file +endif + +ifeq ($(CONFIG_BACKEND), file) +OBJS += config_file.c +ifndef CONFIG_NO_CONFIG_BLOBS +NEED_BASE64=y +endif +L_CFLAGS += -DCONFIG_BACKEND_FILE +endif + +ifeq ($(CONFIG_BACKEND), winreg) +OBJS += config_winreg.c +endif + +ifeq ($(CONFIG_BACKEND), none) +OBJS += config_none.c +endif + +ifdef CONFIG_NO_CONFIG_WRITE +L_CFLAGS += -DCONFIG_NO_CONFIG_WRITE +endif + +ifdef CONFIG_NO_CONFIG_BLOBS +L_CFLAGS += -DCONFIG_NO_CONFIG_BLOBS +endif + +ifdef CONFIG_NO_SCAN_PROCESSING +L_CFLAGS += -DCONFIG_NO_SCAN_PROCESSING +endif + +ifdef CONFIG_SUITEB +L_CFLAGS += -DCONFIG_SUITEB +endif + +ifdef CONFIG_SUITEB192 +L_CFLAGS += -DCONFIG_SUITEB192 +NEED_SHA384=y +endif + +ifdef CONFIG_OCV +L_CFLAGS += -DCONFIG_OCV +OBJS += src/common/ocv.c +endif + +ifdef CONFIG_IEEE80211R +L_CFLAGS += -DCONFIG_IEEE80211R +OBJS += src/rsn_supp/wpa_ft.c +endif + +ifdef CONFIG_MESH +NEED_80211_COMMON=y +NEED_AES_SIV=y +CONFIG_SAE=y +CONFIG_AP=y +L_CFLAGS += -DCONFIG_MESH +OBJS += mesh.c +OBJS += mesh_mpm.c +OBJS += mesh_rsn.c +endif + +ifdef CONFIG_SAE +L_CFLAGS += -DCONFIG_SAE +OBJS += src/common/sae.c +ifdef CONFIG_SAE_PK +L_CFLAGS += -DCONFIG_SAE_PK +OBJS += src/common/sae_pk.c +endif +NEED_ECC=y +NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y +NEED_DRAGONFLY=y +ifdef CONFIG_TESTING_OPTIONS +NEED_DH_GROUPS_ALL=y +endif +endif + +ifdef CONFIG_DPP +L_CFLAGS += -DCONFIG_DPP +OBJS += src/common/dpp.c +OBJS += src/common/dpp_auth.c +OBJS += src/common/dpp_backup.c +OBJS += src/common/dpp_crypto.c +OBJS += src/common/dpp_pkex.c +OBJS += src/common/dpp_reconfig.c +OBJS += src/common/dpp_tcp.c +OBJS += dpp_supplicant.c +NEED_AES_SIV=y +NEED_HMAC_SHA256_KDF=y +NEED_HMAC_SHA384_KDF=y +NEED_HMAC_SHA512_KDF=y +NEED_SHA384=y +NEED_SHA512=y +NEED_ECC=y +NEED_JSON=y +NEED_GAS_SERVER=y +NEED_BASE64=y +NEED_ASN1=y +ifdef CONFIG_DPP2 +L_CFLAGS += -DCONFIG_DPP2 +endif +ifdef CONFIG_DPP3 +L_CFLAGS += -DCONFIG_DPP3 +endif +endif + +ifdef CONFIG_OWE +L_CFLAGS += -DCONFIG_OWE +NEED_ECC=y +NEED_HMAC_SHA256_KDF=y +NEED_HMAC_SHA384_KDF=y +NEED_HMAC_SHA512_KDF=y +NEED_SHA384=y +NEED_SHA512=y +endif + +ifdef CONFIG_FILS +L_CFLAGS += -DCONFIG_FILS +NEED_SHA384=y +NEED_AES_SIV=y +ifdef CONFIG_FILS_SK_PFS +L_CFLAGS += -DCONFIG_FILS_SK_PFS +NEED_ECC=y +endif +endif + +ifdef CONFIG_MBO +CONFIG_WNM=y +endif + +ifdef CONFIG_WNM +L_CFLAGS += -DCONFIG_WNM +OBJS += wnm_sta.c +endif + +ifdef CONFIG_TDLS +L_CFLAGS += -DCONFIG_TDLS +OBJS += src/rsn_supp/tdls.c +endif + +ifdef CONFIG_TDLS_TESTING +L_CFLAGS += -DCONFIG_TDLS_TESTING +endif + +ifdef CONFIG_PMKSA_CACHE_EXTERNAL +L_CFLAGS += -DCONFIG_PMKSA_CACHE_EXTERNAL +endif + +ifndef CONFIG_NO_WPA +OBJS += src/rsn_supp/wpa.c +OBJS += src/rsn_supp/preauth.c +OBJS += src/rsn_supp/pmksa_cache.c +OBJS += src/rsn_supp/wpa_ie.c +OBJS += src/common/wpa_common.c +NEED_AES=y +NEED_SHA1=y +NEED_MD5=y +NEED_RC4=y +else +L_CFLAGS += -DCONFIG_NO_WPA +endif + +ifdef CONFIG_IBSS_RSN +NEED_RSN_AUTHENTICATOR=y +L_CFLAGS += -DCONFIG_IBSS_RSN +L_CFLAGS += -DCONFIG_NO_VLAN +OBJS += ibss_rsn.c +endif + +ifdef CONFIG_P2P +OBJS += p2p_supplicant.c +OBJS += p2p_supplicant_sd.c +OBJS += src/p2p/p2p.c +OBJS += src/p2p/p2p_utils.c +OBJS += src/p2p/p2p_parse.c +OBJS += src/p2p/p2p_build.c +OBJS += src/p2p/p2p_go_neg.c +OBJS += src/p2p/p2p_sd.c +OBJS += src/p2p/p2p_pd.c +OBJS += src/p2p/p2p_invitation.c +OBJS += src/p2p/p2p_dev_disc.c +OBJS += src/p2p/p2p_group.c +OBJS += src/ap/p2p_hostapd.c +L_CFLAGS += -DCONFIG_P2P +NEED_GAS=y +NEED_OFFCHANNEL=y +CONFIG_WPS=y +CONFIG_AP=y +ifdef CONFIG_P2P_STRICT +L_CFLAGS += -DCONFIG_P2P_STRICT +endif +ifdef CONFIG_WIFI_DISPLAY +L_CFLAGS += -DCONFIG_WIFI_DISPLAY +OBJS += wifi_display.c +endif +endif + +ifdef CONFIG_PASN +L_CFLAGS += -DCONFIG_PASN +L_CFLAGS += -DCONFIG_PTKSA_CACHE +NEED_HMAC_SHA256_KDF=y +NEED_HMAC_SHA384_KDF=y +NEED_SHA256=y +NEED_SHA384=y +OBJS += src/common/ptksa_cache.c +OBJS += pasn_supplicant.c +endif + +ifdef CONFIG_HS20 +OBJS += hs20_supplicant.c +L_CFLAGS += -DCONFIG_HS20 +CONFIG_INTERWORKING=y +endif + +ifdef CONFIG_INTERWORKING +OBJS += interworking.c +L_CFLAGS += -DCONFIG_INTERWORKING +NEED_GAS=y +endif + +ifdef CONFIG_FST +L_CFLAGS += -DCONFIG_FST +OBJS += src/fst/fst.c +OBJS += src/fst/fst_session.c +OBJS += src/fst/fst_iface.c +OBJS += src/fst/fst_group.c +OBJS += src/fst/fst_ctrl_aux.c +ifdef CONFIG_FST_TEST +L_CFLAGS += -DCONFIG_FST_TEST +endif +ifdef CONFIG_CTRL_IFACE +OBJS += src/fst/fst_ctrl_iface.c +endif +endif + +ifdef CONFIG_WEP +L_CFLAGS += -DCONFIG_WEP +endif + +ifdef CONFIG_NO_TKIP +L_CFLAGS += -DCONFIG_NO_TKIP +endif + + +include $(LOCAL_PATH)/src/drivers/drivers.mk + +ifdef CONFIG_AP +OBJS_d += $(DRV_BOTH_OBJS) +L_CFLAGS += $(DRV_BOTH_CFLAGS) +LDFLAGS += $(DRV_BOTH_LDFLAGS) +LIBS += $(DRV_BOTH_LIBS) +else +NEED_AP_MLME= +OBJS_d += $(DRV_WPA_OBJS) +L_CFLAGS += $(DRV_WPA_CFLAGS) +LDFLAGS += $(DRV_WPA_LDFLAGS) +LIBS += $(DRV_WPA_LIBS) +endif + +ifndef CONFIG_L2_PACKET +CONFIG_L2_PACKET=linux +endif + +OBJS_l2 += src/l2_packet/l2_packet_$(CONFIG_L2_PACKET).c + +ifeq ($(CONFIG_L2_PACKET), pcap) +ifdef CONFIG_WINPCAP +L_CFLAGS += -DCONFIG_WINPCAP +LIBS += -lwpcap -lpacket +LIBS_w += -lwpcap +else +LIBS += -ldnet -lpcap +endif +endif + +ifeq ($(CONFIG_L2_PACKET), winpcap) +LIBS += -lwpcap -lpacket +LIBS_w += -lwpcap +endif + +ifeq ($(CONFIG_L2_PACKET), freebsd) +LIBS += -lpcap +endif + +ifdef CONFIG_ERP +L_CFLAGS += -DCONFIG_ERP +NEED_HMAC_SHA256_KDF=y +endif + +ifdef CONFIG_EAP_TLS +# EAP-TLS +ifeq ($(CONFIG_EAP_TLS), dyn) +L_CFLAGS += -DEAP_TLS_DYNAMIC +EAPDYN += src/eap_peer/eap_tls.so +else +L_CFLAGS += -DEAP_TLS +OBJS += src/eap_peer/eap_tls.c +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_UNAUTH_TLS +# EAP-UNAUTH-TLS +L_CFLAGS += -DEAP_UNAUTH_TLS +ifndef CONFIG_EAP_TLS +OBJS += src/eap_peer/eap_tls.c +TLS_FUNCS=y +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_PEAP +# EAP-PEAP +ifeq ($(CONFIG_EAP_PEAP), dyn) +L_CFLAGS += -DEAP_PEAP_DYNAMIC +EAPDYN += src/eap_peer/eap_peap.so +else +L_CFLAGS += -DEAP_PEAP +OBJS += src/eap_peer/eap_peap.c +OBJS += src/eap_common/eap_peap_common.c +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_TTLS +# EAP-TTLS +ifeq ($(CONFIG_EAP_TTLS), dyn) +L_CFLAGS += -DEAP_TTLS_DYNAMIC +EAPDYN += src/eap_peer/eap_ttls.so +else +L_CFLAGS += -DEAP_TTLS +OBJS += src/eap_peer/eap_ttls.c +endif +TLS_FUNCS=y +ifndef CONFIG_FIPS +MS_FUNCS=y +CHAP=y +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_MD5 +# EAP-MD5 +ifeq ($(CONFIG_EAP_MD5), dyn) +L_CFLAGS += -DEAP_MD5_DYNAMIC +EAPDYN += src/eap_peer/eap_md5.so +else +L_CFLAGS += -DEAP_MD5 +OBJS += src/eap_peer/eap_md5.c +endif +CHAP=y +CONFIG_IEEE8021X_EAPOL=y +endif + +# backwards compatibility for old spelling +ifdef CONFIG_MSCHAPV2 +ifndef CONFIG_EAP_MSCHAPV2 +CONFIG_EAP_MSCHAPV2=y +endif +endif + +ifdef CONFIG_EAP_MSCHAPV2 +# EAP-MSCHAPv2 +ifeq ($(CONFIG_EAP_MSCHAPV2), dyn) +L_CFLAGS += -DEAP_MSCHAPv2_DYNAMIC +EAPDYN += src/eap_peer/eap_mschapv2.so +EAPDYN += src/eap_peer/mschapv2.so +else +L_CFLAGS += -DEAP_MSCHAPv2 +OBJS += src/eap_peer/eap_mschapv2.c +OBJS += src/eap_peer/mschapv2.c +endif +MS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_GTC +# EAP-GTC +ifeq ($(CONFIG_EAP_GTC), dyn) +L_CFLAGS += -DEAP_GTC_DYNAMIC +EAPDYN += src/eap_peer/eap_gtc.so +else +L_CFLAGS += -DEAP_GTC +OBJS += src/eap_peer/eap_gtc.c +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_OTP +# EAP-OTP +ifeq ($(CONFIG_EAP_OTP), dyn) +L_CFLAGS += -DEAP_OTP_DYNAMIC +EAPDYN += src/eap_peer/eap_otp.so +else +L_CFLAGS += -DEAP_OTP +OBJS += src/eap_peer/eap_otp.c +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_SIM +# EAP-SIM +ifeq ($(CONFIG_EAP_SIM), dyn) +L_CFLAGS += -DEAP_SIM_DYNAMIC +EAPDYN += src/eap_peer/eap_sim.so +else +L_CFLAGS += -DEAP_SIM +OBJS += src/eap_peer/eap_sim.c +endif +CONFIG_IEEE8021X_EAPOL=y +CONFIG_EAP_SIM_COMMON=y +NEED_AES_CBC=y +endif + +ifdef CONFIG_EAP_LEAP +# EAP-LEAP +ifeq ($(CONFIG_EAP_LEAP), dyn) +L_CFLAGS += -DEAP_LEAP_DYNAMIC +EAPDYN += src/eap_peer/eap_leap.so +else +L_CFLAGS += -DEAP_LEAP +OBJS += src/eap_peer/eap_leap.c +endif +MS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_PSK +# EAP-PSK +ifeq ($(CONFIG_EAP_PSK), dyn) +L_CFLAGS += -DEAP_PSK_DYNAMIC +EAPDYN += src/eap_peer/eap_psk.so +else +L_CFLAGS += -DEAP_PSK +OBJS += src/eap_peer/eap_psk.c src/eap_common/eap_psk_common.c +endif +CONFIG_IEEE8021X_EAPOL=y +NEED_AES=y +NEED_AES_ENCBLOCK=y +NEED_AES_EAX=y +endif + +ifdef CONFIG_EAP_AKA +# EAP-AKA +ifeq ($(CONFIG_EAP_AKA), dyn) +L_CFLAGS += -DEAP_AKA_DYNAMIC +EAPDYN += src/eap_peer/eap_aka.so +else +L_CFLAGS += -DEAP_AKA +OBJS += src/eap_peer/eap_aka.c +endif +CONFIG_IEEE8021X_EAPOL=y +CONFIG_EAP_SIM_COMMON=y +NEED_AES_CBC=y +endif + +ifdef CONFIG_EAP_PROXY +L_CFLAGS += -DCONFIG_EAP_PROXY +OBJS += src/eap_peer/eap_proxy_$(CONFIG_EAP_PROXY).c +include $(LOCAL_PATH)/eap_proxy_$(CONFIG_EAP_PROXY).mk +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_AKA_PRIME +# EAP-AKA' +ifeq ($(CONFIG_EAP_AKA_PRIME), dyn) +L_CFLAGS += -DEAP_AKA_PRIME_DYNAMIC +else +L_CFLAGS += -DEAP_AKA_PRIME +endif +endif + +ifdef CONFIG_EAP_SIM_COMMON +OBJS += src/eap_common/eap_sim_common.c +NEED_AES=y +NEED_FIPS186_2_PRF=y +endif + +ifdef CONFIG_EAP_FAST +# EAP-FAST +ifeq ($(CONFIG_EAP_FAST), dyn) +L_CFLAGS += -DEAP_FAST_DYNAMIC +EAPDYN += src/eap_peer/eap_fast.so +EAPDYN += src/eap_common/eap_fast_common.c +else +L_CFLAGS += -DEAP_FAST +OBJS += src/eap_peer/eap_fast.c src/eap_peer/eap_fast_pac.c +OBJS += src/eap_common/eap_fast_common.c +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +NEED_T_PRF=y +endif + +ifdef CONFIG_EAP_TEAP +# EAP-TEAP +ifeq ($(CONFIG_EAP_TEAP), dyn) +L_CFLAGS += -DEAP_YEAP_DYNAMIC +EAPDYN += src/eap_peer/eap_teap.so +EAPDYN += src/eap_common/eap_teap_common.c +else +L_CFLAGS += -DEAP_TEAP +OBJS += src/eap_peer/eap_teap.c src/eap_peer/eap_teap_pac.c +OBJS += src/eap_common/eap_teap_common.c +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +NEED_T_PRF=y +NEED_SHA384=y +NEED_TLS_PRF_SHA256=y +NEED_TLS_PRF_SHA384=y +endif + +ifdef CONFIG_EAP_PAX +# EAP-PAX +ifeq ($(CONFIG_EAP_PAX), dyn) +L_CFLAGS += -DEAP_PAX_DYNAMIC +EAPDYN += src/eap_peer/eap_pax.so +else +L_CFLAGS += -DEAP_PAX +OBJS += src/eap_peer/eap_pax.c src/eap_common/eap_pax_common.c +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_SAKE +# EAP-SAKE +ifeq ($(CONFIG_EAP_SAKE), dyn) +L_CFLAGS += -DEAP_SAKE_DYNAMIC +EAPDYN += src/eap_peer/eap_sake.so +else +L_CFLAGS += -DEAP_SAKE +OBJS += src/eap_peer/eap_sake.c src/eap_common/eap_sake_common.c +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_GPSK +# EAP-GPSK +ifeq ($(CONFIG_EAP_GPSK), dyn) +L_CFLAGS += -DEAP_GPSK_DYNAMIC +EAPDYN += src/eap_peer/eap_gpsk.so +else +L_CFLAGS += -DEAP_GPSK +OBJS += src/eap_peer/eap_gpsk.c src/eap_common/eap_gpsk_common.c +endif +CONFIG_IEEE8021X_EAPOL=y +ifdef CONFIG_EAP_GPSK_SHA256 +L_CFLAGS += -DEAP_GPSK_SHA256 +endif +endif + +ifdef CONFIG_EAP_PWD +L_CFLAGS += -DEAP_PWD +OBJS += src/eap_peer/eap_pwd.c src/eap_common/eap_pwd_common.c +CONFIG_IEEE8021X_EAPOL=y +NEED_ECC=y +NEED_DRAGONFLY=y +endif + +ifdef CONFIG_EAP_EKE +# EAP-EKE +ifeq ($(CONFIG_EAP_EKE), dyn) +L_CFLAGS += -DEAP_EKE_DYNAMIC +EAPDYN += src/eap_peer/eap_eke.so +else +L_CFLAGS += -DEAP_EKE +OBJS += src/eap_peer/eap_eke.c src/eap_common/eap_eke_common.c +endif +CONFIG_IEEE8021X_EAPOL=y +NEED_DH_GROUPS=y +NEED_DH_GROUPS_ALL=y +NEED_AES_CBC=y +endif + +ifdef CONFIG_WPS +# EAP-WSC +L_CFLAGS += -DCONFIG_WPS -DEAP_WSC +OBJS += wps_supplicant.c +OBJS += src/utils/uuid.c +OBJS += src/eap_peer/eap_wsc.c src/eap_common/eap_wsc_common.c +OBJS += src/wps/wps.c +OBJS += src/wps/wps_common.c +OBJS += src/wps/wps_attr_parse.c +OBJS += src/wps/wps_attr_build.c +OBJS += src/wps/wps_attr_process.c +OBJS += src/wps/wps_dev_attr.c +OBJS += src/wps/wps_enrollee.c +OBJS += src/wps/wps_registrar.c +CONFIG_IEEE8021X_EAPOL=y +NEED_DH_GROUPS=y +NEED_BASE64=y +NEED_AES_CBC=y +NEED_MODEXP=y + +ifdef CONFIG_WPS_NFC +L_CFLAGS += -DCONFIG_WPS_NFC +OBJS += src/wps/ndef.c +NEED_WPS_OOB=y +endif + +ifdef NEED_WPS_OOB +L_CFLAGS += -DCONFIG_WPS_OOB +endif + +ifdef CONFIG_WPS_ER +CONFIG_WPS_UPNP=y +L_CFLAGS += -DCONFIG_WPS_ER +OBJS += src/wps/wps_er.c +OBJS += src/wps/wps_er_ssdp.c +endif + +ifdef CONFIG_WPS_UPNP +L_CFLAGS += -DCONFIG_WPS_UPNP +OBJS += src/wps/wps_upnp.c +OBJS += src/wps/wps_upnp_ssdp.c +OBJS += src/wps/wps_upnp_web.c +OBJS += src/wps/wps_upnp_event.c +OBJS += src/wps/wps_upnp_ap.c +OBJS += src/wps/upnp_xml.c +OBJS += src/wps/httpread.c +OBJS += src/wps/http_client.c +OBJS += src/wps/http_server.c +endif + +ifdef CONFIG_WPS_STRICT +L_CFLAGS += -DCONFIG_WPS_STRICT +OBJS += src/wps/wps_validate.c +endif + +ifdef CONFIG_WPS_TESTING +L_CFLAGS += -DCONFIG_WPS_TESTING +endif + +ifdef CONFIG_WPS_REG_DISABLE_OPEN +L_CFLAGS += -DCONFIG_WPS_REG_DISABLE_OPEN +endif + +endif + +ifdef CONFIG_EAP_IKEV2 +# EAP-IKEv2 +ifeq ($(CONFIG_EAP_IKEV2), dyn) +L_CFLAGS += -DEAP_IKEV2_DYNAMIC +EAPDYN += src/eap_peer/eap_ikev2.so src/eap_peer/ikev2.c +EAPDYN += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c +else +L_CFLAGS += -DEAP_IKEV2 +OBJS += src/eap_peer/eap_ikev2.c src/eap_peer/ikev2.c +OBJS += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c +endif +CONFIG_IEEE8021X_EAPOL=y +NEED_DH_GROUPS=y +NEED_DH_GROUPS_ALL=y +NEED_MODEXP=y +NEED_CIPHER=y +endif + +ifdef CONFIG_EAP_VENDOR_TEST +ifeq ($(CONFIG_EAP_VENDOR_TEST), dyn) +L_CFLAGS += -DEAP_VENDOR_TEST_DYNAMIC +EAPDYN += src/eap_peer/eap_vendor_test.so +else +L_CFLAGS += -DEAP_VENDOR_TEST +OBJS += src/eap_peer/eap_vendor_test.c +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_TNC +# EAP-TNC +L_CFLAGS += -DEAP_TNC +OBJS += src/eap_peer/eap_tnc.c +OBJS += src/eap_peer/tncc.c +NEED_BASE64=y +ifndef CONFIG_NATIVE_WINDOWS +ifndef CONFIG_DRIVER_BSD +LIBS += -ldl +endif +endif +endif + +ifdef CONFIG_IEEE8021X_EAPOL +# IEEE 802.1X/EAPOL state machines (e.g., for RADIUS authentication) +L_CFLAGS += -DIEEE8021X_EAPOL +OBJS += src/eapol_supp/eapol_supp_sm.c +OBJS += src/eap_peer/eap.c src/eap_peer/eap_methods.c +NEED_EAP_COMMON=y +ifdef CONFIG_DYNAMIC_EAP_METHODS +L_CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS +LIBS += -ldl -rdynamic +endif +endif + +ifdef CONFIG_AP +NEED_EAP_COMMON=y +NEED_RSN_AUTHENTICATOR=y +L_CFLAGS += -DCONFIG_AP +OBJS += ap.c +L_CFLAGS += -DCONFIG_NO_RADIUS +L_CFLAGS += -DCONFIG_NO_ACCOUNTING +L_CFLAGS += -DCONFIG_NO_VLAN +OBJS += src/ap/hostapd.c +OBJS += src/ap/wpa_auth_glue.c +OBJS += src/ap/utils.c +OBJS += src/ap/authsrv.c +OBJS += src/ap/ap_config.c +OBJS += src/ap/sta_info.c +OBJS += src/ap/tkip_countermeasures.c +OBJS += src/ap/ap_mlme.c +OBJS += src/ap/ieee802_1x.c +OBJS += src/eapol_auth/eapol_auth_sm.c +OBJS += src/ap/ieee802_11_auth.c +OBJS += src/ap/ieee802_11_shared.c +OBJS += src/ap/drv_callbacks.c +OBJS += src/ap/ap_drv_ops.c +OBJS += src/ap/beacon.c +OBJS += src/ap/bss_load.c +OBJS += src/ap/eap_user_db.c +OBJS += src/ap/neighbor_db.c +OBJS += src/ap/rrm.c +OBJS += src/ap/ieee802_11_ht.c +ifdef CONFIG_IEEE80211AC +OBJS += src/ap/ieee802_11_vht.c +endif +ifdef CONFIG_IEEE80211AX +OBJS += src/ap/ieee802_11_he.c +endif +ifdef CONFIG_WNM_AP +L_CFLAGS += -DCONFIG_WNM_AP +OBJS += src/ap/wnm_ap.c +endif +ifdef CONFIG_MBO +OBJS += src/ap/mbo_ap.c +endif +ifdef CONFIG_FILS +OBJS += src/ap/fils_hlp.c +endif +ifdef CONFIG_CTRL_IFACE +OBJS += src/ap/ctrl_iface_ap.c +endif + +L_CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY +OBJS += src/eap_server/eap_server.c +OBJS += src/eap_server/eap_server_identity.c +OBJS += src/eap_server/eap_server_methods.c + +ifdef CONFIG_IEEE80211AC +L_CFLAGS += -DCONFIG_IEEE80211AC +endif +ifdef CONFIG_IEEE80211AX +L_CFLAGS += -DCONFIG_IEEE80211AX +endif + +ifdef NEED_AP_MLME +OBJS += src/ap/wmm.c +OBJS += src/ap/ap_list.c +OBJS += src/ap/ieee802_11.c +OBJS += src/ap/hw_features.c +OBJS += src/ap/dfs.c +L_CFLAGS += -DNEED_AP_MLME +endif +ifdef CONFIG_WPS +L_CFLAGS += -DEAP_SERVER_WSC +OBJS += src/ap/wps_hostapd.c +OBJS += src/eap_server/eap_server_wsc.c +endif +ifdef CONFIG_DPP +OBJS += src/ap/dpp_hostapd.c +OBJS += src/ap/gas_query_ap.c +NEED_AP_GAS_SERV=y +endif +ifdef CONFIG_INTERWORKING +NEED_AP_GAS_SERV=y +endif +ifdef NEED_AP_GAS_SERV +OBJS += src/ap/gas_serv.c +endif +ifdef CONFIG_HS20 +OBJS += src/ap/hs20.c +endif +endif + +ifdef CONFIG_MBO +OBJS += mbo.c +L_CFLAGS += -DCONFIG_MBO +endif + +ifdef CONFIG_TESTING_OPTIONS +L_CFLAGS += -DCONFIG_TESTING_OPTIONS +endif + +ifdef NEED_RSN_AUTHENTICATOR +L_CFLAGS += -DCONFIG_NO_RADIUS +NEED_AES_WRAP=y +OBJS += src/ap/wpa_auth.c +OBJS += src/ap/wpa_auth_ie.c +OBJS += src/ap/pmksa_cache_auth.c +endif + +ifdef CONFIG_ACS +L_CFLAGS += -DCONFIG_ACS +OBJS += src/ap/acs.c +LIBS += -lm +endif + +ifdef CONFIG_PCSC +# PC/SC interface for smartcards (USIM, GSM SIM) +L_CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC +OBJS += src/utils/pcsc_funcs.c +# -lpthread may not be needed depending on how pcsc-lite was configured +ifdef CONFIG_NATIVE_WINDOWS +#Once MinGW gets support for WinScard, -lwinscard could be used instead of the +#dynamic symbol loading that is now used in pcsc_funcs.c +#LIBS += -lwinscard +else +LIBS += -lpcsclite -lpthread +endif +endif + +ifdef CONFIG_SIM_SIMULATOR +L_CFLAGS += -DCONFIG_SIM_SIMULATOR +NEED_MILENAGE=y +endif + +ifdef CONFIG_USIM_SIMULATOR +L_CFLAGS += -DCONFIG_USIM_SIMULATOR +NEED_MILENAGE=y +endif + +ifdef NEED_MILENAGE +OBJS += src/crypto/milenage.c +NEED_AES_ENCBLOCK=y +endif + +ifdef CONFIG_PKCS12 +L_CFLAGS += -DPKCS12_FUNCS +endif + +ifdef CONFIG_SMARTCARD +L_CFLAGS += -DCONFIG_SMARTCARD +endif + +ifdef NEED_DRAGONFLY +OBJS += src/common/dragonfly.c +endif + +ifdef MS_FUNCS +OBJS += src/crypto/ms_funcs.c +NEED_DES=y +NEED_MD4=y +endif + +ifdef CHAP +OBJS += src/eap_common/chap.c +endif + +ifdef TLS_FUNCS +NEED_DES=y +# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, EAP_TTLS, and EAP_FAST) +OBJS += src/eap_peer/eap_tls_common.c +ifndef CONFIG_FIPS +NEED_TLS_PRF=y +NEED_SHA1=y +NEED_MD5=y +endif +endif + +ifndef CONFIG_TLS +CONFIG_TLS=openssl +endif + +ifdef CONFIG_TLSV11 +L_CFLAGS += -DCONFIG_TLSV11 +endif + +ifdef CONFIG_TLSV12 +L_CFLAGS += -DCONFIG_TLSV12 +endif + +ifeq ($(CONFIG_TLS), openssl) +ifdef TLS_FUNCS +L_CFLAGS += -DEAP_TLS_OPENSSL +OBJS += src/crypto/tls_openssl.c +OBJS += src/crypto/tls_openssl_ocsp.c +LIBS += -lssl +endif +OBJS += src/crypto/crypto_openssl.c +OBJS_p += src/crypto/crypto_openssl.c +ifdef NEED_FIPS186_2_PRF +OBJS += src/crypto/fips_prf_openssl.c +endif +NEED_TLS_PRF_SHA256=y +LIBS += -lcrypto +LIBS_p += -lcrypto +ifdef CONFIG_TLS_ADD_DL +LIBS += -ldl +LIBS_p += -ldl +endif +ifndef CONFIG_TLS_DEFAULT_CIPHERS +CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW" +endif +L_CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" +endif + +ifeq ($(CONFIG_TLS), gnutls) +ifndef CONFIG_CRYPTO +# default to libgcrypt +CONFIG_CRYPTO=gnutls +endif +ifdef TLS_FUNCS +OBJS += src/crypto/tls_gnutls.c +LIBS += -lgnutls -lgpg-error +endif +OBJS += src/crypto/crypto_$(CONFIG_CRYPTO).c +OBJS_p += src/crypto/crypto_$(CONFIG_CRYPTO).c +ifdef NEED_FIPS186_2_PRF +OBJS += src/crypto/fips_prf_internal.c +OBJS += src/crypto/sha1-internal.c +endif +ifeq ($(CONFIG_CRYPTO), gnutls) +LIBS += -lgcrypt +LIBS_p += -lgcrypt +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +ifeq ($(CONFIG_CRYPTO), nettle) +LIBS += -lnettle -lgmp +LIBS_p += -lnettle -lgmp +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +endif + +ifeq ($(CONFIG_TLS), internal) +ifndef CONFIG_CRYPTO +CONFIG_CRYPTO=internal +endif +ifdef TLS_FUNCS +OBJS += src/crypto/crypto_internal-rsa.c +OBJS += src/crypto/tls_internal.c +OBJS += src/tls/tlsv1_common.c +OBJS += src/tls/tlsv1_record.c +OBJS += src/tls/tlsv1_cred.c +OBJS += src/tls/tlsv1_client.c +OBJS += src/tls/tlsv1_client_write.c +OBJS += src/tls/tlsv1_client_read.c +OBJS += src/tls/tlsv1_client_ocsp.c +NEED_ASN1=y +OBJS += src/tls/rsa.c +OBJS += src/tls/x509v3.c +OBJS += src/tls/pkcs1.c +OBJS += src/tls/pkcs5.c +OBJS += src/tls/pkcs8.c +NEED_BASE64=y +NEED_TLS_PRF=y +ifdef CONFIG_TLSV12 +NEED_TLS_PRF_SHA256=y +endif +NEED_MODEXP=y +NEED_CIPHER=y +L_CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT +endif +ifdef NEED_CIPHER +NEED_DES=y +OBJS += src/crypto/crypto_internal-cipher.c +endif +ifdef NEED_MODEXP +OBJS += src/crypto/crypto_internal-modexp.c +OBJS += src/tls/bignum.c +endif +ifeq ($(CONFIG_CRYPTO), libtomcrypt) +OBJS += src/crypto/crypto_libtomcrypt.c +OBJS_p += src/crypto/crypto_libtomcrypt.c +LIBS += -ltomcrypt -ltfm +LIBS_p += -ltomcrypt -ltfm +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +ifeq ($(CONFIG_CRYPTO), internal) +OBJS += src/crypto/crypto_internal.c +OBJS_p += src/crypto/crypto_internal.c +NEED_AES_ENC=y +L_CFLAGS += -DCONFIG_CRYPTO_INTERNAL +ifdef CONFIG_INTERNAL_LIBTOMMATH +L_CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH +ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST +L_CFLAGS += -DLTM_FAST +endif +else +LIBS += -ltommath +LIBS_p += -ltommath +endif +CONFIG_INTERNAL_AES=y +CONFIG_INTERNAL_DES=y +CONFIG_INTERNAL_SHA1=y +CONFIG_INTERNAL_MD4=y +CONFIG_INTERNAL_MD5=y +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_SHA384=y +CONFIG_INTERNAL_SHA512=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +ifeq ($(CONFIG_CRYPTO), cryptoapi) +OBJS += src/crypto/crypto_cryptoapi.c +OBJS_p += src/crypto/crypto_cryptoapi.c +L_CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +endif +endif + +ifeq ($(CONFIG_TLS), none) +ifdef TLS_FUNCS +OBJS += src/crypto/tls_none.c +L_CFLAGS += -DEAP_TLS_NONE +CONFIG_INTERNAL_AES=y +CONFIG_INTERNAL_SHA1=y +CONFIG_INTERNAL_MD5=y +endif +OBJS += src/crypto/crypto_none.c +OBJS_p += src/crypto/crypto_none.c +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +endif + +ifdef TLS_FUNCS +ifdef CONFIG_SMARTCARD +ifndef CONFIG_NATIVE_WINDOWS +ifneq ($(CONFIG_L2_PACKET), freebsd) +LIBS += -ldl +endif +endif +endif +endif + +ifndef TLS_FUNCS +OBJS += src/crypto/tls_none.c +ifeq ($(CONFIG_TLS), internal) +CONFIG_INTERNAL_AES=y +CONFIG_INTERNAL_SHA1=y +CONFIG_INTERNAL_MD5=y +CONFIG_INTERNAL_RC4=y +endif +endif + +AESOBJS = # none so far (see below) +ifdef CONFIG_INTERNAL_AES +AESOBJS += src/crypto/aes-internal.c src/crypto/aes-internal-dec.c +endif + +ifneq ($(CONFIG_TLS), openssl) +NEED_INTERNAL_AES_WRAP=y +endif +ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP +# Seems to be needed at least with BoringSSL +NEED_INTERNAL_AES_WRAP=y +L_CFLAGS += -DCONFIG_OPENSSL_INTERNAL_AES_WRAP +endif +ifdef CONFIG_FIPS +# Have to use internal AES key wrap routines to use OpenSSL EVP since the +# OpenSSL AES_wrap_key()/AES_unwrap_key() API is not available in FIPS mode. +NEED_INTERNAL_AES_WRAP=y +endif + +ifdef NEED_INTERNAL_AES_WRAP +AESOBJS += src/crypto/aes-unwrap.c +endif +ifdef NEED_AES_EAX +AESOBJS += src/crypto/aes-eax.c +NEED_AES_CTR=y +endif +ifdef NEED_AES_SIV +AESOBJS += src/crypto/aes-siv.c +NEED_AES_CTR=y +endif +ifdef NEED_AES_CTR +AESOBJS += src/crypto/aes-ctr.c +endif +ifdef NEED_AES_ENCBLOCK +AESOBJS += src/crypto/aes-encblock.c +endif +NEED_AES_ENC=y +ifdef CONFIG_OPENSSL_CMAC +L_CFLAGS += -DCONFIG_OPENSSL_CMAC +else +AESOBJS += src/crypto/aes-omac1.c +endif +ifdef NEED_AES_WRAP +NEED_AES_ENC=y +ifdef NEED_INTERNAL_AES_WRAP +AESOBJS += src/crypto/aes-wrap.c +endif +endif +ifdef NEED_AES_CBC +NEED_AES_ENC=y +ifneq ($(CONFIG_TLS), openssl) +AESOBJS += src/crypto/aes-cbc.c +endif +endif +ifdef NEED_AES_ENC +ifdef CONFIG_INTERNAL_AES +AESOBJS += src/crypto/aes-internal-enc.c +endif +endif +ifdef NEED_AES +OBJS += $(AESOBJS) +endif + +SHA1OBJS = +ifdef NEED_SHA1 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), gnutls) +SHA1OBJS += src/crypto/sha1.c +endif +endif +SHA1OBJS += src/crypto/sha1-prf.c +ifdef CONFIG_INTERNAL_SHA1 +SHA1OBJS += src/crypto/sha1-internal.c +ifdef NEED_FIPS186_2_PRF +SHA1OBJS += src/crypto/fips_prf_internal.c +endif +endif +ifdef CONFIG_NO_WPA_PASSPHRASE +L_CFLAGS += -DCONFIG_NO_PBKDF2 +else +ifneq ($(CONFIG_TLS), openssl) +SHA1OBJS += src/crypto/sha1-pbkdf2.c +endif +endif +ifdef NEED_T_PRF +SHA1OBJS += src/crypto/sha1-tprf.c +endif +ifdef NEED_TLS_PRF +SHA1OBJS += src/crypto/sha1-tlsprf.c +endif +endif + +MD5OBJS = +ifndef CONFIG_FIPS +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), gnutls) +MD5OBJS += src/crypto/md5.c +endif +endif +endif +ifdef NEED_MD5 +ifdef CONFIG_INTERNAL_MD5 +MD5OBJS += src/crypto/md5-internal.c +endif +OBJS += $(MD5OBJS) +OBJS_p += $(MD5OBJS) +endif + +ifdef NEED_MD4 +ifdef CONFIG_INTERNAL_MD4 +OBJS += src/crypto/md4-internal.c +endif +endif + +DESOBJS = # none needed when not internal +ifdef NEED_DES +ifdef CONFIG_INTERNAL_DES +DESOBJS += src/crypto/des-internal.c +endif +endif + +ifdef CONFIG_NO_RC4 +L_CFLAGS += -DCONFIG_NO_RC4 +endif + +ifdef NEED_RC4 +ifdef CONFIG_INTERNAL_RC4 +ifndef CONFIG_NO_RC4 +OBJS += src/crypto/rc4.c +endif +endif +endif + +SHA256OBJS = # none by default +L_CFLAGS += -DCONFIG_SHA256 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), gnutls) +SHA256OBJS += src/crypto/sha256.c +endif +endif +SHA256OBJS += src/crypto/sha256-prf.c +ifdef CONFIG_INTERNAL_SHA256 +SHA256OBJS += src/crypto/sha256-internal.c +endif +ifdef CONFIG_INTERNAL_SHA384 +L_CFLAGS += -DCONFIG_INTERNAL_SHA384 +SHA256OBJS += src/crypto/sha384-internal.c +endif +ifdef CONFIG_INTERNAL_SHA512 +L_CFLAGS += -DCONFIG_INTERNAL_SHA512 +SHA256OBJS += src/crypto/sha512-internal.c +endif +ifdef NEED_TLS_PRF_SHA256 +SHA256OBJS += src/crypto/sha256-tlsprf.c +endif +ifdef NEED_TLS_PRF_SHA384 +SHA256OBJS += src/crypto/sha384-tlsprf.c +endif +ifdef NEED_HMAC_SHA256_KDF +L_CFLAGS += -DCONFIG_HMAC_SHA256_KDF +SHA256OBJS += src/crypto/sha256-kdf.c +endif +ifdef NEED_HMAC_SHA384_KDF +L_CFLAGS += -DCONFIG_HMAC_SHA384_KDF +SHA256OBJS += src/crypto/sha384-kdf.c +endif +ifdef NEED_HMAC_SHA512_KDF +L_CFLAGS += -DCONFIG_HMAC_SHA512_KDF +SHA256OBJS += src/crypto/sha512-kdf.c +endif +OBJS += $(SHA256OBJS) +ifdef NEED_SHA384 +L_CFLAGS += -DCONFIG_SHA384 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), gnutls) +OBJS += src/crypto/sha384.c +endif +endif +OBJS += src/crypto/sha384-prf.c +endif +ifdef NEED_SHA512 +L_CFLAGS += -DCONFIG_SHA512 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), gnutls) +OBJS += src/crypto/sha512.c +endif +endif +OBJS += src/crypto/sha512-prf.c +endif + +ifdef NEED_ASN1 +OBJS += src/tls/asn1.c +endif + +ifdef NEED_DH_GROUPS +OBJS += src/crypto/dh_groups.c +endif +ifdef NEED_DH_GROUPS_ALL +L_CFLAGS += -DALL_DH_GROUPS +endif +ifdef CONFIG_INTERNAL_DH_GROUP5 +ifdef NEED_DH_GROUPS +OBJS += src/crypto/dh_group5.c +endif +endif + +ifdef NEED_ECC +L_CFLAGS += -DCONFIG_ECC +endif + +ifdef CONFIG_NO_RANDOM_POOL +L_CFLAGS += -DCONFIG_NO_RANDOM_POOL +else +OBJS += src/crypto/random.c +endif + +ifdef CONFIG_CTRL_IFACE +ifeq ($(CONFIG_CTRL_IFACE), y) +ifdef CONFIG_NATIVE_WINDOWS +CONFIG_CTRL_IFACE=named_pipe +else +CONFIG_CTRL_IFACE=unix +endif +endif +L_CFLAGS += -DCONFIG_CTRL_IFACE +ifeq ($(CONFIG_CTRL_IFACE), unix) +L_CFLAGS += -DCONFIG_CTRL_IFACE_UNIX +OBJS += src/common/ctrl_iface_common.c +endif +ifeq ($(CONFIG_CTRL_IFACE), udp) +L_CFLAGS += -DCONFIG_CTRL_IFACE_UDP +endif +ifeq ($(CONFIG_CTRL_IFACE), named_pipe) +L_CFLAGS += -DCONFIG_CTRL_IFACE_NAMED_PIPE +endif +ifeq ($(CONFIG_CTRL_IFACE), udp-remote) +CONFIG_CTRL_IFACE=udp +L_CFLAGS += -DCONFIG_CTRL_IFACE_UDP +L_CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE +endif +OBJS += ctrl_iface.c ctrl_iface_$(CONFIG_CTRL_IFACE).c +endif + +ifdef CONFIG_CTRL_IFACE_DBUS_NEW +L_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW +OBJS += dbus/dbus_dict_helpers.c +OBJS += dbus/dbus_new_helpers.c +OBJS += dbus/dbus_new.c dbus/dbus_new_handlers.c +OBJS += dbus/dbus_common.c +ifdef CONFIG_WPS +OBJS += dbus/dbus_new_handlers_wps.c +endif +ifdef CONFIG_P2P +OBJS += dbus/dbus_new_handlers_p2p.c +endif +ifdef CONFIG_CTRL_IFACE_DBUS_INTRO +OBJS += dbus/dbus_new_introspect.c +L_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO +endif +L_CFLAGS += $(DBUS_INCLUDE) +endif + +ifdef CONFIG_CTRL_IFACE_BINDER +WPA_SUPPLICANT_USE_BINDER=y +L_CFLAGS += -DCONFIG_BINDER -DCONFIG_CTRL_IFACE_BINDER +endif + +ifdef CONFIG_READLINE +OBJS_c += src/utils/edit_readline.c +LIBS_c += -lncurses -lreadline +else +ifdef CONFIG_WPA_CLI_EDIT +OBJS_c += src/utils/edit.c +else +OBJS_c += src/utils/edit_simple.c +endif +endif + +ifdef CONFIG_NATIVE_WINDOWS +L_CFLAGS += -DCONFIG_NATIVE_WINDOWS +LIBS += -lws2_32 -lgdi32 -lcrypt32 +LIBS_c += -lws2_32 +LIBS_p += -lws2_32 -lgdi32 +ifeq ($(CONFIG_CRYPTO), cryptoapi) +LIBS_p += -lcrypt32 +endif +endif + +ifdef CONFIG_NO_STDOUT_DEBUG +L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG +ifndef CONFIG_CTRL_IFACE +L_CFLAGS += -DCONFIG_NO_WPA_MSG +endif +endif + +ifdef CONFIG_ANDROID_LOG +L_CFLAGS += -DCONFIG_ANDROID_LOG +endif + +ifdef CONFIG_IPV6 +# for eapol_test only +L_CFLAGS += -DCONFIG_IPV6 +endif + +ifdef NEED_BASE64 +OBJS += src/utils/base64.c +endif + +ifdef NEED_SME +OBJS += sme.c +L_CFLAGS += -DCONFIG_SME +endif + +OBJS += src/common/ieee802_11_common.c +OBJS += src/common/hw_features_common.c + +ifdef NEED_EAP_COMMON +OBJS += src/eap_common/eap_common.c +endif + +ifndef CONFIG_MAIN +CONFIG_MAIN=main +endif + +ifdef CONFIG_DEBUG_SYSLOG +L_CFLAGS += -DCONFIG_DEBUG_SYSLOG +ifdef CONFIG_DEBUG_SYSLOG_FACILITY +L_CFLAGS += -DLOG_HOSTAPD="$(CONFIG_DEBUG_SYSLOG_FACILITY)" +endif +endif + +ifdef CONFIG_DEBUG_LINUX_TRACING +L_CFLAGS += -DCONFIG_DEBUG_LINUX_TRACING +endif + +ifdef CONFIG_DEBUG_FILE +L_CFLAGS += -DCONFIG_DEBUG_FILE +endif + +ifdef CONFIG_DELAYED_MIC_ERROR_REPORT +L_CFLAGS += -DCONFIG_DELAYED_MIC_ERROR_REPORT +endif + +ifdef CONFIG_FIPS +L_CFLAGS += -DCONFIG_FIPS +endif + +OBJS += $(SHA1OBJS) $(DESOBJS) + +OBJS_p += $(SHA1OBJS) +OBJS_p += $(SHA256OBJS) + +ifdef CONFIG_BGSCAN_SIMPLE +L_CFLAGS += -DCONFIG_BGSCAN_SIMPLE +OBJS += bgscan_simple.c +NEED_BGSCAN=y +endif + +ifdef CONFIG_BGSCAN_LEARN +L_CFLAGS += -DCONFIG_BGSCAN_LEARN +OBJS += bgscan_learn.c +NEED_BGSCAN=y +endif + +ifdef NEED_BGSCAN +L_CFLAGS += -DCONFIG_BGSCAN +OBJS += bgscan.c +endif + +ifdef CONFIG_AUTOSCAN_EXPONENTIAL +L_CFLAGS += -DCONFIG_AUTOSCAN_EXPONENTIAL +OBJS += autoscan_exponential.c +NEED_AUTOSCAN=y +endif + +ifdef CONFIG_AUTOSCAN_PERIODIC +L_CFLAGS += -DCONFIG_AUTOSCAN_PERIODIC +OBJS += autoscan_periodic.c +NEED_AUTOSCAN=y +endif + +ifdef NEED_AUTOSCAN +L_CFLAGS += -DCONFIG_AUTOSCAN +OBJS += autoscan.c +endif + +ifdef CONFIG_EXT_PASSWORD_TEST +OBJS += src/utils/ext_password_test.c +L_CFLAGS += -DCONFIG_EXT_PASSWORD_TEST +NEED_EXT_PASSWORD=y +endif + +ifdef CONFIG_EXT_PASSWORD_FILE +OBJS += src/utils/ext_password_file.c +L_CFLAGS += -DCONFIG_EXT_PASSWORD_FILE +NEED_EXT_PASSWORD=y +endif + +ifdef NEED_EXT_PASSWORD +OBJS += src/utils/ext_password.c +L_CFLAGS += -DCONFIG_EXT_PASSWORD +endif + +ifdef NEED_GAS_SERVER +OBJS += src/common/gas_server.c +L_CFLAGS += -DCONFIG_GAS_SERVER +NEED_GAS=y +endif + +ifdef NEED_GAS +OBJS += src/common/gas.c +OBJS += gas_query.c +L_CFLAGS += -DCONFIG_GAS +NEED_OFFCHANNEL=y +endif + +ifdef NEED_OFFCHANNEL +OBJS += offchannel.c +L_CFLAGS += -DCONFIG_OFFCHANNEL +endif + +ifdef NEED_JSON +OBJS += src/utils/json.c +L_CFLAGS += -DCONFIG_JSON +endif + +OBJS += src/drivers/driver_common.c + +OBJS += wpa_supplicant.c events.c bssid_ignore.c wpas_glue.c scan.c +OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.c +OBJS_t += src/radius/radius_client.c +OBJS_t += src/radius/radius.c +OBJS_t2 := $(OBJS) $(OBJS_l2) preauth_test.c +OBJS += $(CONFIG_MAIN).c + +ifdef CONFIG_PRIVSEP +OBJS_priv += $(OBJS_d) src/drivers/drivers.c +OBJS_priv += $(OBJS_l2) +OBJS_priv += src/utils/os_$(CONFIG_OS).c +OBJS_priv += src/utils/$(CONFIG_ELOOP).c +OBJS_priv += src/utils/common.c +OBJS_priv += src/utils/wpa_debug.c +OBJS_priv += src/utils/wpabuf.c +OBJS_priv += wpa_priv.c +ifdef CONFIG_DRIVER_NL80211 +OBJS_priv += src/common/ieee802_11_common.c +endif +OBJS += src/l2_packet/l2_packet_privsep.c +OBJS += src/drivers/driver_privsep.c +EXTRA_progs += wpa_priv +else +OBJS += $(OBJS_d) src/drivers/drivers.c +OBJS += $(OBJS_l2) +endif + +ifdef CONFIG_NDIS_EVENTS_INTEGRATED +L_CFLAGS += -DCONFIG_NDIS_EVENTS_INTEGRATED +OBJS += src/drivers/ndis_events.c +EXTRALIBS += -loleaut32 -lole32 -luuid +ifdef PLATFORMSDKLIB +EXTRALIBS += $(PLATFORMSDKLIB)/WbemUuid.Lib +else +EXTRALIBS += WbemUuid.Lib +endif +endif + +ifndef LDO +LDO=$(CC) +endif + +######################## + +include $(CLEAR_VARS) +LOCAL_MODULE := wpa_cli +LOCAL_MODULE_TAGS := debug +LOCAL_SHARED_LIBRARIES := libc libcutils liblog +LOCAL_CFLAGS := $(L_CFLAGS) +LOCAL_SRC_FILES := $(OBJS_c) +LOCAL_C_INCLUDES := $(INCLUDES) +include $(BUILD_EXECUTABLE) + +######################## +include $(CLEAR_VARS) +LOCAL_MODULE := wpa_supplicant +ifdef CONFIG_DRIVER_CUSTOM +LOCAL_STATIC_LIBRARIES := libCustomWifi +endif +ifneq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB),) +LOCAL_STATIC_LIBRARIES += $(BOARD_WPA_SUPPLICANT_PRIVATE_LIB) +endif +LOCAL_SHARED_LIBRARIES := libc libcutils liblog +ifdef CONFIG_EAP_PROXY +LOCAL_STATIC_LIBRARIES += $(LIB_STATIC_EAP_PROXY) +LOCAL_SHARED_LIBRARIES += $(LIB_SHARED_EAP_PROXY) +endif +ifeq ($(CONFIG_TLS), openssl) +LOCAL_SHARED_LIBRARIES += libcrypto libssl libkeystore_binder +endif + +# With BoringSSL we need libkeystore-engine in order to provide access to +# keystore keys. +LOCAL_SHARED_LIBRARIES += libkeystore-engine + +ifdef CONFIG_DRIVER_NL80211 +ifneq ($(wildcard external/libnl),) +LOCAL_SHARED_LIBRARIES += libnl +else +LOCAL_STATIC_LIBRARIES += libnl_2 +endif +endif +LOCAL_CFLAGS := $(L_CFLAGS) +LOCAL_SRC_FILES := $(OBJS) +LOCAL_C_INCLUDES := $(INCLUDES) +ifeq ($(DBUS), y) +LOCAL_SHARED_LIBRARIES += libdbus +endif +ifeq ($(WPA_SUPPLICANT_USE_BINDER), y) +LOCAL_SHARED_LIBRARIES += libbinder libutils +LOCAL_STATIC_LIBRARIES += libwpa_binder libwpa_binder_interface +endif +include $(BUILD_EXECUTABLE) + +######################## +# +#include $(CLEAR_VARS) +#LOCAL_MODULE := eapol_test +#ifdef CONFIG_DRIVER_CUSTOM +#LOCAL_STATIC_LIBRARIES := libCustomWifi +#endif +#LOCAL_SHARED_LIBRARIES := libc libcrypto libssl +#LOCAL_CFLAGS := $(L_CFLAGS) +#LOCAL_SRC_FILES := $(OBJS_t) +#LOCAL_C_INCLUDES := $(INCLUDES) +#include $(BUILD_EXECUTABLE) +# +######################## +# +#local_target_dir := $(TARGET_OUT)/etc/wifi +# +#include $(CLEAR_VARS) +#LOCAL_MODULE := wpa_supplicant.conf +#LOCAL_MODULE_CLASS := ETC +#LOCAL_MODULE_PATH := $(local_target_dir) +#LOCAL_SRC_FILES := $(LOCAL_MODULE) +#include $(BUILD_PREBUILT) +# +######################## + +include $(CLEAR_VARS) +LOCAL_MODULE = libwpa_client +LOCAL_CFLAGS = $(L_CFLAGS) +LOCAL_SRC_FILES = src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c +LOCAL_C_INCLUDES = $(INCLUDES) +LOCAL_SHARED_LIBRARIES := libcutils liblog +LOCAL_COPY_HEADERS_TO := libwpa_client +LOCAL_COPY_HEADERS := src/common/wpa_ctrl.h +LOCAL_COPY_HEADERS += src/common/qca-vendor.h +include $(BUILD_SHARED_LIBRARY) + +ifeq ($(WPA_SUPPLICANT_USE_BINDER), y) +### Binder interface library ### +######################## + +include $(CLEAR_VARS) +LOCAL_MODULE := libwpa_binder_interface +LOCAL_AIDL_INCLUDES := \ + $(LOCAL_PATH)/binder \ + frameworks/native/aidl/binder +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH)/binder +LOCAL_CPPFLAGS := $(L_CPPFLAGS) +LOCAL_SRC_FILES := \ + binder/binder_constants.cpp \ + binder/fi/w1/wpa_supplicant/ISupplicant.aidl \ + binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl \ + binder/fi/w1/wpa_supplicant/IIface.aidl +LOCAL_SHARED_LIBRARIES := libbinder +include $(BUILD_STATIC_LIBRARY) + +### Binder service library ### +######################## + +include $(CLEAR_VARS) +LOCAL_MODULE := libwpa_binder +LOCAL_CPPFLAGS := $(L_CPPFLAGS) +LOCAL_CFLAGS := $(L_CFLAGS) +LOCAL_C_INCLUDES := $(INCLUDES) +LOCAL_SRC_FILES := \ + binder/binder.cpp binder/binder_manager.cpp \ + binder/supplicant.cpp binder/iface.cpp +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libutils +LOCAL_STATIC_LIBRARIES := libwpa_binder_interface +include $(BUILD_STATIC_LIBRARY) + +endif # BINDER == y diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog new file mode 100644 index 000000000000..efcc6cd9c9ba --- /dev/null +++ b/wpa_supplicant/ChangeLog @@ -0,0 +1,2500 @@ +ChangeLog for wpa_supplicant + +2022-01-16 - v2.10 + * SAE changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + - added support for the hash-to-element mechanism (sae_pwe=1 or + sae_pwe=2); this is currently disabled by default, but will likely + get enabled by default in the future + - fixed PMKSA caching with OKC + - added support for SAE-PK + * EAP-pwd changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + * fixed P2P provision discovery processing of a specially constructed + invalid frame + [https://w1.fi/security/2021-1/] + * fixed P2P group information processing of a specially constructed + invalid frame + [https://w1.fi/security/2020-2/] + * fixed PMF disconnection protection bypass in AP mode + [https://w1.fi/security/2019-7/] + * added support for using OpenSSL 3.0 + * increased the maximum number of EAP message exchanges (mainly to + support cases with very large certificates) + * fixed various issues in experimental support for EAP-TEAP peer + * added support for DPP release 2 (Wi-Fi Device Provisioning Protocol) + * a number of MKA/MACsec fixes and extensions + * added support for SAE (WPA3-Personal) AP mode configuration + * added P2P support for EDMG (IEEE 802.11ay) channels + * fixed EAP-FAST peer with TLS GCM/CCM ciphers + * improved throughput estimation and BSS selection + * dropped support for libnl 1.1 + * added support for nl80211 control port for EAPOL frame TX/RX + * fixed OWE key derivation with groups 20 and 21; this breaks backwards + compatibility for these groups while the default group 19 remains + backwards compatible + * added support for Beacon protection + * added support for Extended Key ID for pairwise keys + * removed WEP support from the default build (CONFIG_WEP=y can be used + to enable it, if really needed) + * added a build option to remove TKIP support (CONFIG_NO_TKIP=y) + * added support for Transition Disable mechanism to allow the AP to + automatically disable transition mode to improve security + * extended D-Bus interface + * added support for PASN + * added a file-based backend for external password storage to allow + secret information to be moved away from the main configuration file + without requiring external tools + * added EAP-TLS peer support for TLS 1.3 (disabled by default for now) + * added support for SCS, MSCS, DSCP policy + * changed driver interface selection to default to automatic fallback + to other compiled in options + * a large number of other fixes, cleanup, and extensions + +2019-08-07 - v2.9 + * SAE changes + - disable use of groups using Brainpool curves + - improved protection against side channel attacks + [https://w1.fi/security/2019-6/] + * EAP-pwd changes + - disable use of groups using Brainpool curves + - allow the set of groups to be configured (eap_pwd_groups) + - improved protection against side channel attacks + [https://w1.fi/security/2019-6/] + * fixed FT-EAP initial mobility domain association using PMKSA caching + (disabled by default for backwards compatibility; can be enabled + with ft_eap_pmksa_caching=1) + * fixed a regression in OpenSSL 1.1+ engine loading + * added validation of RSNE in (Re)Association Response frames + * fixed DPP bootstrapping URI parser of channel list + * extended EAP-SIM/AKA fast re-authentication to allow use with FILS + * extended ca_cert_blob to support PEM format + * improved robustness of P2P Action frame scheduling + * added support for EAP-SIM/AKA using anonymous@realm identity + * fixed Hotspot 2.0 credential selection based on roaming consortium + to ignore credentials without a specific EAP method + * added experimental support for EAP-TEAP peer (RFC 7170) + * added experimental support for EAP-TLS peer with TLS v1.3 + * fixed a regression in WMM parameter configuration for a TDLS peer + * fixed a regression in operation with drivers that offload 802.1X + 4-way handshake + * fixed an ECDH operation corner case with OpenSSL + +2019-04-21 - v2.8 + * SAE changes + - added support for SAE Password Identifier + - changed default configuration to enable only groups 19, 20, 21 + (i.e., disable groups 25 and 26) and disable all unsuitable groups + completely based on REVmd changes + - do not regenerate PWE unnecessarily when the AP uses the + anti-clogging token mechanisms + - fixed some association cases where both SAE and FT-SAE were enabled + on both the station and the selected AP + - started to prefer FT-SAE over SAE AKM if both are enabled + - started to prefer FT-SAE over FT-PSK if both are enabled + - fixed FT-SAE when SAE PMKSA caching is used + - reject use of unsuitable groups based on new implementation guidance + in REVmd (allow only FFC groups with prime >= 3072 bits and ECC + groups with prime >= 256) + - minimize timing and memory use differences in PWE derivation + [https://w1.fi/security/2019-1/] (CVE-2019-9494) + * EAP-pwd changes + - minimize timing and memory use differences in PWE derivation + [https://w1.fi/security/2019-2/] (CVE-2019-9495) + - verify server scalar/element + [https://w1.fi/security/2019-4/] (CVE-2019-9499) + - fix message reassembly issue with unexpected fragment + [https://w1.fi/security/2019-5/] + - enforce rand,mask generation rules more strictly + - fix a memory leak in PWE derivation + - disallow ECC groups with a prime under 256 bits (groups 25, 26, and + 27) + * fixed CONFIG_IEEE80211R=y (FT) build without CONFIG_FILS=y + * Hotspot 2.0 changes + - do not indicate release number that is higher than the one + AP supports + - added support for release number 3 + - enable PMF automatically for network profiles created from + credentials + * fixed OWE network profile saving + * fixed DPP network profile saving + * added support for RSN operating channel validation + (CONFIG_OCV=y and network profile parameter ocv=1) + * added Multi-AP backhaul STA support + * fixed build with LibreSSL + * number of MKA/MACsec fixes and extensions + * extended domain_match and domain_suffix_match to allow list of values + * fixed dNSName matching in domain_match and domain_suffix_match when + using wolfSSL + * started to prefer FT-EAP-SHA384 over WPA-EAP-SUITE-B-192 AKM if both + are enabled + * extended nl80211 Connect and external authentication to support + SAE, FT-SAE, FT-EAP-SHA384 + * fixed KEK2 derivation for FILS+FT + * extended client_cert file to allow loading of a chain of PEM + encoded certificates + * extended beacon reporting functionality + * extended D-Bus interface with number of new properties + * fixed a regression in FT-over-DS with mac80211-based drivers + * OpenSSL: allow systemwide policies to be overridden + * extended driver flags indication for separate 802.1X and PSK + 4-way handshake offload capability + * added support for random P2P Device/Interface Address use + * extended PEAP to derive EMSK to enable use with ERP/FILS + * extended WPS to allow SAE configuration to be added automatically + for PSK (wps_cred_add_sae=1) + * removed support for the old D-Bus interface (CONFIG_CTRL_IFACE_DBUS) + * extended domain_match and domain_suffix_match to allow list of values + * added a RSN workaround for misbehaving PMF APs that advertise + IGTK/BIP KeyID using incorrect byte order + * fixed PTK rekeying with FILS and FT + +2018-12-02 - v2.7 + * fixed WPA packet number reuse with replayed messages and key + reinstallation + [https://w1.fi/security/2017-1/] (CVE-2017-13077, CVE-2017-13078, + CVE-2017-13079, CVE-2017-13080, CVE-2017-13081, CVE-2017-13082, + CVE-2017-13086, CVE-2017-13087, CVE-2017-13088) + * fixed unauthenticated EAPOL-Key decryption in wpa_supplicant + [https://w1.fi/security/2018-1/] (CVE-2018-14526) + * added support for FILS (IEEE 802.11ai) shared key authentication + * added support for OWE (Opportunistic Wireless Encryption, RFC 8110; + and transition mode defined by WFA) + * added support for DPP (Wi-Fi Device Provisioning Protocol) + * added support for RSA 3k key case with Suite B 192-bit level + * fixed Suite B PMKSA caching not to update PMKID during each 4-way + handshake + * fixed EAP-pwd pre-processing with PasswordHashHash + * added EAP-pwd client support for salted passwords + * fixed a regression in TDLS prohibited bit validation + * started to use estimated throughput to avoid undesired signal + strength based roaming decision + * MACsec/MKA: + - new macsec_linux driver interface support for the Linux + kernel macsec module + - number of fixes and extensions + * added support for external persistent storage of PMKSA cache + (PMKSA_GET/PMKSA_ADD control interface commands; and + MESH_PMKSA_GET/MESH_PMKSA_SET for the mesh case) + * fixed mesh channel configuration pri/sec switch case + * added support for beacon report + * large number of other fixes, cleanup, and extensions + * added support for randomizing local address for GAS queries + (gas_rand_mac_addr parameter) + * fixed EAP-SIM/AKA/AKA' ext auth cases within TLS tunnel + * added option for using random WPS UUID (auto_uuid=1) + * added SHA256-hash support for OCSP certificate matching + * fixed EAP-AKA' to add AT_KDF into Synchronization-Failure + * fixed a regression in RSN pre-authentication candidate selection + * added option to configure allowed group management cipher suites + (group_mgmt network profile parameter) + * removed all PeerKey functionality + * fixed nl80211 AP and mesh mode configuration regression with + Linux 4.15 and newer + * added ap_isolate configuration option for AP mode + * added support for nl80211 to offload 4-way handshake into the driver + * added support for using wolfSSL cryptographic library + * SAE + - added support for configuring SAE password separately of the + WPA2 PSK/passphrase + - fixed PTK and EAPOL-Key integrity and key-wrap algorithm selection + for SAE; + note: this is not backwards compatible, i.e., both the AP and + station side implementations will need to be update at the same + time to maintain interoperability + - added support for Password Identifier + - fixed FT-SAE PMKID matching + * Hotspot 2.0 + - added support for fetching of Operator Icon Metadata ANQP-element + - added support for Roaming Consortium Selection element + - added support for Terms and Conditions + - added support for OSEN connection in a shared RSN BSS + - added support for fetching Venue URL information + * added support for using OpenSSL 1.1.1 + * FT + - disabled PMKSA caching with FT since it is not fully functional + - added support for SHA384 based AKM + - added support for BIP ciphers BIP-CMAC-256, BIP-GMAC-128, + BIP-GMAC-256 in addition to previously supported BIP-CMAC-128 + - fixed additional IE inclusion in Reassociation Request frame when + using FT protocol + +2016-10-02 - v2.6 + * fixed WNM Sleep Mode processing when PMF is not enabled + [http://w1.fi/security/2015-6/] (CVE-2015-5310) + * fixed EAP-pwd last fragment validation + [http://w1.fi/security/2015-7/] (CVE-2015-5315) + * fixed EAP-pwd unexpected Confirm message processing + [http://w1.fi/security/2015-8/] (CVE-2015-5316) + * fixed WPS configuration update vulnerability with malformed passphrase + [http://w1.fi/security/2016-1/] (CVE-2016-4476) + * fixed configuration update vulnerability with malformed parameters set + over the local control interface + [http://w1.fi/security/2016-1/] (CVE-2016-4477) + * fixed TK configuration to the driver in EAPOL-Key 3/4 retry case + * extended channel switch support for P2P GO + * started to throttle control interface event message bursts to avoid + issues with monitor sockets running out of buffer space + * mesh mode fixes/improvements + - generate proper AID for peer + - enable WMM by default + - add VHT support + - fix PMKID derivation + - improve robustness on various exchanges + - fix peer link counting in reconnect case + - improve mesh joining behavior + - allow DTIM period to be configured + - allow HT to be disabled (disable_ht=1) + - add MESH_PEER_ADD and MESH_PEER_REMOVE commands + - add support for PMKSA caching + - add minimal support for SAE group negotiation + - allow pairwise/group cipher to be configured in the network profile + - use ieee80211w profile parameter to enable/disable PMF and derive + a separate TX IGTK if PMF is enabled instead of using MGTK + incorrectly + - fix AEK and MTK derivation + - remove GTKdata and IGTKdata from Mesh Peering Confirm/Close + - note: these changes are not fully backwards compatible for secure + (RSN) mesh network + * fixed PMKID derivation with SAE + * added support for requesting and fetching arbitrary ANQP-elements + without internal support in wpa_supplicant for the specific element + (anqp[265]= in "BSS " command output) + * P2P + - filter control characters in group client device names to be + consistent with other P2P peer cases + - support VHT 80+80 MHz and 160 MHz + - indicate group completion in P2P Client role after data association + instead of already after the WPS provisioning step + - improve group-join operation to use SSID, if known, to filter BSS + entries + - added optional ssid= argument to P2P_CONNECT for join case + - added P2P_GROUP_MEMBER command to fetch client interface address + * P2PS + - fix follow-on PD Response behavior + - fix PD Response generation for unknown peer + - fix persistent group reporting + - add channel policy to PD Request + - add group SSID to the P2PS-PROV-DONE event + - allow "P2P_CONNECT p2ps" to be used without specifying the + default PIN + * BoringSSL + - support for OCSP stapling + - support building of h20-osu-client + * D-Bus + - add ExpectDisconnect() + - add global config parameters as properties + - add SaveConfig() + - add VendorElemAdd(), VendorElemGet(), VendorElemRem() + * fixed Suite B 192-bit AKM to use proper PMK length + (note: this makes old releases incompatible with the fixed behavior) + * improved PMF behavior for cases where the AP and STA has different + configuration by not trying to connect in some corner cases where the + connection cannot succeed + * added option to reopen debug log (e.g., to rotate the file) upon + receipt of SIGHUP signal + * EAP-pwd: added support for Brainpool Elliptic Curves + (with OpenSSL 1.0.2 and newer) + * fixed EAPOL reauthentication after FT protocol run + * fixed FTIE generation for 4-way handshake after FT protocol run + * extended INTERFACE_ADD command to allow certain type (sta/ap) + interface to be created + * fixed and improved various FST operations + * added 80+80 MHz and 160 MHz VHT support for IBSS/mesh + * fixed SIGNAL_POLL in IBSS and mesh cases + * added an option to abort an ongoing scan (used to speed up connection + and can also be done with the new ABORT_SCAN command) + * TLS client + - do not verify CA certificates when ca_cert is not specified + - support validating server certificate hash + - support SHA384 and SHA512 hashes + - add signature_algorithms extension into ClientHello + - support TLS v1.2 signature algorithm with SHA384 and SHA512 + - support server certificate probing + - allow specific TLS versions to be disabled with phase2 parameter + - support extKeyUsage + - support PKCS #5 v2.0 PBES2 + - support PKCS #5 with PKCS #12 style key decryption + - minimal support for PKCS #12 + - support OCSP stapling (including ocsp_multi) + * OpenSSL + - support OpenSSL 1.1 API changes + - drop support for OpenSSL 0.9.8 + - drop support for OpenSSL 1.0.0 + * added support for multiple schedule scan plans (sched_scan_plans) + * added support for external server certificate chain validation + (tls_ext_cert_check=1 in the network profile phase1 parameter) + * made phase2 parser more strict about correct use of auth= and + autheap= values + * improved GAS offchannel operations with comeback request + * added SIGNAL_MONITOR command to request signal strength monitoring + events + * added command for retrieving HS 2.0 icons with in-memory storage + (REQ_HS20_ICON, GET_HS20_ICON, DEL_HS20_ICON commands and + RX-HS20-ICON event) + * enabled ACS support for AP mode operations with wpa_supplicant + * EAP-PEAP: fixed interoperability issue with Windows 2012r2 server + ("Invalid Compound_MAC in cryptobinding TLV") + * EAP-TTLS: fixed success after fragmented final Phase 2 message + * VHT: added interoperability workaround for 80+80 and 160 MHz channels + * WNM: workaround for broken AP operating class behavior + * added kqueue(2) support for eloop (CONFIG_ELOOP_KQUEUE) + * nl80211: + - add support for full station state operations + - do not add NL80211_ATTR_SMPS_MODE attribute if HT is disabled + - add NL80211_ATTR_PREV_BSSID with Connect command + - fix IEEE 802.1X/WEP EAP reauthentication and rekeying to use + unencrypted EAPOL frames + * added initial MBO support; number of extensions to WNM BSS Transition + Management + * added support for PBSS/PCP and P2P on 60 GHz + * Interworking: add credential realm to EAP-TLS identity + * fixed EAPOL-Key Request Secure bit to be 1 if PTK is set + * HS 2.0: add support for configuring frame filters + * added POLL_STA command to check connectivity in AP mode + * added initial functionality for location related operations + * started to ignore pmf=1/2 parameter for non-RSN networks + * added wps_disabled=1 network profile parameter to allow AP mode to + be started without enabling WPS + * wpa_cli: added action script support for AP-ENABLED and AP-DISABLED + events + * improved Public Action frame addressing + - add gas_address3 configuration parameter to control Address 3 + behavior + * number of small fixes + +2015-09-27 - v2.5 + * fixed P2P validation of SSID element length before copying it + [http://w1.fi/security/2015-1/] (CVE-2015-1863) + * fixed WPS UPnP vulnerability with HTTP chunked transfer encoding + [http://w1.fi/security/2015-2/] (CVE-2015-4141) + * fixed WMM Action frame parser (AP mode) + [http://w1.fi/security/2015-3/] (CVE-2015-4142) + * fixed EAP-pwd peer missing payload length validation + [http://w1.fi/security/2015-4/] + (CVE-2015-4143, CVE-2015-4144, CVE-2015-4145, CVE-2015-4146) + * fixed validation of WPS and P2P NFC NDEF record payload length + [http://w1.fi/security/2015-5/] + * nl80211: + - added VHT configuration for IBSS + - fixed vendor command handling to check OUI properly + - allow driver-based roaming to change ESS + * added AVG_BEACON_RSSI to SIGNAL_POLL output + * wpa_cli: added tab completion for number of commands + * removed unmaintained and not yet completed SChannel/CryptoAPI support + * modified Extended Capabilities element use in Probe Request frames to + include all cases if any of the values are non-zero + * added support for dynamically creating/removing a virtual interface + with interface_add/interface_remove + * added support for hashed password (NtHash) in EAP-pwd peer + * added support for memory-only PSK/passphrase (mem_only_psk=1 and + CTRL-REQ/RSP-PSK_PASSPHRASE) + * P2P + - optimize scan frequencies list when re-joining a persistent group + - fixed number of sequences with nl80211 P2P Device interface + - added operating class 125 for P2P use cases (this allows 5 GHz + channels 161 and 169 to be used if they are enabled in the current + regulatory domain) + - number of fixes to P2PS functionality + - do not allow 40 MHz co-ex PRI/SEC switch to force MCC + - extended support for preferred channel listing + * D-Bus: + - fixed WPS property of fi.w1.wpa_supplicant1.BSS interface + - fixed PresenceRequest to use group interface + - added new signals: FindStopped, WPS pbc-overlap, + GroupFormationFailure, WPS timeout, InvitationReceived + - added new methods: WPS Cancel, P2P Cancel, Reconnect, RemoveClient + - added manufacturer info + * added EAP-EKE peer support for deriving Session-Id + * added wps_priority configuration parameter to set the default priority + for all network profiles added by WPS + * added support to request a scan with specific SSIDs with the SCAN + command (optional "ssid " arguments) + * removed support for WEP40/WEP104 as a group cipher with WPA/WPA2 + * fixed SAE group selection in an error case + * modified SAE routines to be more robust and PWE generation to be + stronger against timing attacks + * added support for Brainpool Elliptic Curves with SAE + * added support for CCMP-256 and GCMP-256 as group ciphers with FT + * fixed BSS selection based on estimated throughput + * added option to disable TLSv1.0 with OpenSSL + (phase1="tls_disable_tlsv1_0=1") + * added Fast Session Transfer (FST) module + * fixed OpenSSL PKCS#12 extra certificate handling + * fixed key derivation for Suite B 192-bit AKM (this breaks + compatibility with the earlier version) + * added RSN IE to Mesh Peering Open/Confirm frames + * number of small fixes + +2015-03-15 - v2.4 + * allow OpenSSL cipher configuration to be set for internal EAP server + (openssl_ciphers parameter) + * fixed number of small issues based on hwsim test case failures and + static analyzer reports + * P2P: + - add new=<0/1> flag to P2P-DEVICE-FOUND events + - add passive channels in invitation response from P2P Client + - enable nl80211 P2P_DEVICE support by default + - fix regresssion in disallow_freq preventing search on social + channels + - fix regressions in P2P SD query processing + - try to re-invite with social operating channel if no common channels + in invitation + - allow cross connection on parent interface (this fixes number of + use cases with nl80211) + - add support for P2P services (P2PS) + - add p2p_go_ctwindow configuration parameter to allow GO CTWindow to + be configured + * increase postponing of EAPOL-Start by one second with AP/GO that + supports WPS 2.0 (this makes it less likely to trigger extra roundtrip + of identity frames) + * add support for PMKSA caching with SAE + * add support for control mesh BSS (IEEE 802.11s) operations + * fixed number of issues with D-Bus P2P commands + * fixed regression in ap_scan=2 special case for WPS + * fixed macsec_validate configuration + * add a workaround for incorrectly behaving APs that try to use + EAPOL-Key descriptor version 3 when the station supports PMF even if + PMF is not enabled on the AP + * allow TLS v1.1 and v1.2 to be negotiated by default; previous behavior + of disabling these can be configured to work around issues with broken + servers with phase1="tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1" + * add support for Suite B (128-bit and 192-bit level) key management and + cipher suites + * add WMM-AC support (WMM_AC_ADDTS/WMM_AC_DELTS) + * improved BSS Transition Management processing + * add support for neighbor report + * add support for link measurement + * fixed expiration of BSS entry with all-zeros BSSID + * add optional LAST_ID=x argument to LIST_NETWORK to allow all + configured networks to be listed even with huge number of network + profiles + * add support for EAP Re-Authentication Protocol (ERP) + * fixed EAP-IKEv2 fragmentation reassembly + * improved PKCS#11 configuration for OpenSSL + * set stdout to be line-buffered + * add TDLS channel switch configuration + * add support for MAC address randomization in scans with nl80211 + * enable HT for IBSS if supported by the driver + * add BSSID black and white lists (bssid_blacklist, bssid_whitelist) + * add support for domain_suffix_match with GnuTLS + * add OCSP stapling client support with GnuTLS + * include peer certificate in EAP events even without a separate probe + operation; old behavior can be restored with cert_in_cb=0 + * add peer ceritficate alt subject name to EAP events + (CTRL-EVENT-EAP-PEER-ALT) + * add domain_match network profile parameter (similar to + domain_suffix_match, but full match is required) + * enable AP/GO mode HT Tx STBC automatically based on driver support + * add ANQP-QUERY-DONE event to provide information on ANQP parsing + status + * allow passive scanning to be forced with passive_scan=1 + * add a workaround for Linux packet socket behavior when interface is in + bridge + * increase 5 GHz band preference in BSS selection (estimate SNR, if info + not available from driver; estimate maximum throughput based on common + HT/VHT/specific TX rate support) + * add INTERWORKING_ADD_NETWORK ctrl_iface command; this can be used to + implement Interworking network selection behavior in upper layers + software components + * add optional reassoc_same_bss_optim=1 (disabled by default) + optimization to avoid unnecessary Authentication frame exchange + * extend TDLS frame padding workaround to cover all packets + * allow wpa_supplicant to recover nl80211 functionality if the cfg80211 + module gets removed and reloaded without restarting wpa_supplicant + * allow hostapd DFS implementation to be used in wpa_supplicant AP mode + +2014-10-09 - v2.3 + * fixed number of minor issues identified in static analyzer warnings + * fixed wfd_dev_info to be more careful and not read beyond the buffer + when parsing invalid information for P2P-DEVICE-FOUND + * extended P2P and GAS query operations to support drivers that have + maximum remain-on-channel time below 1000 ms (500 ms is the current + minimum supported value) + * added p2p_search_delay parameter to make the default p2p_find delay + configurable + * improved P2P operating channel selection for various multi-channel + concurrency cases + * fixed some TDLS failure cases to clean up driver state + * fixed dynamic interface addition cases with nl80211 to avoid adding + ifindex values to incorrect interface to skip foreign interface events + properly + * added TDLS workaround for some APs that may add extra data to the + end of a short frame + * fixed EAP-AKA' message parser with multiple AT_KDF attributes + * added configuration option (p2p_passphrase_len) to allow longer + passphrases to be generated for P2P groups + * fixed IBSS channel configuration in some corner cases + * improved HT/VHT/QoS parameter setup for TDLS + * modified D-Bus interface for P2P peers/groups + * started to use constant time comparison for various password and hash + values to reduce possibility of any externally measurable timing + differences + * extended explicit clearing of freed memory and expired keys to avoid + keeping private data in memory longer than necessary + * added optional scan_id parameter to the SCAN command to allow manual + scan requests for active scans for specific configured SSIDs + * fixed CTRL-EVENT-REGDOM-CHANGE event init parameter value + * added option to set Hotspot 2.0 Rel 2 update_identifier in network + configuration to support external configuration + * modified Android PNO functionality to send Probe Request frames only + for hidden SSIDs (based on scan_ssid=1) + * added generic mechanism for adding vendor elements into frames at + runtime (VENDOR_ELEM_ADD, VENDOR_ELEM_GET, VENDOR_ELEM_REMOVE) + * added fields to show unrecognized vendor elements in P2P_PEER + * removed EAP-TTLS/MSCHAPv2 interoperability workaround so that + MS-CHAP2-Success is required to be present regardless of + eap_workaround configuration + * modified EAP fast session resumption to allow results to be used only + with the same network block that generated them + * extended freq_list configuration to apply for sched_scan as well as + normal scan + * modified WPS to merge mixed-WPA/WPA2 credentials from a single session + * fixed nl80211/RTM_DELLINK processing when a P2P GO interface is + removed from a bridge + * fixed number of small P2P issues to make negotiations more robust in + corner cases + * added experimental support for using temporary, random local MAC + address (mac_addr and preassoc_mac_addr parameters); this is disabled + by default (i.e., previous behavior of using permanent address is + maintained if configuration is not changed) + * added D-Bus interface for setting/clearing WFD IEs + * fixed TDLS AID configuration for VHT + * modified -m configuration file to be used only for the P2P + non-netdev management device and do not load this for the default + station interface or load the station interface configuration for + the P2P management interface + * fixed external MAC address changes while wpa_supplicant is running + * started to enable HT (if supported by the driver) for IBSS + * fixed wpa_cli action script execution to use more robust mechanism + (CVE-2014-3686) + +2014-06-04 - v2.2 + * added DFS indicator to get_capability freq + * added/fixed nl80211 functionality + - BSSID/frequency hint for driver-based BSS selection + - fix tearing down WDS STA interfaces + - support vendor specific driver command + (VENDOR []) + - GO interface teardown optimization + - allow beacon interval to be configured for IBSS + - add SHA256-based AKM suites to CONNECT/ASSOCIATE commands + * removed unused NFC_RX_HANDOVER_REQ and NFC_RX_HANDOVER_SEL control + interface commands (the more generic NFC_REPORT_HANDOVER is now used) + * fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding; + this fixes password with include UTF-8 characters that use + three-byte encoding EAP methods that use NtPasswordHash + * fixed couple of sequences where radio work items could get stuck, + e.g., when rfkill blocking happens during scanning or when + scan-for-auth workaround is used + * P2P enhancements/fixes + - enable enable U-APSD on GO automatically if the driver indicates + support for this + - fixed some service discovery cases with broadcast queries not being + sent to all stations + - fixed Probe Request frame triggering invitation to trigger only a + single invitation instance even if multiple Probe Request frames are + received + - fixed a potential NULL pointer dereference crash when processing an + invalid Invitation Request frame + - add optional configuration file for the P2P_DEVICE parameters + - optimize scan for GO during persistent group invocation + - fix possible segmentation fault when PBC overlap is detected while + using a separate P2P group interface + - improve GO Negotiation robustness by allowing GO Negotiation + Confirmation to be retransmitted + - do use freed memory on device found event when P2P NFC + * added phase1 network parameter options for disabling TLS v1.1 and v1.2 + to allow workarounds with misbehaving AAA servers + (tls_disable_tlsv1_1=1 and tls_disable_tlsv1_2=1) + * added support for OCSP stapling to validate AAA server certificate + during TLS exchange + * Interworking/Hotspot 2.0 enhancements + - prefer the last added network in Interworking connection to make the + behavior more consistent with likely user expectation + - roaming partner configuration (roaming_partner within a cred block) + - support Hotspot 2.0 Release 2 + * "hs20_anqp_get 8" to request OSU Providers list + * "hs20_icon_request " to request icon files + * "fetch_osu" and "cancel_osu_fetch" to start/stop full OSU provider + search (all suitable APs in scan results) + * OSEN network for online signup connection + * min_{dl,ul}_bandwidth_{home,roaming} cred parameters + * max_bss_load cred parameter + * req_conn_capab cred parameter + * sp_priority cred parameter + * ocsp cred parameter + * slow down automatic connection attempts on EAP failure to meet + required behavior (no more than 10 retries within a 10-minute + interval) + * sample implementation of online signup client (both SPP and + OMA-DM protocols) (hs20/client/*) + - fixed GAS indication for additional comeback delay with status + code 95 + - extend ANQP_GET to accept Hotspot 2.0 subtypes + ANQP_GET [,]... + [,hs20:][...,hs20:] + - add control interface events CRED-ADDED , + CRED-MODIFIED , CRED-REMOVED + - add "GET_CRED " command + - enable FT for the connection automatically if the AP advertises + support for this + - fix a case where auto_interworking=1 could end up stopping scanning + * fixed TDLS interoperability issues with supported operating class in + some deployed stations + * internal TLS implementation enhancements/fixes + - add SHA256-based cipher suites + - add DHE-RSA cipher suites + - fix X.509 validation of PKCS#1 signature to check for extra data + * fixed PTK derivation for CCMP-256 and GCMP-256 + * added "reattach" command for fast reassociate-back-to-same-BSS + * allow PMF to be enabled for AP mode operation with the ieee80211w + parameter + * added "get_capability tdls" command + * added option to set config blobs through control interface with + "SET blob " + * D-Bus interface extensions/fixes + - make p2p_no_group_iface configurable + - declare ServiceDiscoveryRequest method properly + - export peer's device address as a property + - make reassociate command behave like the control interface one, + i.e., to allow connection from disconnected state + * added optional "freq=" parameter to SET pno + * added optional "freq=" parameter to SELECT_NETWORK + * fixed OBSS scan result processing for 20/40 MHz co-ex report + * remove WPS 1.0 only support, i.e., WSC 2.0 support is now enabled + whenever CONFIG_WPS=y is set + * fixed regression in parsing of WNM Sleep Mode exit key data + * fixed potential segmentation fault and memory leaks in WNM neighbor + report processing + * EAP-pwd fixes + - fragmentation of PWD-Confirm-Resp + - fix memory leak when fragmentation is used + - fix possible segmentation fault on EAP method deinit if an invalid + group is negotiated + * added MACsec/IEEE Std 802.1X-2010 PAE implementation (currently + available only with the macsec_qca driver wrapper) + * fixed EAP-SIM counter-too-small message + * added 'dup_network ' command; this can be used to + clone the psk field without having toextract it from wpa_supplicant + * fixed GSM authentication on USIM + * added support for using epoll in eloop (CONFIG_ELOOP_EPOLL=y) + * fixed some concurrent virtual interface cases with dedicated P2P + management interface to not catch events from removed interface (this + could result in the management interface getting disabled) + * fixed a memory leak in SAE random number generation + * fixed off-by-one bounds checking in printf_encode() + - this could result in some control interface ATTACH command cases + terminating wpa_supplicant + * fixed EAPOL-Key exchange when GCMP is used with SHA256-based AKM + * various bug fixes + +2014-02-04 - v2.1 + * added support for simultaneous authentication of equals (SAE) for + stronger password-based authentication with WPA2-Personal + * improved P2P negotiation and group formation robustness + - avoid unnecessary Dialog Token value changes during retries + - avoid more concurrent scanning cases during full group formation + sequence + - do not use potentially obsolete scan result data from driver + cache for peer discovery/updates + - avoid undesired re-starting of GO negotiation based on Probe + Request frames + - increase GO Negotiation and Invitation timeouts to address busy + environments and peers that take long time to react to messages, + e.g., due to power saving + - P2P Device interface type + * improved P2P channel selection (use more peer information and allow + more local options) + * added support for optional per-device PSK assignment by P2P GO + (wpa_cli p2p_set per_sta_psk <0/1>) + * added P2P_REMOVE_CLIENT for removing a client from P2P groups + (including persistent groups); this can be used to securely remove + a client from a group if per-device PSKs are used + * added more configuration flexibility for allowed P2P GO/client + channels (p2p_no_go_freq list and p2p_add_cli_chan=0/1) + * added nl80211 functionality + - VHT configuration for nl80211 + - MFP (IEEE 802.11w) information for nl80211 command API + - support split wiphy dump + - FT (IEEE 802.11r) with driver-based SME + - use advertised number of supported concurrent channels + - QoS Mapping configuration + * improved TDLS negotiation robustness + * added more TDLS peer parameters to be configured to the driver + * optimized connection time by allowing recently received scan results + to be used instead of having to run through a new scan + * fixed ctrl_iface BSS command iteration with RANGE argument and no + exact matches; also fixed argument parsing for some cases with + multiple arguments + * added 'SCAN TYPE=ONLY' ctrl_iface command to request manual scan + without executing roaming/network re-selection on scan results + * added Session-Id derivation for EAP peer methods + * added fully automated regression testing with mac80211_hwsim + * changed configuration parser to reject invalid integer values + * allow AP/Enrollee to be specified with BSSID instead of UUID for + WPS ER operations + * disable network block temporarily on repeated connection failures + * changed the default driver interface from wext to nl80211 if both are + included in the build + * remove duplicate networks if WPS provisioning is run multiple times + * remove duplicate networks when Interworking network selection uses the + same network + * added global freq_list configuration to allow scan frequencies to be + limited for all cases instead of just for a specific network block + * added support for BSS Transition Management + * added option to use "IFNAME= " prefix to use the global + control interface connection to perform per-interface commands; + similarly, allow global control interface to be used as a monitor + interface to receive events from all interfaces + * fixed OKC-based PMKSA cache entry clearing + * fixed TKIP group key configuration with FT + * added support for using OCSP stapling to validate server certificate + (ocsp=1 as optional and ocsp=2 as mandatory) + * added EAP-EKE peer + * added peer restart detection for IBSS RSN + * added domain_suffix_match (and domain_suffix_match2 for Phase 2 + EAP-TLS) to specify additional constraint for the server certificate + domain name + * added support for external SIM/USIM processing in EAP-SIM, EAP-AKA, + and EAP-AKA' (CTRL-REQ-SIM and CTRL-RSP-SIM commands over control + interface) + * added global bgscan configuration option as a default for all network + blocks that do not specify their own bgscan parameters + * added D-Bus methods for TDLS + * added more control to scan requests + - "SCAN freq=" can be used to specify which channels are + scanned (comma-separated frequency ranges in MHz) + - "SCAN passive=1" can be used to request a passive scan (no Probe + Request frames are sent) + - "SCAN use_id" can be used to request a scan id to be returned and + included in event messages related to this specific scan operation + - "SCAN only_new=1" can be used to request the driver/cfg80211 to + report only BSS entries that have been updated during this scan + round + - these optional arguments to the SCAN command can be combined with + each other + * modified behavior on externally triggered scans + - avoid concurrent operations requiring full control of the radio when + an externally triggered scan is detected + - do not use results for internal roaming decision + * added a new cred block parameter 'temporary' to allow credential + blocks to be stored separately even if wpa_supplicant configuration + file is used to maintain other network information + * added "radio work" framework to schedule exclusive radio operations + for off-channel functionality + - reduce issues with concurrent operations that try to control which + channel is used + - allow external programs to request exclusive radio control in a way + that avoids conflicts with wpa_supplicant + * added support for using Protected Dual of Public Action frames for + GAS/ANQP exchanges when associated with PMF + * added support for WPS+NFC updates and P2P+NFC + - improved protocol for WPS + - P2P group formation/join based on NFC connection handover + - new IPv4 address assignment for P2P groups (ip_addr_* configuration + parameters on the GO) to replace DHCP + - option to fetch and report alternative carrier records for external + NFC operations + * various bug fixes + +2013-01-12 - v2.0 + * removed Qt3-based wpa_gui (obsoleted by wpa_qui-qt4) + * removed unmaintained driver wrappers broadcom, iphone, osx, ralink, + hostap, madwifi (hostap and madwifi remain available for hostapd; + their wpa_supplicant functionality is obsoleted by wext) + * improved debug logging (human readable event names, interface name + included in more entries) + * changed AP mode behavior to enable WPS only for open and + WPA/WPA2-Personal configuration + * improved P2P concurrency operations + - better coordination of concurrent scan and P2P search operations + - avoid concurrent remain-on-channel operation requests by canceling + previous operations prior to starting a new one + - reject operations that would require multi-channel concurrency if + the driver does not support it + - add parameter to select whether STA or P2P connection is preferred + if the driver cannot support both at the same time + - allow driver to indicate channel changes + - added optional delay= parameter for + p2p_find to avoid taking all radio resources + - use 500 ms p2p_find search delay by default during concurrent + operations + - allow all channels in GO Negotiation if the driver supports + multi-channel concurrency + * added number of small changes to make it easier for static analyzers + to understand the implementation + * fixed number of small bugs (see git logs for more details) + * nl80211: number of updates to use new cfg80211/nl80211 functionality + - replace monitor interface with nl80211 commands for AP mode + - additional information for driver-based AP SME + - STA entry authorization in RSN IBSS + * EAP-pwd: + - fixed KDF for group 21 and zero-padding + - added support for fragmentation + - increased maximum number of hunting-and-pecking iterations + * avoid excessive Probe Response retries for broadcast Probe Request + frames (only with drivers using wpa_supplicant AP mode SME/MLME) + * added "GET country" ctrl_iface command + * do not save an invalid network block in wpa_supplicant.conf to avoid + problems reading the file on next start + * send STA connected/disconnected ctrl_iface events to both the P2P + group and parent interfaces + * added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y) + * added "SET pno <1/0>" ctrl_iface command to start/stop preferred + network offload with sched_scan driver command + * merged in number of changes from Android repository for P2P, nl80211, + and build parameters + * changed P2P GO mode configuration to use driver capabilities to + automatically enable HT operations when supported + * added "wpa_cli status wps" command to fetch WPA2-Personal passhrase + for WPS use cases in AP mode + * EAP-AKA: keep pseudonym identity across EAP exchanges to match EAP-SIM + behavior + * improved reassociation behavior in cases where association is rejected + or when an AP disconnects us to handle common load balancing + mechanisms + - try to avoid extra scans when the needed information is available + * added optional "join" argument for p2p_prov_disc ctrl_iface command + * added group ifname to P2P-PROV-DISC-* events + * added P2P Device Address to AP-STA-DISCONNECTED event and use + p2p_dev_addr parameter name with AP-STA-CONNECTED + * added workarounds for WPS PBC overlap detection for some P2P use cases + where deployed stations work incorrectly + * optimize WPS connection speed by disconnecting prior to WPS scan and + by using single channel scans when AP channel is known + * PCSC and SIM/USIM improvements: + - accept 0x67 (Wrong length) as a response to READ RECORD to fix + issues with some USIM cards + - try to read MNC length from SIM/USIM + - build realm according to 3GPP TS 23.003 with identity from the SIM + - allow T1 protocol to be enabled + * added more WPS and P2P information available through D-Bus + * improve P2P negotiation robustness + - extra waits to get ACK frames through + - longer timeouts for cases where deployed devices have been + identified have issues meeting the specification requirements + - more retries for some P2P frames + - handle race conditions in GO Negotiation start by both devices + - ignore unexpected GO Negotiation Response frame + * added support for libnl 3.2 and newer + * added P2P persistent group info to P2P_PEER data + * maintain a list of P2P Clients for persistent group on GO + * AP: increased initial group key handshake retransmit timeout to 500 ms + * added optional dev_id parameter for p2p_find + * added P2P-FIND-STOPPED ctrl_iface event + * fixed issues in WPA/RSN element validation when roaming with ap_scan=1 + and driver-based BSS selection + * do not expire P2P peer entries while connected with the peer in a + group + * fixed WSC element inclusion in cases where P2P is disabled + * AP: added a WPS workaround for mixed mode AP Settings with Windows 7 + * EAP-SIM: fixed AT_COUNTER_TOO_SMALL use + * EAP-SIM/AKA: append realm to pseudonym identity + * EAP-SIM/AKA: store pseudonym identity in network configuration to + allow it to persist over multiple EAP sessions and wpa_supplicant + restarts + * EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this + breaks interoperability with older versions + * added support for WFA Hotspot 2.0 + - GAS/ANQP to fetch network information + - credential configuration and automatic network selections based on + credential match with ANQP information + * limited PMKSA cache entries to be used only with the network context + that was used to create them + * improved PMKSA cache expiration to avoid unnecessary disconnections + * adjusted bgscan_simple fast-scan backoff to avoid too frequent + background scans + * removed ctrl_iface event on P2P PD Response in join-group case + * added option to fetch BSS table entry based on P2P Device Address + ("BSS p2p_dev_addr=") + * added BSS entry age to ctrl_iface BSS command output + * added optional MASK=0xH option for ctrl_iface BSS command to select + which fields are included in the response + * added optional RANGE=ALL|N1-N2 option for ctrl_iface BSS command to + fetch information about several BSSes in one call + * simplified licensing terms by selecting the BSD license as the only + alternative + * added "P2P_SET disallow_freq " ctrl_iface command to + disable channels from P2P use + * added p2p_pref_chan configuration parameter to allow preferred P2P + channels to be specified + * added support for advertising immediate availability of a WPS + credential for P2P use cases + * optimized scan operations for P2P use cases (use single channel scan + for a specific SSID when possible) + * EAP-TTLS: fixed peer challenge generation for MSCHAPv2 + * SME: do not use reassociation after explicit disconnection request + (local or a notification from an AP) + * added support for sending debug info to Linux tracing (-T on command + line) + * added support for using Deauthentication reason code 3 as an + indication of P2P group termination + * added wps_vendor_ext_m1 configuration parameter to allow vendor + specific attributes to be added to WPS M1 + * started using separate TLS library context for tunneled TLS + (EAP-PEAP/TLS, EAP-TTLS/TLS, EAP-FAST/TLS) to support different CA + certificate configuration between Phase 1 and Phase 2 + * added optional "auto" parameter for p2p_connect to request automatic + GO Negotiation vs. join-a-group selection + * added disabled_scan_offload parameter to disable automatic scan + offloading (sched_scan) + * added optional persistent= parameter for p2p_connect to + allow forcing of a specific SSID/passphrase for GO Negotiation + * added support for OBSS scan requests and 20/40 BSS coexistence reports + * reject PD Request for unknown group + * removed scripts and notes related to Windows binary releases (which + have not been used starting from 1.x) + * added initial support for WNM operations + - Keep-alive based on BSS max idle period + - WNM-Sleep Mode + - minimal BSS Transition Management processing + * added autoscan module to control scanning behavior while not connected + - autoscan_periodic and autoscan_exponential modules + * added new WPS NFC ctrl_iface mechanism + - added initial support NFC connection handover + - removed obsoleted WPS_OOB command (including support for deprecated + UFD config_method) + * added optional framework for external password storage ("ext:") + * wpa_cli: added optional support for controlling wpa_supplicant + remotely over UDP (CONFIG_CTRL_IFACE=udp-remote) for testing purposes + * wpa_cli: extended tab completion to more commands + * changed SSID output to use printf-escaped strings instead of masking + of non-ASCII characters + - SSID can now be configured in the same format: ssid=P"abc\x00test" + * removed default ACM=1 from AC_VO and AC_VI + * added optional "ht40" argument for P2P ctrl_iface commands to allow + 40 MHz channels to be requested on the 5 GHz band + * added optional parameters for p2p_invite command to specify channel + when reinvoking a persistent group as the GO + * improved FIPS mode builds with OpenSSL + - "make fips" with CONFIG_FIPS=y to build wpa_supplicant with the + OpenSSL FIPS object module + - replace low level OpenSSL AES API calls to use EVP + - use OpenSSL keying material exporter when possible + - do not export TLS keys in FIPS mode + - remove MD5 from CONFIG_FIPS=y builds + - use OpenSSL function for PKBDF2 passphrase-to-PSK + - use OpenSSL HMAC implementation + - mix RAND_bytes() output into random_get_bytes() to force OpenSSL + DRBG to be used in FIPS mode + - use OpenSSL CMAC implementation + * added mechanism to disable TLS Session Ticket extension + - a workaround for servers that do not support TLS extensions that + was enabled by default in recent OpenSSL versions + - tls_disable_session_ticket=1 + - automatically disable TLS Session Ticket extension by default when + using EAP-TLS/PEAP/TTLS (i.e., only use it with EAP-FAST) + * changed VENDOR-TEST EAP method to use proper private enterprise number + (this will not interoperate with older versions) + * disable network block temporarily on authentication failures + * improved WPS AP selection during WPS PIN iteration + * added support for configuring GCMP cipher for IEEE 802.11ad + * added support for Wi-Fi Display extensions + - WFD_SUBELEMENT_SET ctrl_iface command to configure WFD subelements + - SET wifi_display <0/1> to disable/enable WFD support + - WFD service discovery + - an external program is needed to manage the audio/video streaming + and codecs + * optimized scan result use for network selection + - use the internal BSS table instead of raw scan results + - allow unnecessary scans to be skipped if fresh information is + available (e.g., after GAS/ANQP round for Interworking) + * added support for 256-bit AES with internal TLS implementation + * allow peer to propose channel in P2P invitation process for a + persistent group + * added disallow_aps parameter to allow BSSIDs/SSIDs to be disallowed + from network selection + * re-enable the networks disabled during WPS operations + * allow P2P functionality to be disabled per interface (p2p_disabled=1) + * added secondary device types into P2P_PEER output + * added an option to disable use of a separate P2P group interface + (p2p_no_group_iface=1) + * fixed P2P Bonjour SD to match entries with both compressed and not + compressed domain name format and support multiple Bonjour PTR matches + for the same key + * use deauthentication instead of disassociation for all disconnection + operations; this removes the now unused disassociate() wpa_driver_ops + callback + * optimized PSK generation on P2P GO by caching results to avoid + multiple PBKDF2 operations + * added okc=1 global configuration parameter to allow OKC to be enabled + by default for all network blocks + * added a workaround for WPS PBC session overlap detection to avoid + interop issues with deployed station implementations that do not + remove active PBC indication from Probe Request frames properly + * added basic support for 60 GHz band + * extend EAPOL frames processing workaround for roaming cases + (postpone processing of unexpected EAPOL frame until association + event to handle reordered events) + +2012-05-10 - v1.0 + * bsd: Add support for setting HT values in IFM_MMASK. + * Delay STA entry removal until Deauth/Disassoc TX status in AP mode. + This allows the driver to use PS buffering of Deauthentication and + Disassociation frames when the STA is in power save sleep. Only + available with drivers that provide TX status events for Deauth/ + Disassoc frames (nl80211). + * Drop oldest unknown BSS table entries first. This makes it less + likely to hit connection issues in environments with huge number + of visible APs. + * Add systemd support. + * Add support for setting the syslog facility from the config file + at build time. + * atheros: Add support for IEEE 802.11w configuration. + * AP mode: Allow enable HT20 if driver supports it, by setting the + config parameter ieee80211n. + * Allow AP mode to disconnect STAs based on low ACK condition (when + the data connection is not working properly, e.g., due to the STA + going outside the range of the AP). Disabled by default, enable by + config option disassoc_low_ack. + * nl80211: + - Support GTK rekey offload. + - Support PMKSA candidate events. This adds support for RSN + pre-authentication with nl80211 interface and drivers that handle + roaming internally. + * dbus: + - Add a DBus signal for EAP SM requests, emitted on the Interface + object. + - Export max scan ssids supported by the driver as MaxScanSSID. + - Add signal Certification for information about server certification. + - Add BSSExpireAge and BSSExpireCount interface properties and + support set/get, which allows for setting BSS cache expiration age + and expiration scan count. + - Add ConfigFile to AddInterface properties. + - Add Interface.Country property and support to get/set the value. + - Add DBus property CurrentAuthMode. + - P2P DBus API added. + - Emit property changed events (for property BSSs) when adding/ + removing BSSs. + - Treat '' in SSIDs of Interface.Scan as a request for broadcast + scan, instead of ignoring it. + - Add DBus getter/setter for FastReauth. + - Raise PropertiesChanged on org.freedesktop.DBus.Properties. + * wpa_cli: + - Send AP-STA-DISCONNECTED event when an AP disconnects a station + due to inactivity. + - Make second argument to set command optional. This can be used to + indicate a zero length value. + - Add signal_poll command. + - Add bss_expire_age and bss_expire_count commands to set/get BSS + cache expiration age and expiration scan count. + - Add ability to set scan interval (the time in seconds wpa_s waits + before requesting a new scan after failing to find a suitable + network in scan results) using scan_interval command. + - Add event CTRL-EVENT-ASSOC-REJECT for association rejected. + - Add command get version, that returns wpa_supplicant version string. + - Add command sta_autoconnect for disabling automatic reconnection + on receiving disconnection event. + - Setting bssid parameter to an empty string "" or any can now be + used to clear the bssid_set flag in a network block, i.e., to remove + bssid filtering. + - Add tdls_testing command to add a special testing feature for + changing TDLS behavior. Build param CONFIG_TDLS_TESTING must be + enabled as well. + - For interworking, add wpa_cli commands interworking_select, + interworking_connect, anqp_get, fetch_anqp, and stop_fetch_anqp. + - Many P2P commands were added. See README-P2P. + - Many WPS/WPS ER commands - see WPS/WPS ER sections for details. + - Allow set command to change global config parameters. + - Add log_level command, which can be used to display the current + debugging level and to change the log level during run time. + - Add note command, which can be used to insert notes to the debug + log. + - Add internal line edit implementation. CONFIG_WPA_CLI_EDIT=y + can now be used to build wpa_cli with internal implementation of + line editing and history support. This can be used as a replacement + for CONFIG_READLINE=y. + * AP mode: Add max_num_sta config option, which can be used to limit + the number of stations allowed to connect to the AP. + * Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad + config file. + * wext: Increase scan timeout from 5 to 10 seconds. + * Add blacklist command, allowing an external program to + manage the BSS blacklist and display its current contents. + * WPS: + - Add wpa_cli wps_pin get command for generating random PINs. This can + be used in a UI to generate a PIN without starting WPS (or P2P) + operation. + - Set RF bands based on driver capabilities, instead of hardcoding + them. + - Add mechanism for indicating non-standard WPS errors. + - Add CONFIG_WPS_REG_DISABLE_OPEN=y option to disable open networks + by default. + - Add wps_ap_pin cli command for wpa_supplicant AP mode. + - Add wps_check_pin cli command for processing PIN from user input. + UIs can use this command to process a PIN entered by a user and to + validate the checksum digit (if present). + - Cancel WPS operation on PBC session overlap detection. + - New wps_cancel command in wpa_cli will cancel a pending WPS + operation. + - wpa_cli action: Add WPS_EVENT_SUCCESS and WPS_EVENT_FAIL handlers. + - Trigger WPS config update on Manufacturer, Model Name, Model + Number, and Serial Number changes. + - Fragment size is now configurable for EAP-WSC peer. Use + wpa_cli set wps_fragment_size . + - Disable AP PIN after 10 consecutive failures. Slow down attacks on + failures up to 10. + - Allow AP to start in Enrollee mode without AP PIN for probing, to + be compatible with Windows 7. + - Add Config Error into WPS-FAIL events to provide more info to the + user on how to resolve the issue. + - Label and Display config methods are not allowed to be enabled + at the same time, since it is unclear which PIN to use if both + methods are advertised. + - When controlling multiple interfaces: + - apply WPS commands to all interfaces configured to use WPS + - apply WPS config changes to all interfaces that use WPS + - when an attack is detected on any interface, disable AP PIN on + all interfaces + * WPS ER: + - Add special AP Setup Locked mode to allow read only ER. + ap_setup_locked=2 can now be used to enable a special mode where + WPS ER can learn the current AP settings, but cannot change them. + - Show SetSelectedRegistrar events as ctrl_iface events + - Add wps_er_set_config to enroll a network based on a local + network configuration block instead of having to (re-)learn the + current AP settings with wps_er_learn. + - Allow AP filtering based on IP address, add ctrl_iface event for + learned AP settings, add wps_er_config command to configure an AP. + * WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2) + - Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool + for testing protocol extensibility. + - Add build option CONFIG_WPS_STRICT to allow disabling of WPS + workarounds. + - Add support for AuthorizedMACs attribute. + * TDLS: + - Propagate TDLS related nl80211 capability flags from kernel and + add them as driver capability flags. If the driver doesn't support + capabilities, assume TDLS is supported internally. When TDLS is + explicitly not supported, disable all user facing TDLS operations. + - Allow TDLS to be disabled at runtime (mostly for testing). + Use set tdls_disabled. + - Honor AP TDLS settings that prohibit/allow TDLS. + - Add a special testing feature for changing TDLS behavior. Use + CONFIG_TDLS_TESTING build param to enable. Configure at runtime + with tdls_testing cli command. + - Add support for TDLS 802.11z. + * wlantest: Add a tool wlantest for IEEE802.11 protocol testing. + wlantest can be used to capture frames from a monitor interface + for realtime capturing or from pcap files for offline analysis. + * Interworking: Support added for 802.11u. Enable in .config with + CONFIG_INTERWORKING. See wpa_supplicant.conf for config parameters + for interworking. wpa_cli commands added to support this are + interworking_select, interworking_connect, anqp_get, fetch_anqp, + and stop_fetch_anqp. + * Android: Add build and runtime support for Android wpa_supplicant. + * bgscan learn: Add new bgscan that learns BSS information based on + previous scans, and uses that information to dynamically generate + the list of channels for background scans. + * Add a new debug message level for excessive information. Use + -ddd to enable. + * TLS: Add support for tls_disable_time_checks=1 in client mode. + * Internal TLS: + - Add support for TLS v1.1 (RFC 4346). Enable with build parameter + CONFIG_TLSV11. + - Add domainComponent parser for X.509 names. + * Linux: Add RFKill support by adding an interface state "disabled". + * Reorder some IEs to get closer to IEEE 802.11 standard. Move + WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames. + Move HT IEs to be later in (Re)Assoc Resp. + * Solaris: Add support for wired 802.1X client. + * Wi-Fi Direct support. See README-P2P for more information. + * Many bugfixes. + +2010-04-18 - v0.7.2 + * nl80211: fixed number of issues with roaming + * avoid unnecessary roaming if multiple APs with similar signal + strength are present in scan results + * add TLS client events and server probing to ease design of + automatic detection of EAP parameters + * add option for server certificate matching (SHA256 hash of the + certificate) instead of trusted CA certificate configuration + * bsd: Cleaned up driver wrapper and added various low-level + configuration options + * wpa_gui-qt4: do not show too frequent WPS AP available events as + tray messages + * TNC: fixed issues with fragmentation + * EAP-TNC: add Flags field into fragment acknowledgement (needed to + interoperate with other implementations; may potentially breaks + compatibility with older wpa_supplicant/hostapd versions) + * wpa_cli: added option for using a separate process to receive event + messages to reduce latency in showing these + (CFLAGS += -DCONFIG_WPA_CLI_FORK=y in .config to enable this) + * maximum BSS table size can now be configured (bss_max_count) + * BSSes to be included in the BSS table can be filtered based on + configured SSIDs to save memory (filter_ssids) + * fix number of issues with IEEE 802.11r/FT; this version is not + backwards compatible with old versions + * nl80211: add support for IEEE 802.11r/FT protocol (both over-the-air + and over-the-DS) + * add freq_list network configuration parameter to allow the AP + selection to filter out entries based on the operating channel + * add signal strength change events for bgscan; this allows more + dynamic changes to background scanning interval based on changes in + the signal strength with the current AP; this improves roaming within + ESS quite a bit, e.g., with bgscan="simple:30:-45:300" in the network + configuration block to request background scans less frequently when + signal strength remains good and to automatically trigger background + scans whenever signal strength drops noticeably + (this is currently only available with nl80211) + * add BSSID and reason code (if available) to disconnect event messages + * wpa_gui-qt4: more complete support for translating the GUI with + linguist and add German translation + * fix DH padding with internal crypto code (mainly, for WPS) + * do not trigger initial scan automatically anymore if there are no + enabled networks + +2010-01-16 - v0.7.1 + * cleaned up driver wrapper API (struct wpa_driver_ops); the new API + is not fully backwards compatible, so out-of-tree driver wrappers + will need modifications + * cleaned up various module interfaces + * merge hostapd and wpa_supplicant developers' documentation into a + single document + * nl80211: use explicit deauthentication to clear cfg80211 state to + avoid issues when roaming between APs + * dbus: major design changes in the new D-Bus API + (fi.w1.wpa_supplicant1) + * nl80211: added support for IBSS networks + * added internal debugging mechanism with backtrace support and memory + allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y) + * added WPS ER unsubscription command to more cleanly unregister from + receiving UPnP events when ER is terminated + * cleaned up AP mode operations to avoid need for virtual driver_ops + wrapper + * added BSS table to maintain more complete scan result information + over multiple scans (that may include only partial results) + * wpa_gui-qt4: update Peers dialog information more dynamically while + the dialog is kept open + * fixed PKCS#12 use with OpenSSL 1.0.0 + * driver_wext: Added cfg80211-specific optimization to avoid some + unnecessary scans and to speed up association + +2009-11-21 - v0.7.0 + * increased wpa_cli ping interval to 5 seconds and made this + configurable with a new command line options (-G) + * fixed scan buffer processing with WEXT to handle up to 65535 + byte result buffer (previously, limited to 32768 bytes) + * allow multiple driver wrappers to be specified on command line + (e.g., -Dnl80211,wext); the first one that is able to initialize the + interface will be used + * added support for multiple SSIDs per scan request to optimize + scan_ssid=1 operations in ap_scan=1 mode (i.e., search for hidden + SSIDs); this requires driver support and can currently be used only + with nl80211 + * added support for WPS USBA out-of-band mechanism with USB Flash + Drives (UFD) (CONFIG_WPS_UFD=y) + * driver_ndis: add PAE group address to the multicast address list to + fix wired IEEE 802.1X authentication + * fixed IEEE 802.11r key derivation function to match with the standard + (note: this breaks interoperability with previous version) [Bug 303] + * added better support for drivers that allow separate authentication + and association commands (e.g., mac80211-based Linux drivers with + nl80211; SME in wpa_supplicant); this allows over-the-air FT protocol + to be used (IEEE 802.11r) + * fixed SHA-256 based key derivation function to match with the + standard when using CCMP (for IEEE 802.11r and IEEE 802.11w) + (note: this breaks interoperability with previous version) [Bug 307] + * use shared driver wrapper files with hostapd + * added AP mode functionality (CONFIG_AP=y) with mode=2 in the network + block; this can be used for open and WPA2-Personal networks + (optionally, with WPS); this links in parts of hostapd functionality + into wpa_supplicant + * wpa_gui-qt4: added new Peers dialog to show information about peers + (other devices, including APs and stations, etc. in the neighborhood) + * added support for WPS External Registrar functionality (configure APs + and enroll new devices); can be used with wpa_gui-qt4 Peers dialog + and wpa_cli commands wps_er_start, wps_er_stop, wps_er_pin, + wps_er_pbc, wps_er_learn + (this can also be used with a new 'none' driver wrapper if no + wireless device or IEEE 802.1X on wired is needed) + * driver_nl80211: multiple updates to provide support for new Linux + nl80211/mac80211 functionality + * updated management frame protection to use IEEE Std 802.11w-2009 + * fixed number of small WPS issues and added workarounds to + interoperate with common deployed broken implementations + * added support for NFC out-of-band mechanism with WPS + * driver_ndis: fixed wired IEEE 802.1X authentication with PAE group + address frames + * added preliminary support for IEEE 802.11r RIC processing + * added support for specifying subset of enabled frequencies to scan + (scan_freq option in the network configuration block); this can speed + up scanning process considerably if it is known that only a small + subset of channels is actually used in the network (this is currently + supported only with -Dnl80211) + * added a workaround for race condition between receiving the + association event and the following EAPOL-Key + * added background scan and roaming infrastructure to allow + network-specific optimizations to be used to improve roaming within + an ESS (same SSID) + * added new DBus interface (fi.w1.wpa_supplicant1) + +2009-01-06 - v0.6.7 + * added support for Wi-Fi Protected Setup (WPS) + (wpa_supplicant can now be configured to act as a WPS Enrollee to + enroll credentials for a network using PIN and PBC methods; in + addition, wpa_supplicant can act as a wireless WPS Registrar to + configure an AP); WPS support can be enabled by adding CONFIG_WPS=y + into .config and setting the runtime configuration variables in + wpa_supplicant.conf (see WPS section in the example configuration + file); new wpa_cli commands wps_pin, wps_pbc, and wps_reg are used to + manage WPS negotiation; see README-WPS for more details + * added support for EAP-AKA' (draft-arkko-eap-aka-kdf) + * added support for using driver_test over UDP socket + * fixed PEAPv0 Cryptobinding interoperability issue with Windows Server + 2008 NPS; optional cryptobinding is now enabled (again) by default + * fixed PSK editing in wpa_gui + * changed EAP-GPSK to use the IANA assigned EAP method type 51 + * added a Windows installer that includes WinPcap and all the needed + DLLs; in addition, it set up the registry automatically so that user + will only need start wpa_gui to get prompted to start the wpasvc + servide and add a new interface if needed through wpa_gui dialog + * updated management frame protection to use IEEE 802.11w/D7.0 + +2008-11-23 - v0.6.6 + * added Milenage SIM/USIM emulator for EAP-SIM/EAP-AKA + (can be used to simulate test SIM/USIM card with a known private key; + enable with CONFIG_SIM_SIMULATOR=y/CONFIG_USIM_SIMULATOR=y in .config + and password="Ki:OPc"/password="Ki:OPc:SQN" in network configuration) + * added a new network configuration option, wpa_ptk_rekey, that can be + used to enforce frequent PTK rekeying, e.g., to mitigate some attacks + against TKIP deficiencies + * added an optional mitigation mechanism for certain attacks against + TKIP by delaying Michael MIC error reports by a random amount of time + between 0 and 60 seconds; this can be enabled with a build option + CONFIG_DELAYED_MIC_ERROR_REPORT=y in .config + * fixed EAP-AKA to use RES Length field in AT_RES as length in bits, + not bytes + * updated OpenSSL code for EAP-FAST to use an updated version of the + session ticket overriding API that was included into the upstream + OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is + needed with that version anymore) + * updated userspace MLME instructions to match with the current Linux + mac80211 implementation; please also note that this can only be used + with driver_nl80211.c (the old code from driver_wext.c was removed) + * added support (Linux only) for RoboSwitch chipsets (often found in + consumer grade routers); driver interface 'roboswitch' + * fixed canceling of PMKSA caching when using drivers that generate + RSN IE and refuse to drop PMKIDs that wpa_supplicant does not know + about + +2008-11-01 - v0.6.5 + * added support for SHA-256 as X.509 certificate digest when using the + internal X.509/TLSv1 implementation + * updated management frame protection to use IEEE 802.11w/D6.0 + * added support for using SHA256-based stronger key derivation for WPA2 + (IEEE 802.11w) + * fixed FT (IEEE 802.11r) authentication after a failed association to + use correct FTIE + * added support for configuring Phase 2 (inner/tunneled) authentication + method with wpa_gui-qt4 + +2008-08-10 - v0.6.4 + * added support for EAP Sequences in EAP-FAST Phase 2 + * added support for using TNC with EAP-FAST + * added driver_ps3 for the PS3 Linux wireless driver + * added support for optional cryptobinding with PEAPv0 + * fixed the OpenSSL patches (0.9.8g and 0.9.9) for EAP-FAST to + allow fallback to full handshake if server rejects PAC-Opaque + * added fragmentation support for EAP-TNC + * added support for parsing PKCS #8 formatted private keys into the + internal TLS implementation (both PKCS #1 RSA key and PKCS #8 + encapsulated RSA key can now be used) + * added option of using faster, but larger, routines in the internal + LibTomMath (for internal TLS implementation) to speed up DH and RSA + calculations (CONFIG_INTERNAL_LIBTOMMATH_FAST=y) + * fixed race condition between disassociation event and group key + handshake to avoid getting stuck in incorrect state [Bug 261] + * fixed opportunistic key caching (proactive_key_caching) + +2008-02-22 - v0.6.3 + * removed 'nai' and 'eappsk' network configuration variables that were + previously used for configuring user identity and key for EAP-PSK, + EAP-PAX, EAP-SAKE, and EAP-GPSK. 'identity' field is now used as the + replacement for 'nai' (if old configuration used a separate + 'identity' value, that would now be configured as + 'anonymous_identity'). 'password' field is now used as the + replacement for 'eappsk' (it can also be set using hexstring to + present random binary data) + * removed '-w' command line parameter (wait for interface to be added, + if needed); cleaner way of handling this functionality is to use an + external mechanism (e.g., hotplug scripts) that start wpa_supplicant + when an interface is added + * updated FT support to use the latest draft, IEEE 802.11r/D9.0 + * added ctrl_iface monitor event (CTRL-EVENT-SCAN-RESULTS) for + indicating when new scan results become available + * added new ctrl_iface command, BSS, to allow scan results to be + fetched without hitting the message size limits (this command + can be used to iterate through the scan results one BSS at the time) + * fixed EAP-SIM not to include AT_NONCE_MT and AT_SELECTED_VERSION + attributes in EAP-SIM Start/Response when using fast reauthentication + * fixed EAPOL not to end up in infinite loop when processing dynamic + WEP keys with IEEE 802.1X + * fixed problems in getting NDIS events from WMI on Windows 2000 + +2008-01-01 - v0.6.2 + * added support for Makefile builds to include debug-log-to-a-file + functionality (CONFIG_DEBUG_FILE=y and -f on command line) + * fixed EAP-SIM and EAP-AKA message parser to validate attribute + lengths properly to avoid potential crash caused by invalid messages + * added data structure for storing allocated buffers (struct wpabuf); + this does not affect wpa_supplicant usage, but many of the APIs + changed and various interfaces (e.g., EAP) is not compatible with old + versions + * added support for protecting EAP-AKA/Identity messages with + AT_CHECKCODE (optional feature in RFC 4187) + * added support for protected result indication with AT_RESULT_IND for + EAP-SIM and EAP-AKA (phase1="result_ind=1") + * added driver_wext workaround for race condition between scanning and + association with drivers that take very long time to scan all + channels (e.g., madwifi with dual-band cards); wpa_supplicant is now + using a longer hardcoded timeout for the scan if the driver supports + notifications for scan completion (SIOCGIWSCAN event); this helps, + e.g., in cases where wpa_supplicant and madwifi driver ended up in + loop where the driver did not even try to associate + * stop EAPOL timer tick when no timers are in use in order to reduce + power consumption (no need to wake up the process once per second) + [Bug 237] + * added support for privilege separation (run only minimal part of + wpa_supplicant functionality as root and rest as unprivileged, + non-root process); see 'Privilege separation' in README for details; + this is disabled by default and can be enabled with CONFIG_PRIVSEP=y + in .config + * changed scan results data structure to include all information + elements to make it easier to support new IEs; old get_scan_result() + driver_ops is still supported for backwards compatibility (results + are converted internally to the new format), but all drivers should + start using the new get_scan_results2() to make them more likely to + work with new features + * Qt4 version of wpa_gui (wpa_gui-qt4 subdirectory) is now native Qt4 + application, i.e., it does not require Qt3Support anymore; Windows + binary of wpa_gui.exe is now from this directory and only requires + QtCore4.dll and QtGui4.dll libraries + * updated Windows binary build to use Qt 4.3.3 and made Qt DLLs + available as a separate package to make wpa_gui installation easier: + http://w1.fi/wpa_supplicant/qt4/wpa_gui-qt433-windows-dll.zip + * added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt); + only shared key/password authentication is supported in this version + +2007-11-24 - v0.6.1 + * added support for configuring password as NtPasswordHash + (16-byte MD4 hash of password) in hash:<32 hex digits> format + * added support for fallback from abbreviated TLS handshake to + full handshake when using EAP-FAST (e.g., due to an expired + PAC-Opaque) + * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest + draft (draft-ietf-emu-eap-gpsk-07.txt) + * added support for drivers that take care of RSN 4-way handshake + internally (WPA_DRIVER_FLAGS_4WAY_HANDSHAKE in get_capa flags and + WPA_ALG_PMK in set_key) + * added an experimental port for Mac OS X (CONFIG_DRIVER_OSX=y in + .config); this version supports only ap_scan=2 mode and allow the + driver to take care of the 4-way handshake + * fixed a buffer overflow in parsing TSF from scan results when using + driver_wext.c with a driver that includes the TSF (e.g., iwl4965) + [Bug 232] + * updated FT support to use the latest draft, IEEE 802.11r/D8.0 + * fixed an integer overflow issue in the ASN.1 parser used by the + (experimental) internal TLS implementation to avoid a potential + buffer read overflow + * fixed a race condition with -W option (wait for a control interface + monitor before starting) that could have caused the first messages to + be lost + * added support for processing TNCC-TNCS-Messages to report + recommendation (allow/none/isolate) when using TNC [Bug 243] + +2007-05-28 - v0.6.0 + * added network configuration parameter 'frequency' for setting + initial channel for IBSS (adhoc) networks + * added experimental IEEE 802.11r/D6.0 support + * updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48 + * updated EAP-PSK to use the IANA-allocated EAP type 47 + * fixed EAP-PAX key derivation + * fixed EAP-PSK bit ordering of the Flags field + * fixed EAP-PEAP/TTLS/FAST to use the correct EAP identifier in + tunnelled identity request (previously, the identifier from the outer + method was used, not the tunnelled identifier which could be + different) + * added support for fragmentation of outer TLS packets during Phase 2 + of EAP-PEAP/TTLS/FAST + * fixed EAP-TTLS AVP parser processing for too short AVP lengths + * added support for EAP-FAST authentication with inner methods that + generate MSK (e.g., EAP-MSCHAPv2 that was previously only supported + for PAC provisioning) + * added support for authenticated EAP-FAST provisioning + * added support for configuring maximum number of EAP-FAST PACs to + store in a PAC list (fast_max_pac_list_len= in phase1 string) + * added support for storing EAP-FAST PACs in binary format + (fast_pac_format=binary in phase1 string) + * fixed dbus ctrl_iface to validate message interface before + dispatching to avoid a possible segfault [Bug 190] + * fixed PeerKey key derivation to use the correct PRF label + * updated Windows binary build to link against OpenSSL 0.9.8d and + added support for EAP-FAST + * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest + draft (draft-ietf-emu-eap-gpsk-04.txt) + * fixed EAP-AKA Notification processing to allow Notification to be + processed after AKA Challenge response has been sent + * updated to use IEEE 802.11w/D2.0 for management frame protection + (still experimental) + * fixed EAP-TTLS implementation not to crash on use of freed memory + if TLS library initialization fails + * added support for EAP-TNC (Trusted Network Connect) + (this version implements the EAP-TNC method and EAP-TTLS changes + needed to run two methods in sequence (IF-T) and the IF-IMC and + IF-TNCCS interfaces from TNCC) + +2006-11-24 - v0.5.6 + * added experimental, integrated TLSv1 client implementation with the + needed X.509/ASN.1/RSA/bignum processing (this can be enabled by + setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in + .config); this can be useful, e.g., if the target system does not + have a suitable TLS library and a minimal code size is required + (total size of this internal TLS/crypto code is bit under 50 kB on + x86 and the crypto code is shared by rest of the supplicant so some + of it was already required; TLSv1/X.509/ASN.1/RSA added about 25 kB) + * removed STAKey handshake since PeerKey handshake has replaced it in + IEEE 802.11ma and there are no known deployments of STAKey + * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest + draft (draft-ietf-emu-eap-gpsk-01.txt) + * added preliminary implementation of IEEE 802.11w/D1.0 (management + frame protection) + (Note: this requires driver support to work properly.) + (Note2: IEEE 802.11w is an unapproved draft and subject to change.) + * fixed Windows named pipes ctrl_iface to not stop listening for + commands if client program opens a named pipe and closes it + immediately without sending a command + * fixed USIM PIN status determination for the case that PIN is not + needed (this allows EAP-AKA to be used with USIM cards that do not + use PIN) + * added support for reading 3G USIM AID from EF_DIR to allow EAP-AKA to + be used with cards that do not support file selection based on + partial AID + * added support for matching the subjectAltName of the authentication + server certificate against multiple name components (e.g., + altsubject_match="DNS:server.example.com;DNS:server2.example.com") + * fixed EAP-SIM/AKA key derivation for re-authentication case (only + affects IEEE 802.1X with dynamic WEP keys) + * changed ctrl_iface network configuration 'get' operations to not + return password/key material; if these fields are requested, "*" + will be returned if the password/key is set, but the value of the + parameter is not exposed + +2006-08-27 - v0.5.5 + * added support for building Windows version with UNICODE defined + (wide-char functions) + * driver_ndis: fixed static WEP configuration to avoid race condition + issues with some NDIS drivers between association and setting WEP + keys + * driver_ndis: added validation for IELength value in scan results to + avoid crashes when using buggy NDIS drivers [Bug 165] + * fixed Release|Win32 target in the Visual Studio project files + (previously, only Debug|Win32 target was set properly) + * changed control interface API call wpa_ctrl_pending() to allow it to + return -1 on error (e.g., connection lost); control interface clients + will need to make sure that they verify that the value is indeed >0 + when determining whether there are pending messages + * added an alternative control interface backend for Windows targets: + Named Pipe (CONFIG_CTRL_IFACE=named_pipe); this is now the default + control interface mechanism for Windows builds (previously, UDP to + localhost was used) + * changed ctrl_interface configuration for UNIX domain sockets: + - deprecated ctrl_interface_group variable (it may be removed in + future versions) + - allow both directory and group be configured with ctrl_interface + in following format: DIR=/var/run/wpa_supplicant GROUP=wheel + - ctrl_interface=/var/run/wpa_supplicant is still supported for the + case when group is not changed + * added support for controlling more than one interface per process in + Windows version + * added a workaround for a case where the AP is using unknown address + (e.g., MAC address of the wired interface) as the source address for + EAPOL-Key frames; previously, that source address was used as the + destination for EAPOL-Key frames and in key derivation; now, BSSID is + used even if the source address does not match with it + (this resolves an interoperability issue with Thomson SpeedTouch 580) + * added a workaround for UDP-based control interface (which was used in + Windows builds before this release) to prevent packets with forged + addresses from being accepted as local control requests + * removed ndis_events.cpp and possibility of using external + ndis_events.exe; C version (ndis_events.c) is fully functional and + there is no desire to maintain two separate versions of this + implementation + * ndis_events: Changed NDIS event notification design to use WMI to + learn the adapter description through Win32_PnPEntity class; this + should fix some cases where the adapter name was not recognized + correctly (e.g., with some USB WLAN adapters, e.g., Ralink RT2500 + USB) [Bug 113] + * fixed selection of the first network in ap_scan=2 mode; previously, + wpa_supplicant could get stuck in SCANNING state when only the first + network for enabled (e.g., after 'wpa_cli select_network 0') + * winsvc: added support for configuring ctrl_interface parameters in + registry (ctrl_interface string value in + HKLM\SOFTWARE\wpa_supplicant\interfaces\0000 key); this new value is + required to enable control interface (previously, this was hardcoded + to be enabled) + * allow wpa_gui subdirectory to be built with both Qt3 and Qt4 + * converted wpa_gui-qt4 subdirectory to use Qt4 specific project format + +2006-06-20 - v0.5.4 + * fixed build with CONFIG_STAKEY=y [Bug 143] + * added support for doing MLME (IEEE 802.11 management frame + processing) in wpa_supplicant when using Devicescape IEEE 802.11 + stack (wireless-dev.git tree) + * added a new network block configuration option, fragment_size, to + configure the maximum EAP fragment size + * driver_ndis: Disable WZC automatically for the selected interface to + avoid conflicts with two programs trying to control the radio; WZC + will be re-enabled (if it was enabled originally) when wpa_supplicant + is terminated + * added an experimental TLSv1 client implementation + (CONFIG_TLS=internal) that can be used instead of an external TLS + library, e.g., to reduce total size requirement on systems that do + not include any TLS library by default (this is not yet complete; + basic functionality is there, but certificate validation is not yet + included) + * added PeerKey handshake implementation for IEEE 802.11e + direct link setup (DLS) to replace STAKey handshake + * fixed WPA PSK update through ctrl_iface for the case where the old + PSK was derived from an ASCII passphrase and the new PSK is set as + a raw PSK (hex string) + * added new configuration option for identifying which network block + was used (id_str in wpa_supplicant.conf; included on + WPA_EVENT_CONNECT monitor event and as WPA_ID_STR environmental + variable in wpa_cli action scripts; in addition WPA_ID variable is + set to the current unique identifier that wpa_supplicant assigned + automatically for the network and that can be used with + GET_NETWORK/SET_NETWORK ctrl_iface commands) + * wpa_cli action script is now called only when the connect/disconnect + status changes or when associating with a different network + * fixed configuration parser not to remove CCMP from group cipher list + if WPA-None (adhoc) is used (pairwise=NONE in that case) + * fixed integrated NDIS events processing not to hang the process due + to a missed change in eloop_win.c API in v0.5.3 [Bug 155] + * added support for EAP Generalized Pre-Shared Key (EAP-GPSK, + draft-clancy-emu-eap-shared-secret-00.txt) + * added Microsoft Visual Studio 2005 solution and project files for + build wpa_supplicant for Windows (see vs2005 subdirectory) + * eloop_win: fixed unregistration of Windows events + * l2_packet_winpcap: fixed a deadlock in deinitializing l2_packet + at the end of RSN pre-authentication and added unregistration of + a Windows event to avoid getting eloop_win stuck with an invalid + handle + * driver_ndis: added support for selecting AP based on BSSID + * added new environmental variable for wpa_cli action scripts: + WPA_CTRL_DIR is the current control interface directory + * driver_ndis: added support for using NDISUIO instead of WinPcap for + OID set/query operations (CONFIG_USE_NDISUIO=y in .config); with new + l2_packet_ndis (CONFIG_L2_PACKET=ndis), this can be used to build + wpa_supplicant without requiring WinPcap; note that using NDISUIO + requires that WZC is disabled (net stop wzcsvc) since NDISUIO allows + only one application to open the device + * changed NDIS driver naming to only include device GUID, e.g., + {7EE3EFE5-C165-472F-986D-F6FBEDFE8C8D}, instead of including WinPcap + specific \Device\NPF_ prefix before the GUID; the prefix is still + allowed for backwards compatibility, but it is not required anymore + when specifying the interface + * driver_ndis: re-initialize driver interface is the adapter is removed + and re-inserted [Bug 159] + * driver_madwifi: fixed TKIP and CCMP sequence number configuration on + big endian hosts [Bug 146] + +2006-04-27 - v0.5.3 + * fixed EAP-GTC response to include correct user identity when run as + phase 2 method of EAP-FAST (i.e., EAP-FAST did not work in v0.5.2) + * driver_ndis: Fixed encryption mode configuration for unencrypted + networks (some NDIS drivers ignored this, but others, e.g., Broadcom, + refused to associate with open networks) [Bug 106] + * driver_ndis: use BSSID OID polling to detect when IBSS network is + formed even when ndis_events code is included since some NDIS drivers + do not generate media connect events in IBSS mode + * config_winreg: allow global ctrl_interface parameter to be configured + in Windows registry + * config_winreg: added support for saving configuration data into + Windows registry + * added support for controlling network device operational state + (dormant/up) for Linux 2.6.17 to improve DHCP processing (see + http://www.flamewarmaster.de/software/dhcpclient/ for a DHCP client + that can use this information) + * driver_wext: added support for WE-21 change to SSID configuration + * driver_wext: fixed privacy configuration for static WEP keys mode + [Bug 140] + * added an optional driver_ops callback for MLME-SETPROTECTION.request + primitive + * added support for EAP-SAKE (no EAP method number allocated yet, so + this is using the same experimental type 255 as EAP-PSK) + * added support for dynamically loading EAP methods (.so files) instead + of requiring them to be statically linked in; this is disabled by + default (see CONFIG_DYNAMIC_EAP_METHODS in defconfig for information + on how to use this) + +2006-03-19 - v0.5.2 + * do not try to use USIM APDUs when initializing PC/SC for SIM card + access for a network that has not enabled EAP-AKA + * fixed EAP phase 2 Nak for EAP-{PEAP,TTLS,FAST} (this was broken in + v0.5.1 due to the new support for expanded EAP types) + * added support for generating EAP Expanded Nak + * try to fetch scan results once before requesting new scan when + starting up in ap_scan=1 mode (this can speed up initial association + a lot with, e.g., madwifi-ng driver) + * added support for receiving EAPOL frames from a Linux bridge + interface (-bbr0 on command line) + * fixed EAPOL re-authentication for sessions that used PMKSA caching + * changed EAP method registration to use a dynamic list of methods + instead of a static list generated at build time + * fixed PMKSA cache deinitialization not to use freed memory when + removing PMKSA entries + * fixed a memory leak in EAP-TTLS re-authentication + * reject WPA/WPA2 message 3/4 if it does not include any valid + WPA/RSN IE + * driver_wext: added fallback to use SIOCSIWENCODE for setting auth_alg + if the driver does not support SIOCSIWAUTH + +2006-01-29 - v0.5.1 + * driver_test: added better support for multiple APs and STAs by using + a directory with sockets that include MAC address for each device in + the name (driver_param=test_dir=/tmp/test) + * added support for EAP expanded type (vendor specific EAP methods) + * added AP_SCAN command into ctrl_iface so that ap_scan configuration + option can be changed if needed + * wpa_cli/wpa_gui: skip non-socket files in control directory when + using UNIX domain sockets; this avoids selecting an incorrect + interface (e.g., a PID file could be in this directory, even though + use of this directory for something else than socket files is not + recommended) + * fixed TLS library deinitialization after RSN pre-authentication not + to disable TLS library for normal authentication + * driver_wext: Remove null-termination from SSID length if the driver + used it; some Linux drivers do this and they were causing problems in + wpa_supplicant not finding matching configuration block. This change + would break a case where the SSID actually ends in '\0', but that is + not likely to happen in real use. + * fixed PMKSA cache processing not to trigger deauthentication if the + current PMKSA cache entry is replaced with a valid new entry + * fixed PC/SC initialization for ap_scan != 1 modes (this fixes + EAP-SIM and EAP-AKA with real SIM/USIM card when using ap_scan=0 or + ap_scan=2) + +2005-12-18 - v0.5.0 (beginning of 0.5.x development releases) + * added experimental STAKey handshake implementation for IEEE 802.11e + direct link setup (DLS); note: this is disabled by default in both + build and runtime configuration (can be enabled with CONFIG_STAKEY=y + and stakey=1) + * fixed EAP-SIM and EAP-AKA pseudonym and fast re-authentication to + decrypt AT_ENCR_DATA attributes correctly + * fixed EAP-AKA to allow resynchronization within the same session + * made code closer to ANSI C89 standard to make it easier to port to + other C libraries and compilers + * started moving operating system or C library specific functions into + wrapper functions defined in os.h and implemented in os_*.c to make + code more portable + * wpa_supplicant can now be built with Microsoft Visual C++ + (e.g., with the freely available Toolkit 2003 version or Visual + C++ 2005 Express Edition and Platform SDK); see nmake.mak for an + example makefile for nmake + * added support for using Windows registry for command line parameters + (CONFIG_MAIN=main_winsvc) and configuration data + (CONFIG_BACKEND=winreg); see win_example.reg for an example registry + contents; this version can be run both as a Windows service and as a + normal application; 'wpasvc.exe app' to start as applicant, + 'wpasvc.exe reg ' to register a service, + 'net start wpasvc' to start the service, 'wpasvc.exe unreg' to + unregister a service + * made it possible to link ndis_events.exe functionality into + wpa_supplicant.exe by defining CONFIG_NDIS_EVENTS_INTEGRATED + * added better support for multiple control interface backends + (CONFIG_CTRL_IFACE option); currently, 'unix' and 'udp' are supported + * fixed PC/SC code to use correct length for GSM AUTH command buffer + and to not use pioRecvPci with SCardTransmit() calls; these were not + causing visible problems with pcsc-lite, but Windows Winscard.dll + refused the previously used parameters; this fixes EAP-SIM and + EAP-AKA authentication using SIM/USIM card under Windows + * added new event loop implementation for Windows using + WaitForMultipleObject() instead of select() in order to allow waiting + for non-socket objects; this can be selected with + CONFIG_ELOOP=eloop_win in .config + * added support for selecting l2_packet implementation in .config + (CONFIG_L2_PACKET; following options are available now: linux, pcap, + winpcap, freebsd, none) + * added new l2_packet implementation for WinPcap + (CONFIG_L2_PACKET=winpcap) that uses a separate receive thread to + reduce latency in EAPOL receive processing from about 100 ms to about + 3 ms + * added support for EAP-FAST key derivation using other ciphers than + RC4-128-SHA for authentication and AES128-SHA for provisioning + * added support for configuring CA certificate as DER file and as a + configuration blob + * fixed private key configuration as configuration blob and added + support for using PKCS#12 as a blob + * tls_gnutls: added support for using PKCS#12 files; added support for + session resumption + * added support for loading trusted CA certificates from Windows + certificate store: ca_cert="cert_store://", where is + likely CA (Intermediate CA certificates) or ROOT (root certificates) + * added C version of ndis_events.cpp and made it possible to build this + with MinGW so that CONFIG_NDIS_EVENTS_INTEGRATED can be used more + easily on cross-compilation builds + * added wpasvc.exe into Windows binary release; this is an alternative + version of wpa_supplicant.exe with configuration backend using + Windows registry and with the entry point designed to run as a + Windows service + * integrated ndis_events.exe functionality into wpa_supplicant.exe and + wpasvc.exe and removed this additional tool from the Windows binary + release since it is not needed anymore + * load winscard.dll functions dynamically when building with MinGW + since MinGW does not yet include winscard library + +2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases) + * l2_packet_pcap: fixed wired IEEE 802.1X authentication with libpcap + and WinPcap to receive frames sent to PAE group address + * disable EAP state machine when IEEE 802.1X authentication is not used + in order to get rid of bogus "EAP failed" messages + * fixed OpenSSL error reporting to go through all pending errors to + avoid confusing reports of old errors being reported at later point + during handshake + * fixed configuration file updating to not write empty variables + (e.g., proto or key_mgmt) that the file parser would not accept + * fixed ADD_NETWORK ctrl_iface command to use the same default values + for variables as empty network definitions read from config file + would get + * fixed EAP state machine to not discard EAP-Failure messages in many + cases (e.g., during TLS handshake) + * fixed a infinite loop in private key reading if the configured file + cannot be parsed successfully + * driver_madwifi: added support for madwifi-ng + * wpa_gui: do not display password/PSK field contents + * wpa_gui: added CA certificate configuration + * driver_ndis: fixed scan request in ap_scan=2 mode not to change SSID + * driver_ndis: include Beacon IEs in AssocInfo in order to notice if + the new AP is using different WPA/RSN IE + * use longer timeout for IEEE 802.11 association to avoid problems with + drivers that may take more than five second to associate + +2005-10-27 - v0.4.6 + * allow fallback to WPA, if mixed WPA+WPA2 networks have mismatch in + RSN IE, but WPA IE would match with wpa_supplicant configuration + * added support for named configuration blobs in order to avoid having + to use file system for external files (e.g., certificates); + variables can be set to "blob://" instead of file path to + use a named blob; supported fields: pac_file, client_cert, + private_key + * fixed RSN pre-authentication (it was broken in the clean up of WPA + state machine interface in v0.4.5) + * driver_madwifi: set IEEE80211_KEY_GROUP flag for group keys to make + sure the driver configures broadcast decryption correctly + * added ca_path (and ca_path2) configuration variables that can be used + to configure OpenSSL CA path, e.g., /etc/ssl/certs, for using the + system-wide trusted CA list + * added support for starting wpa_supplicant without a configuration + file (-C argument must be used to set ctrl_interface parameter for + this case; in addition, -p argument can be used to provide + driver_param; these new arguments can also be used with a + configuration to override the values from the configuration) + * added global control interface that can be optionally used for adding + and removing network interfaces dynamically (-g command line argument + for both wpa_supplicant and wpa_cli) without having to restart + wpa_supplicant process + * wpa_gui: + - try to save configuration whenever something is modified + - added WEP key configuration + - added possibility to edit the current network configuration + * driver_ndis: fixed driver polling not to increase frequency on each + received EAPOL frame due to incorrectly cancelled timeout + * added simple configuration file examples (in examples subdirectory) + * fixed driver_wext.c to filter wireless events based on ifindex to + avoid interfaces receiving events from other interfaces + * delay sending initial EAPOL-Start couple of seconds to speed up + authentication for the most common case of Authenticator starting + EAP authentication immediately after association + +2005-09-25 - v0.4.5 + * added a workaround for clearing keys with ndiswrapper to allow + roaming from WPA enabled AP to plaintext one + * added docbook documentation (doc/docbook) that can be used to + generate, e.g., man pages + * l2_packet_linux: use socket type SOCK_DGRAM instead of SOCK_RAW for + PF_PACKET in order to prepare for network devices that do not use + Ethernet headers (e.g., network stack that includes IEEE 802.11 + header in the frames) + * use receipt of EAPOL-Key frame as a lower layer success indication + for EAP state machine to allow recovery from dropped EAP-Success + frame + * cleaned up internal EAPOL frame processing by not including link + layer (Ethernet) header during WPA and EAPOL/EAP processing; this + header is added only when transmitted the frame; this makes it easier + to use wpa_supplicant on link layers that use different header than + Ethernet + * updated EAP-PSK to use draft 9 by default since this can now be + tested with hostapd; removed support for draft 3, including + server_nai configuration option from network blocks + * driver_wired: add PAE address to the multicast address list in order + to be able to receive EAPOL frames with drivers that do not include + these multicast addresses by default + * driver_wext: add support for WE-19 + * added support for multiple configuration backends (CONFIG_BACKEND + option); currently, only 'file' is supported (i.e., the format used + in wpa_supplicant.conf) + * added support for updating configuration ('wpa_cli save_config'); + this is disabled by default and can be enabled with global + update_config=1 variable in wpa_supplicant.conf; this allows wpa_cli + and wpa_gui to store the configuration changes in a permanent store + * added GET_NETWORK ctrl_iface command + (e.g., 'wpa_cli get_network 0 ssid') + +2005-08-21 - v0.4.4 + * replaced OpenSSL patch for EAP-FAST support + (openssl-tls-extensions.patch) with a more generic and correct + patch (the new patch is not compatible with the previous one, so the + OpenSSL library will need to be patched with the new patch in order + to be able to build wpa_supplicant with EAP-FAST support) + * added support for using Windows certificate store (through CryptoAPI) + for client certificate and private key operations (EAP-TLS) + (see wpa_supplicant.conf for more information on how to configure + this with private_key) + * ported wpa_gui to Windows + * added Qt4 version of wpa_gui (wpa_gui-qt4 directory); this can be + built with the open source version of the Qt4 for Windows + * allow non-WPA modes (e.g., IEEE 802.1X with dynamic WEP) to be used + with drivers that do not support WPA + * ndis_events: fixed Windows 2000 support + * added support for enabling/disabling networks from the list of all + configured networks ('wpa_cli enable_network ' and + 'wpa_cli disable_network ') + * added support for adding and removing network from the current + configuration ('wpa_cli add_network' and 'wpa_cli remove_network + '); added networks are disabled by default and they can + be enabled with enable_network command once the configuration is done + for the new network; note: configuration file is not yet updated, so + these new networks are lost when wpa_supplicant is restarted + * added support for setting network configuration parameters through + the control interface, for example: + wpa_cli set_network 0 ssid "\"my network\"" + * fixed parsing of strings that include both " and # within double + quoted area (e.g., "start"#end") + * added EAP workaround for PEAP session resumption: allow outer, + i.e., not tunneled, EAP-Success to terminate session since; this can + be disabled with eap_workaround=0 + (this was allowed for PEAPv1 before, but now it is also allowed for + PEAPv0 since at least one RADIUS authentication server seems to be + doing this for PEAPv0, too) + * wpa_gui: added preliminary support for adding new networks to the + wpa_supplicant configuration (double click on the scan results to + open network configuration) + +2005-06-26 - v0.4.3 + * removed interface for external EAPOL/EAP supplicant (e.g., + Xsupplicant), (CONFIG_XSUPPLICANT_IFACE) since it is not required + anymore and is unlikely to be used by anyone + * driver_ndis: fixed WinPcap 3.0 support + * fixed build with CONFIG_DNET_PCAP=y on Linux + * l2_packet: moved different implementations into separate files + (l2_packet_*.c) + +2005-06-12 - v0.4.2 + * driver_ipw: updated driver structures to match with ipw2200-1.0.4 + (note: ipw2100-1.1.0 is likely to require an update to work with + this) + * added support for using ap_scan=2 mode with multiple network blocks; + wpa_supplicant will go through the networks one by one until the + driver reports a successful association; this uses the same order for + networks as scan_ssid=1 scans, i.e., the priority field is ignored + and the network block order in the file is used instead + * fixed a potential issue in RSN pre-authentication ending up using + freed memory if pre-authentication times out + * added support for matching alternative subject name extensions of the + authentication server certificate; new configuration variables + altsubject_match and altsubject_match2 + * driver_ndis: added support for IEEE 802.1X authentication with wired + NDIS drivers + * added support for querying private key password (EAP-TLS) through the + control interface (wpa_cli/wpa_gui) if one is not included in the + configuration file + * driver_broadcom: fixed couple of memory leaks in scan result + processing + * EAP-PAX is now registered as EAP type 46 + * fixed EAP-PAX MAC calculation + * fixed EAP-PAX CK and ICK key derivation + * added support for using password with EAP-PAX (as an alternative to + entering key with eappsk); SHA-1 hash of the password will be used as + the key in this case + * added support for arbitrary driver interface parameters through the + configuration file with a new driver_param field; this adds a new + driver_ops function set_param() + * added possibility to override l2_packet module with driver interface + API (new send_eapol handler); this can be used to implement driver + specific TX/RX functions for EAPOL frames + * fixed ctrl_interface_group processing for the case where gid is + entered as a number, not group name + * driver_test: added support for testing hostapd with wpa_supplicant + by using test driver interface without any kernel drivers or network + cards + +2005-05-22 - v0.4.1 + * driver_madwifi: fixed WPA/WPA2 mode configuration to allow EAPOL + packets to be encrypted; this was apparently broken by the changed + ioctl order in v0.4.0 + * driver_madwifi: added preliminary support for compiling against 'BSD' + branch of madwifi CVS tree + * added support for EAP-MSCHAPv2 password retries within the same EAP + authentication session + * added support for password changes with EAP-MSCHAPv2 (used when the + password has expired) + * added support for reading additional certificates from PKCS#12 files + and adding them to the certificate chain + * fixed association with IEEE 802.1X (no WPA) when dynamic WEP keys + were used + * fixed a possible double free in EAP-TTLS fast-reauthentication when + identity or password is entered through control interface + * display EAP Notification messages to user through control interface + with "CTRL-EVENT-EAP-NOTIFICATION" prefix + * added GUI version of wpa_cli, wpa_gui; this is not build + automatically with 'make'; use 'make wpa_gui' to build (this requires + Qt development tools) + * added 'disconnect' command to control interface for setting + wpa_supplicant in state where it will not associate before + 'reassociate' command has been used + * added support for selecting a network from the list of all configured + networks ('wpa_cli select_network '; this disabled all + other networks; to re-enable, 'wpa_cli select_network any') + * added support for getting scan results through control interface + * added EAP workaround for PEAPv1 session resumption: allow outer, + i.e., not tunneled, EAP-Success to terminate session since; this can + be disabled with eap_workaround=0 + +2005-04-25 - v0.4.0 (beginning of 0.4.x development releases) + * added a new build time option, CONFIG_NO_STDOUT_DEBUG, that can be + used to reduce the size of the wpa_supplicant considerably if + debugging code is not needed + * fixed EAPOL-Key validation to drop packets with invalid Key Data + Length; such frames could have crashed wpa_supplicant due to buffer + overflow + * added support for wired authentication (IEEE 802.1X on wired + Ethernet); driver interface 'wired' + * obsoleted set_wpa() handler in the driver interface API (it can be + replaced by moving enable/disable functionality into init()/deinit()) + (calls to set_wpa() are still present for backwards compatibility, + but they may be removed in the future) + * driver_madwifi: fixed association in plaintext mode + * modified the EAP workaround that accepts EAP-Success with incorrect + Identifier to be even less strict about verification in order to + interoperate with some authentication servers + * added support for sending TLS alerts + * added support for 'any' SSID wildcard; if ssid is not configured or + is set to an empty string, any SSID will be accepted for non-WPA AP + * added support for asking PIN (for SIM) from frontends (e.g., + wpa_cli); if a PIN is needed, but not included in the configuration + file, a control interface request is sent and EAP processing is + delayed until the PIN is available + * added support for using external devices (e.g., a smartcard) for + private key operations in EAP-TLS (CONFIG_SMARTCARD=y in .config); + new wpa_supplicant.conf variables: + - global: opensc_engine_path, pkcs11_engine_path, pkcs11_module_path + - network: engine, engine_id, key_id + * added experimental support for EAP-PAX + * added monitor mode for wpa_cli (-a) that + allows external commands (e.g., shell scripts) to be run based on + wpa_supplicant events, e.g., when authentication has been completed + and data connection is ready; other related wpa_cli arguments: + -B (run in background), -P (write PID file); wpa_supplicant has a new + command line argument (-W) that can be used to make it wait until a + control interface command is received in order to avoid missing + events + * added support for opportunistic WPA2 PMKSA key caching (disabled by + default, can be enabled with proactive_key_caching=1) + * fixed RSN IE in 4-Way Handshake message 2/4 for the case where + Authenticator rejects PMKSA caching attempt and the driver is not + using assoc_info events + * added -P argument for wpa_supplicant to write the current + process id into a file + +2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) + * added new phase1 option parameter, include_tls_length=1, to force + wpa_supplicant to add TLS Message Length field to all TLS messages + even if the packet is not fragmented; this may be needed with some + authentication servers + * fixed WPA/RSN IE verification in message 3 of 4-Way Handshake when + using drivers that take care of AP selection (e.g., when using + ap_scan=2) + * fixed reprocessing of pending request after ctrl_iface requests for + identity/password/otp + * fixed ctrl_iface requests for identity/password/otp in Phase 2 of + EAP-PEAP and EAP-TTLS + * all drivers using driver_wext: set interface up and select Managed + mode when starting wpa_supplicant; set interface down when exiting + * renamed driver_ipw2100.c to driver_ipw.c since it now supports both + ipw2100 and ipw2200; please note that this also changed the + configuration variable in .config to CONFIG_DRIVER_IPW + +2005-01-24 - v0.3.6 + * fixed a busy loop introduced in v0.3.5 for scan result processing + when no matching AP is found + +2005-01-23 - v0.3.5 + * added a workaround for an interoperability issue with a Cisco AP + when using WPA2-PSK + * fixed non-WPA IEEE 802.1X to use the same authentication timeout as + WPA with IEEE 802.1X (i.e., timeout 10 -> 70 sec to allow + retransmission of dropped frames) + * fixed issues with 64-bit CPUs and SHA1 cleanup in previous version + (e.g., segfault when processing EAPOL-Key frames) + * fixed EAP workaround and fast reauthentication configuration for + RSN pre-authentication; previously these were disabled and + pre-authentication would fail if the used authentication server + requires EAP workarounds + * added support for blacklisting APs that fail or timeout + authentication in ap_scan=1 mode so that all APs are tried in cases + where the ones with strongest signal level are failing authentication + * fixed CA certificate loading after a failed EAP-TLS/PEAP/TTLS + authentication attempt + * allow EAP-PEAP/TTLS fast reauthentication only if Phase 2 succeeded + in the previous authentication (previously, only Phase 1 success was + verified) + +2005-01-09 - v0.3.4 + * added preliminary support for IBSS (ad-hoc) mode configuration + (mode=1 in network block); this included a new key_mgmt mode + WPA-NONE, i.e., TKIP or CCMP with a fixed key (based on psk) and no + key management; see wpa_supplicant.conf for more details and an + example on how to configure this (note: this is currently implemented + only for driver_hostapd.c, but the changes should be trivial to add + in associate() handler for other drivers, too (assuming the driver + supports WPA-None) + * added preliminary port for native Windows (i.e., no cygwin) using + mingw + +2005-01-02 - v0.3.3 + * added optional support for GNU Readline and History Libraries for + wpa_cli (CONFIG_READLINE) + * cleaned up EAP state machine <-> method interface and number of + small problems with error case processing not terminating on + EAP-Failure but waiting for timeout + * added couple of workarounds for interoperability issues with a + Cisco AP when using WPA2 + * added support for EAP-FAST (draft-cam-winget-eap-fast-00.txt); + Note: This requires a patch for openssl to add support for TLS + extensions and number of workarounds for operations without + certificates. Proof of concept type of experimental patch is + included in openssl-tls-extensions.patch. + +2004-12-19 - v0.3.2 + * fixed private key loading for cases where passphrase is not set + * fixed Windows/cygwin L2 packet handler freeing; previous version + could cause a segfault when RSN pre-authentication was completed + * added support for PMKSA caching with drivers that generate RSN IEs + (e.g., NDIS); currently, this is only implemented in driver_ndis.c, + but similar code can be easily added to driver_ndiswrapper.c once + ndiswrapper gets full support for RSN PMKSA caching + * improved recovery from PMKID mismatches by requesting full EAP + authentication in case of failed PMKSA caching attempt + * driver_ndis: added support for NDIS NdisMIncidateStatus() events + (this requires that ndis_events is ran while wpa_supplicant is + running) + * driver_ndis: use ADD_WEP/REMOVE_WEP when configuring WEP keys + * added support for driver interfaces to replace the interface name + based on driver/OS specific mapping, e.g., in case of driver_ndis, + this allows the beginning of the adapter description to be used as + the interface name + * added support for CR+LF (Windows-style) line ends in configuration + file + * driver_ndis: enable radio before starting scanning, disable radio + when exiting + * modified association event handler to set portEnabled = FALSE before + clearing port Valid in order to reset EAP state machine and avoid + problems with new authentication getting ignored because of state + machines ending up in AUTHENTICATED/SUCCESS state based on old + information + * added support for driver events to add PMKID candidates in order to + allow drivers to give priority to most likely roaming candidates + * driver_hostap: moved PrivacyInvoked configuration to associate() + function so that this will not be set for plaintext connections + * added KEY_MGMT_802_1X_NO_WPA as a new key_mgmt type so that driver + interface can distinguish plaintext and IEEE 802.1X (no WPA) + authentication + * fixed static WEP key configuration to use broadcast/default type for + all keys (previously, the default TX key was configured as pairwise/ + unicast key) + * driver_ndis: added legacy WPA capability detection for non-WPA2 + drivers + * added support for setting static WEP keys for IEEE 802.1X without + dynamic WEP keying (eapol_flags=0) + +2004-12-12 - v0.3.1 + * added support for reading PKCS#12 (PFX) files (as a replacement for + PEM/DER) to get certificate and private key (CONFIG_PKCS12) + * fixed compilation with CONFIG_PCSC=y + * added new ap_scan mode, ap_scan=2, for drivers that take care of + association, but need to be configured with security policy and SSID, + e.g., ndiswrapper and NDIS driver; this mode should allow such + drivers to work with hidden SSIDs and optimized roaming; when + ap_scan=2 is used, only the first network block in the configuration + file is used and this configuration should have explicit security + policy (i.e., only one option in the lists) for key_mgmt, pairwise, + group, proto variables + * added experimental port of wpa_supplicant for Windows + - driver_ndis.c driver interface (NDIS OIDs) + - currently, this requires cygwin and WinPcap + - small utility, win_if_list, can be used to get interface name + * control interface can now be removed at build time; add + CONFIG_CTRL_IFACE=y to .config to maintain old functionality + * optional Xsupplicant interface can now be removed at build time; + (CONFIG_XSUPPLICANT_IFACE=y in .config to bring it back) + * added auth_alg to driver interface associate() parameters to make it + easier for drivers to configure authentication algorithm as part of + the association + +2004-12-05 - v0.3.0 (beginning of 0.3.x development releases) + * driver_broadcom: added new driver interface for Broadcom wl.o driver + (a generic driver for Broadcom IEEE 802.11a/g cards) + * wpa_cli: fixed parsing of -p command line argument + * PEAPv1: fixed tunneled EAP-Success reply handling to reply with TLS + ACK, not tunneled EAP-Success (of which only the first byte was + actually send due to a bug in previous code); this seems to + interoperate with most RADIUS servers that implements PEAPv1 + * PEAPv1: added support for terminating PEAP authentication on tunneled + EAP-Success message; this can be configured by adding + peap_outer_success=0 on phase1 parameters in wpa_supplicant.conf + (some RADIUS servers require this whereas others require a tunneled + reply + * PEAPv1: changed phase1 option peaplabel to use default to 0, i.e., to + the old label for key derivation; previously, the default was 1, + but it looks like most existing PEAPv1 implementations use the old + label which is thus more suitable default option + * added support for EAP-PSK (draft-bersani-eap-psk-03.txt) + * fixed parsing of wep_tx_keyidx + * added support for configuring list of allowed Phase 2 EAP types + (for both EAP-PEAP and EAP-TTLS) instead of only one type + * added support for configuring IEEE 802.11 authentication algorithm + (auth_alg; mainly for using Shared Key authentication with static + WEP keys) + * added support for EAP-AKA (with UMTS SIM) + * fixed couple of errors in PCSC handling that could have caused + random-looking errors for EAP-SIM + * added support for EAP-SIM pseudonyms and fast re-authentication + * added support for EAP-TLS/PEAP/TTLS fast re-authentication (TLS + session resumption) + * added support for EAP-SIM with two challenges + (phase1="sim_min_num_chal=3" can be used to require three challenges) + * added support for configuring DH/DSA parameters for an ephemeral DH + key exchange (EAP-TLS/PEAP/TTLS) using new configuration parameters + dh_file and dh_file2 (phase 2); this adds support for using DSA keys + and optional DH key exchange to achieve forward secracy with RSA keys + * added support for matching subject of the authentication server + certificate with a substring when using EAP-TLS/PEAP/TTLS; new + configuration variables subject_match and subject_match2 + * changed SSID configuration in driver_wext.c (used by many driver + interfaces) to use ssid_len+1 as the length for SSID since some Linux + drivers expect this + * fixed couple of unaligned reads in scan result parsing to fix WPA + connection on some platforms (e.g., ARM) + * added driver interface for Intel ipw2100 driver + * added support for LEAP with WPA + * added support for larger scan results report (old limit was 4 kB of + data, i.e., about 35 or so APs) when using Linux wireless extensions + v17 or newer + * fixed a bug in PMKSA cache processing: skip sending of EAPOL-Start + only if there is a PMKSA cache entry for the current AP + * fixed error handling for case where reading of scan results fails: + must schedule a new scan or wpa_supplicant will remain waiting + forever + * changed debug output to remove shared password/key material by + default; all key information can be included with -K command line + argument to match the previous behavior + * added support for timestamping debug log messages (disabled by + default, can be enabled with -t command line argument) + * set pairwise/group cipher suite for non-WPA IEEE 802.1X to WEP-104 + if keys are not configured to be used; this fixes IEEE 802.1X mode + with drivers that use this information to configure whether Privacy + bit can be in Beacon frames (e.g., ndiswrapper) + * avoid clearing driver keys if no keys have been configured since last + key clear request; this seems to improve reliability of group key + handshake for ndiswrapper & NDIS driver which seems to be suffering + of some kind of timing issue when the keys are cleared again after + association + * changed driver interface API: + - WPA_SUPPLICANT_DRIVER_VERSION define can be used to determine which + version is being used (now, this is set to 2; previously, it was + not defined) + - pass pointer to private data structure to all calls + - the new API is not backwards compatible; all in-tree driver + interfaces has been converted to the new API + * added support for controlling multiple interfaces (radios) per + wpa_supplicant process; each interface needs to be listed on the + command line (-c, -i, -D arguments) with -N as a separator + (-cwpa1.conf -iwlan0 -Dhostap -N -cwpa2.conf -iath0 -Dmadwifi) + * added a workaround for EAP servers that incorrectly use same Id for + sequential EAP packets + * changed libpcap/libdnet configuration to use .config variable, + CONFIG_DNET_PCAP, instead of requiring Makefile modification + * improved downgrade attack detection in IE verification of msg 3/4: + verify both WPA and RSN IEs, if present, not only the selected one; + reject the AP if an RSN IE is found in msg 3/4, but not in Beacon or + Probe Response frame, and RSN is enabled in wpa_supplicant + configuration + * fixed WPA msg 3/4 processing to allow Key Data field contain other + IEs than just one WPA IE + * added support for FreeBSD and driver interface for the BSD net80211 + layer (CONFIG_DRIVER_BSD=y in .config); please note that some of the + required kernel mods have not yet been committed + * made EAP workarounds configurable; enabled by default, can be + disabled with network block option eap_workaround=0 + +2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases) + * resolved couple of interoperability issues with EAP-PEAPv1 and + Phase 2 (inner EAP) fragment reassembly + * driver_madwifi: fixed WEP key configuration for IEEE 802.1X when the + AP is using non-zero key index for the unicast key and key index zero + for the broadcast key + * driver_hostap: fixed IEEE 802.1X WEP key updates and + re-authentication by allowing unencrypted EAPOL frames when not using + WPA + * added a new driver interface, 'wext', which uses only standard, + driver independent functionality in Linux wireless extensions; + currently, this can be used only for non-WPA IEEE 802.1X mode, but + eventually, this is to be extended to support full WPA/WPA2 once + Linux wireless extensions get support for this + * added support for mode in which the driver is responsible for AP + scanning and selection; this is disabled by default and can be + enabled with global ap_scan=0 variable in wpa_supplicant.conf; + this mode can be used, e.g., with generic 'wext' driver interface to + use wpa_supplicant as IEEE 802.1X Supplicant with any Linux driver + supporting wireless extensions. + * driver_madwifi: fixed WPA2 configuration and scan_ssid=1 (e.g., + operation with an AP that does not include SSID in the Beacon frames) + * added support for new EAP authentication methods: + EAP-TTLS/EAP-OTP, EAP-PEAPv0/OTP, EAP-PEAPv1/OTP, EAP-OTP + * added support for asking one-time-passwords from frontends (e.g., + wpa_cli); this 'otp' command works otherwise like 'password' command, + but the password is used only once and the frontend will be asked for + a new password whenever a request from authenticator requires a + password; this can be used with both EAP-OTP and EAP-GTC + * changed wpa_cli to automatically re-establish connection so that it + does not need to be re-started when wpa_supplicant is terminated and + started again + * improved user data (identity/password/otp) requests through + frontends: process pending EAPOL packets after getting new + information so that full authentication does not need to be + restarted; in addition, send pending requests again whenever a new + frontend is attached + * changed control frontends to use a new directory for socket files to + make it easier for wpa_cli to automatically select between interfaces + and to provide access control for the control interface; + wpa_supplicant.conf: ctrl_interface is now a path + (/var/run/wpa_supplicant is the recommended path) and + ctrl_interface_group can be used to select which group gets access to + the control interface; + wpa_cli: by default, try to connect to the first interface available + in /var/run/wpa_supplicant; this path can be overridden with -p option + and an interface can be selected with -i option (i.e., in most common + cases, wpa_cli does not need to get any arguments) + * added support for LEAP + * added driver interface for Linux ndiswrapper + * added priority option for network blocks in the configuration file; + this allows networks to be grouped based on priority (the scan + results are searched for matches with network blocks in this order) + +2004-06-20 - v0.2.3 + * sort scan results to improve AP selection + * fixed control interface socket removal for some error cases + * improved scan requesting and authentication timeout + * small improvements/bug fixes for EAP-MSCHAPv2, EAP-PEAP, and + TLS processing + * PEAP version can now be forced with phase1="peapver=" + (mostly for testing; by default, the highest version supported by + both the Supplicant and Authentication Server is selected + automatically) + * added support for madwifi driver (Atheros ar521x) + * added a workaround for cases where AP sets Install Tx/Rx bit for + WPA Group Key messages when pairwise keys are used (without this, + the Group Key would be used for Tx and the AP would drop frames + from the station) + * added GSM SIM/USIM interface for GSM authentication algorithm for + EAP-SIM; this requires pcsc-lite + * added support for ATMEL AT76C5XXx driver + * fixed IEEE 802.1X WEP key derivation in the case where Authenticator + does not include key data in the EAPOL-Key frame (i.e., part of + EAP keying material is used as data encryption key) + * added support for using plaintext and static WEP networks + (key_mgmt=NONE) + +2004-05-31 - v0.2.2 + * added support for new EAP authentication methods: + EAP-TTLS/EAP-MD5-Challenge + EAP-TTLS/EAP-GTC + EAP-TTLS/EAP-MSCHAPv2 + EAP-TTLS/EAP-TLS + EAP-TTLS/MSCHAPv2 + EAP-TTLS/MSCHAP + EAP-TTLS/PAP + EAP-TTLS/CHAP + EAP-PEAP/TLS + EAP-PEAP/GTC + EAP-PEAP/MD5-Challenge + EAP-GTC + EAP-SIM (not yet complete; needs GSM/SIM authentication interface) + * added support for anonymous identity (to be used when identity is + sent in plaintext; real identity will be used within TLS protected + tunnel (e.g., with EAP-TTLS) + * added event messages from wpa_supplicant to frontends, e.g., wpa_cli + * added support for requesting identity and password information using + control interface; in other words, the password for EAP-PEAP or + EAP-TTLS does not need to be included in the configuration file since + a frontand (e.g., wpa_cli) can ask it from the user + * improved RSN pre-authentication to use a candidate list and process + all candidates from each scan; not only one per scan + * fixed RSN IE and WPA IE capabilities field parsing + * ignore Tx bit in GTK IE when Pairwise keys are used + * avoid making new scan requests during IEEE 802.1X negotiation + * use openssl/libcrypto for MD5 and SHA-1 when compiling wpa_supplicant + with TLS support (this replaces the included implementation with + library code to save about 8 kB since the library code is needed + anyway for TLS) + * fixed WPA-PSK only mode when compiled without IEEE 802.1X support + (i.e., without CONFIG_IEEE8021X_EAPOL=y in .config) + +2004-05-06 - v0.2.1 + * added support for internal IEEE 802.1X (actually, IEEE 802.1aa/D6.1) + Supplicant + - EAPOL state machines for Supplicant [IEEE 802.1aa/D6.1] + - EAP peer state machine [draft-ietf-eap-statemachine-02.pdf] + - EAP-MD5 (cannot be used with WPA-RADIUS) + [draft-ietf-eap-rfc2284bis-09.txt] + - EAP-TLS [RFC 2716] + - EAP-MSCHAPv2 (currently used only with EAP-PEAP) + - EAP-PEAP/MSCHAPv2 [draft-josefsson-pppext-eap-tls-eap-07.txt] + [draft-kamath-pppext-eap-mschapv2-00.txt] + (PEAP version 0, 1, and parts of 2; only 0 and 1 are enabled by + default; tested with FreeRADIUS, Microsoft IAS, and Funk Odyssey) + - new configuration file options: eap, identity, password, ca_cert, + client_cert, privatekey, private_key_passwd + - Xsupplicant is not required anymore, but it can be used by + disabling the internal IEEE 802.1X Supplicant with -e command line + option + - this code is not included in the default build; Makefile need to + be edited for this (uncomment lines for selected functionality) + - EAP-TLS and EAP-PEAP require openssl libraries + * use module prefix in debug messages (WPA, EAP, EAP-TLS, ..) + * added support for non-WPA IEEE 802.1X mode with dynamic WEP keys + (i.e., complete IEEE 802.1X/EAP authentication and use IEEE 802.1X + EAPOL-Key frames instead of WPA key handshakes) + * added support for IEEE 802.11i/RSN (WPA2) + - improved PTK Key Handshake + - PMKSA caching, pre-authentication + * fixed wpa_supplicant to ignore possible extra data after WPA + EAPOL-Key packets (this fixes 'Invalid EAPOL-Key MIC when using + TPTK' error from message 3 of 4-Way Handshake in case the AP + includes extra data after the EAPOL-Key) + * added interface for external programs (frontends) to control + wpa_supplicant + - CLI example (wpa_cli) with interactive mode and command line + mode + - replaced SIGUSR1 status/statistics with the new control interface + * made some feature compile time configurable + - .config file for make + - driver interfaces (hostap, hermes, ..) + - EAPOL/EAP functions + +2004-02-15 - v0.2.0 + * Initial version of wpa_supplicant diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile new file mode 100644 index 000000000000..cb66defac7c8 --- /dev/null +++ b/wpa_supplicant/Makefile @@ -0,0 +1,2074 @@ +BINALL=wpa_supplicant wpa_cli + +ifndef CONFIG_NO_WPA_PASSPHRASE +BINALL += wpa_passphrase +endif + +ALL = $(BINALL) +ALL += systemd/wpa_supplicant.service +ALL += systemd/wpa_supplicant@.service +ALL += systemd/wpa_supplicant-nl80211@.service +ALL += systemd/wpa_supplicant-wired@.service +ALL += dbus/fi.w1.wpa_supplicant1.service +ifdef CONFIG_BUILD_WPA_CLIENT_SO +ALL += libwpa_client.so +endif + +EXTRA_TARGETS=dynamic_eap_methods + +CONFIG_FILE=.config +include ../src/build.rules + +ifdef LIBS +# If LIBS is set with some global build system defaults, clone those for +# LIBS_c and LIBS_p to cover wpa_passphrase and wpa_cli as well. +ifndef LIBS_c +LIBS_c := $(LIBS) +endif +ifndef LIBS_p +LIBS_p := $(LIBS) +endif +endif + +export LIBDIR ?= /usr/local/lib +export INCDIR ?= /usr/local/include +export BINDIR ?= /usr/local/sbin +PKG_CONFIG ?= pkg-config + +CFLAGS += $(EXTRA_CFLAGS) +CFLAGS += -I$(abspath ../src) +CFLAGS += -I$(abspath ../src/utils) + +ifndef CONFIG_NO_GITVER +# Add VERSION_STR postfix for builds from a git repository +ifeq ($(wildcard ../.git),../.git) +GITVER := $(shell git describe --dirty=+) +ifneq ($(GITVER),) +CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\" +endif +endif +endif + +ifdef CONFIG_TESTING_OPTIONS +CFLAGS += -DCONFIG_TESTING_OPTIONS +CONFIG_WPS_TESTING=y +CONFIG_TDLS_TESTING=y +endif + +mkconfig: + @if [ -f .config ]; then \ + echo '.config exists - did not replace it'; \ + exit 1; \ + fi + echo CONFIG_DRIVER_HOSTAP=y >> .config + echo CONFIG_DRIVER_WEXT=y >> .config + +$(DESTDIR)$(BINDIR)/%: % + install -D $(<) $(@) + +install: $(addprefix $(DESTDIR)$(BINDIR)/,$(BINALL)) + $(MAKE) -C ../src install +ifdef CONFIG_BUILD_WPA_CLIENT_SO + install -m 0644 -D libwpa_client.so $(DESTDIR)/$(LIBDIR)/libwpa_client.so + install -m 0644 -D ../src/common/wpa_ctrl.h $(DESTDIR)/$(INCDIR)/wpa_ctrl.h +endif + if ls eap_*.so >/dev/null 2>&1; then \ + install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ + cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ + ; fi + +ifdef CONFIG_FIPS +CONFIG_NO_RANDOM_POOL= +CONFIG_OPENSSL_CMAC=y +endif + +OBJS = config.o +OBJS += notify.o +OBJS += bss.o +OBJS += eap_register.o +OBJS += ../src/utils/common.o +OBJS += ../src/utils/config.o +OBJS += ../src/utils/wpa_debug.o +OBJS += ../src/utils/wpabuf.o +OBJS += ../src/utils/bitfield.o +OBJS += ../src/utils/ip_addr.o +OBJS += ../src/utils/crc32.o +OBJS += op_classes.o +OBJS += rrm.o +OBJS += twt.o +OBJS += robust_av.o +OBJS_p = wpa_passphrase.o +OBJS_p += ../src/utils/common.o +OBJS_p += ../src/utils/wpa_debug.o +OBJS_p += ../src/utils/wpabuf.o +OBJS_c = wpa_cli.o ../src/common/wpa_ctrl.o +OBJS_c += ../src/utils/wpa_debug.o +OBJS_c += ../src/utils/common.o +OBJS_c += ../src/common/cli.o +OBJS += wmm_ac.o + +ifndef CONFIG_OS +ifdef CONFIG_NATIVE_WINDOWS +CONFIG_OS=win32 +else +CONFIG_OS=unix +endif +endif + +ifeq ($(CONFIG_OS), internal) +CFLAGS += -DOS_NO_C_LIB_DEFINES +endif + +OBJS += ../src/utils/os_$(CONFIG_OS).o +OBJS_p += ../src/utils/os_$(CONFIG_OS).o +OBJS_c += ../src/utils/os_$(CONFIG_OS).o + +ifdef CONFIG_WPA_TRACE +CFLAGS += -DWPA_TRACE +OBJS += ../src/utils/trace.o +OBJS_p += ../src/utils/trace.o +OBJS_c += ../src/utils/trace.o +OBJS_priv += ../src/utils/trace.o +LIBCTRL += ../src/utils/trace.o +LIBCTRLSO += ../src/utils/trace.c +LDFLAGS += -rdynamic +CFLAGS += -funwind-tables +ifdef CONFIG_WPA_TRACE_BFD +CFLAGS += -DPACKAGE="wpa_supplicant" -DWPA_TRACE_BFD +LIBS += -lbfd -ldl -liberty -lz +LIBS_p += -lbfd -ldl -liberty -lz +LIBS_c += -lbfd -ldl -liberty -lz +endif +endif + +ifndef CONFIG_ELOOP +CONFIG_ELOOP=eloop +endif +OBJS += ../src/utils/$(CONFIG_ELOOP).o +OBJS_c += ../src/utils/$(CONFIG_ELOOP).o + +ifndef CONFIG_OSX +ifeq ($(CONFIG_ELOOP), eloop) +# Using glibc < 2.17 requires -lrt for clock_gettime() +# OS X has an alternate implementation +LIBS += -lrt +LIBS_c += -lrt +LIBS_p += -lrt +endif +endif + +ifdef CONFIG_ELOOP_POLL +CFLAGS += -DCONFIG_ELOOP_POLL +endif + +ifdef CONFIG_ELOOP_EPOLL +CFLAGS += -DCONFIG_ELOOP_EPOLL +endif + +ifdef CONFIG_ELOOP_KQUEUE +CFLAGS += -DCONFIG_ELOOP_KQUEUE +endif + +ifdef CONFIG_EAPOL_TEST +CFLAGS += -Werror -DEAPOL_TEST +endif + +ifdef CONFIG_CODE_COVERAGE +CFLAGS += -O0 -fprofile-arcs -ftest-coverage +LIBS += -lgcov +LIBS_c += -lgcov +LIBS_p += -lgcov +endif + +ifdef CONFIG_HT_OVERRIDES +CFLAGS += -DCONFIG_HT_OVERRIDES +endif + +ifdef CONFIG_VHT_OVERRIDES +CFLAGS += -DCONFIG_VHT_OVERRIDES +endif + +ifdef CONFIG_HE_OVERRIDES +CFLAGS += -DCONFIG_HE_OVERRIDES +endif + +ifndef CONFIG_BACKEND +CONFIG_BACKEND=file +endif + +ifeq ($(CONFIG_BACKEND), file) +OBJS += config_file.o +ifndef CONFIG_NO_CONFIG_BLOBS +NEED_BASE64=y +endif +CFLAGS += -DCONFIG_BACKEND_FILE +endif + +ifeq ($(CONFIG_BACKEND), winreg) +OBJS += config_winreg.o +endif + +ifeq ($(CONFIG_BACKEND), none) +OBJS += config_none.o +endif + +ifdef CONFIG_NO_CONFIG_WRITE +CFLAGS += -DCONFIG_NO_CONFIG_WRITE +endif + +ifdef CONFIG_NO_CONFIG_BLOBS +CFLAGS += -DCONFIG_NO_CONFIG_BLOBS +endif + +ifdef CONFIG_NO_SCAN_PROCESSING +CFLAGS += -DCONFIG_NO_SCAN_PROCESSING +endif + +ifdef CONFIG_SUITEB +CFLAGS += -DCONFIG_SUITEB +endif + +ifdef CONFIG_SUITEB192 +CFLAGS += -DCONFIG_SUITEB192 +NEED_SHA384=y +endif + +ifdef CONFIG_OCV +CFLAGS += -DCONFIG_OCV +OBJS += ../src/common/ocv.o +endif + +ifdef CONFIG_IEEE80211R +CFLAGS += -DCONFIG_IEEE80211R +OBJS += ../src/rsn_supp/wpa_ft.o +endif + +ifdef CONFIG_MESH +NEED_80211_COMMON=y +NEED_AES_SIV=y +CONFIG_SAE=y +CONFIG_AP=y +CFLAGS += -DCONFIG_MESH +OBJS += mesh.o +OBJS += mesh_mpm.o +OBJS += mesh_rsn.o +endif + +ifdef CONFIG_SAE +CFLAGS += -DCONFIG_SAE +OBJS += ../src/common/sae.o +ifdef CONFIG_SAE_PK +CFLAGS += -DCONFIG_SAE_PK +OBJS += ../src/common/sae_pk.o +endif +NEED_ECC=y +NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y +NEED_DRAGONFLY=y +ifdef CONFIG_TESTING_OPTIONS +NEED_DH_GROUPS_ALL=y +endif +endif + +ifdef CONFIG_DPP +CFLAGS += -DCONFIG_DPP +OBJS += ../src/common/dpp.o +OBJS += ../src/common/dpp_auth.o +OBJS += ../src/common/dpp_backup.o +OBJS += ../src/common/dpp_crypto.o +OBJS += ../src/common/dpp_pkex.o +OBJS += ../src/common/dpp_reconfig.o +OBJS += ../src/common/dpp_tcp.o +OBJS += dpp_supplicant.o +NEED_AES_SIV=y +NEED_HMAC_SHA256_KDF=y +NEED_HMAC_SHA384_KDF=y +NEED_HMAC_SHA512_KDF=y +NEED_SHA384=y +NEED_SHA512=y +NEED_ECC=y +NEED_JSON=y +NEED_GAS_SERVER=y +NEED_BASE64=y +NEED_ASN1=y +ifdef CONFIG_DPP2 +CFLAGS += -DCONFIG_DPP2 +endif +ifdef CONFIG_DPP3 +CFLAGS += -DCONFIG_DPP3 +endif +endif + +ifdef CONFIG_OWE +CFLAGS += -DCONFIG_OWE +NEED_ECC=y +NEED_HMAC_SHA256_KDF=y +NEED_HMAC_SHA384_KDF=y +NEED_HMAC_SHA512_KDF=y +NEED_SHA384=y +NEED_SHA512=y +endif + +ifdef CONFIG_FILS +CFLAGS += -DCONFIG_FILS +NEED_SHA384=y +NEED_AES_SIV=y +ifdef CONFIG_FILS_SK_PFS +CFLAGS += -DCONFIG_FILS_SK_PFS +NEED_ECC=y +endif +endif + +ifdef CONFIG_MBO +CONFIG_WNM=y +endif + +ifdef CONFIG_WNM +CFLAGS += -DCONFIG_WNM +OBJS += wnm_sta.o +endif + +ifdef CONFIG_TDLS +CFLAGS += -DCONFIG_TDLS +OBJS += ../src/rsn_supp/tdls.o +endif + +ifdef CONFIG_TDLS_TESTING +CFLAGS += -DCONFIG_TDLS_TESTING +endif + +ifdef CONFIG_PMKSA_CACHE_EXTERNAL +CFLAGS += -DCONFIG_PMKSA_CACHE_EXTERNAL +endif + +ifndef CONFIG_NO_WPA +OBJS += ../src/rsn_supp/wpa.o +OBJS += ../src/rsn_supp/preauth.o +OBJS += ../src/rsn_supp/pmksa_cache.o +OBJS += ../src/rsn_supp/wpa_ie.o +OBJS += ../src/common/wpa_common.o +NEED_AES=y +NEED_SHA1=y +NEED_MD5=y +NEED_RC4=y +else +CFLAGS += -DCONFIG_NO_WPA +ifeq ($(CONFIG_TLS), internal) +NEED_SHA1=y +NEED_MD5=y +endif +endif + +ifdef CONFIG_IBSS_RSN +NEED_RSN_AUTHENTICATOR=y +CFLAGS += -DCONFIG_IBSS_RSN +CFLAGS += -DCONFIG_NO_VLAN +OBJS += ibss_rsn.o +endif + +ifdef CONFIG_MATCH_IFACE +CFLAGS += -DCONFIG_MATCH_IFACE +endif + +ifdef CONFIG_P2P +OBJS += p2p_supplicant.o +OBJS += p2p_supplicant_sd.o +OBJS += ../src/p2p/p2p.o +OBJS += ../src/p2p/p2p_utils.o +OBJS += ../src/p2p/p2p_parse.o +OBJS += ../src/p2p/p2p_build.o +OBJS += ../src/p2p/p2p_go_neg.o +OBJS += ../src/p2p/p2p_sd.o +OBJS += ../src/p2p/p2p_pd.o +OBJS += ../src/p2p/p2p_invitation.o +OBJS += ../src/p2p/p2p_dev_disc.o +OBJS += ../src/p2p/p2p_group.o +OBJS += ../src/ap/p2p_hostapd.o +CFLAGS += -DCONFIG_P2P +NEED_GAS=y +NEED_OFFCHANNEL=y +CONFIG_WPS=y +CONFIG_AP=y +ifdef CONFIG_P2P_STRICT +CFLAGS += -DCONFIG_P2P_STRICT +endif +ifdef CONFIG_WIFI_DISPLAY +CFLAGS += -DCONFIG_WIFI_DISPLAY +OBJS += wifi_display.o +endif +endif + +ifdef CONFIG_PASN +CFLAGS += -DCONFIG_PASN +CFLAGS += -DCONFIG_PTKSA_CACHE +NEED_HMAC_SHA256_KDF=y +NEED_HMAC_SHA384_KDF=y +NEED_SHA256=y +NEED_SHA384=y +OBJS += ../src/common/ptksa_cache.o +OBJS += pasn_supplicant.o +endif + +ifdef CONFIG_HS20 +OBJS += hs20_supplicant.o +CFLAGS += -DCONFIG_HS20 +CONFIG_INTERWORKING=y +endif + +ifdef CONFIG_INTERWORKING +OBJS += interworking.o +CFLAGS += -DCONFIG_INTERWORKING +NEED_GAS=y +endif + +ifdef CONFIG_NO_ROAMING +CFLAGS += -DCONFIG_NO_ROAMING +endif + +include ../src/drivers/drivers.mak +ifdef CONFIG_AP +OBJS_d += $(DRV_BOTH_OBJS) +CFLAGS += $(DRV_BOTH_CFLAGS) +LDFLAGS += $(DRV_BOTH_LDFLAGS) +LIBS += $(DRV_BOTH_LIBS) +else +NEED_AP_MLME= +OBJS_d += $(DRV_WPA_OBJS) +CFLAGS += $(DRV_WPA_CFLAGS) +LDFLAGS += $(DRV_WPA_LDFLAGS) +LIBS += $(DRV_WPA_LIBS) +endif + +ifndef CONFIG_L2_PACKET +CONFIG_L2_PACKET=linux +endif + +OBJS_l2 += ../src/l2_packet/l2_packet_$(CONFIG_L2_PACKET).o + +ifeq ($(CONFIG_L2_PACKET), pcap) +ifdef CONFIG_WINPCAP +CFLAGS += -DCONFIG_WINPCAP +LIBS += -lwpcap -lpacket +LIBS_w += -lwpcap +else +LIBS += -ldnet -lpcap +endif +endif + +ifeq ($(CONFIG_L2_PACKET), winpcap) +LIBS += -lwpcap -lpacket +LIBS_w += -lwpcap +endif + +ifeq ($(CONFIG_L2_PACKET), freebsd) +LIBS += -lpcap +endif + +ifdef CONFIG_ERP +CFLAGS += -DCONFIG_ERP +NEED_HMAC_SHA256_KDF=y +endif + +ifdef CONFIG_EAP_TLS +# EAP-TLS +ifeq ($(CONFIG_EAP_TLS), dyn) +CFLAGS += -DEAP_TLS_DYNAMIC +EAPDYN += eap_tls.so +else +CFLAGS += -DEAP_TLS +OBJS += ../src/eap_peer/eap_tls.o +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_UNAUTH_TLS +# EAP-UNAUTH-TLS +CFLAGS += -DEAP_UNAUTH_TLS +ifndef CONFIG_EAP_TLS +OBJS += ../src/eap_peer/eap_tls.o +TLS_FUNCS=y +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_PEAP +# EAP-PEAP +SRC_EAP_PEAP = ../src/eap_peer/eap_peap.c ../src/eap_common/eap_peap_common.c +ifeq ($(CONFIG_EAP_PEAP), dyn) +CFLAGS += -DEAP_PEAP_DYNAMIC +EAPDYN += eap_peap.so +else +CFLAGS += -DEAP_PEAP +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_PEAP)) +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_TTLS +# EAP-TTLS +ifeq ($(CONFIG_EAP_TTLS), dyn) +CFLAGS += -DEAP_TTLS_DYNAMIC +EAPDYN += eap_ttls.so +else +CFLAGS += -DEAP_TTLS +OBJS += ../src/eap_peer/eap_ttls.o +endif +TLS_FUNCS=y +ifndef CONFIG_FIPS +MS_FUNCS=y +CHAP=y +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_MD5 +# EAP-MD5 +ifeq ($(CONFIG_EAP_MD5), dyn) +CFLAGS += -DEAP_MD5_DYNAMIC +EAPDYN += eap_md5.so +else +CFLAGS += -DEAP_MD5 +OBJS += ../src/eap_peer/eap_md5.o +endif +CHAP=y +CONFIG_IEEE8021X_EAPOL=y +endif + +# backwards compatibility for old spelling +ifdef CONFIG_MSCHAPV2 +ifndef CONFIG_EAP_MSCHAPV2 +CONFIG_EAP_MSCHAPV2=y +endif +endif + +ifdef CONFIG_EAP_MSCHAPV2 +# EAP-MSCHAPv2 +SRC_EAP_MSCHAPV2 = ../src/eap_peer/eap_mschapv2.c ../src/eap_peer/mschapv2.c +ifeq ($(CONFIG_EAP_MSCHAPV2), dyn) +CFLAGS += -DEAP_MSCHAPv2_DYNAMIC +EAPDYN += eap_mschapv2.so +else +CFLAGS += -DEAP_MSCHAPv2 +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_MSCHAPV2)) +endif +MS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_GTC +# EAP-GTC +ifeq ($(CONFIG_EAP_GTC), dyn) +CFLAGS += -DEAP_GTC_DYNAMIC +EAPDYN += eap_gtc.so +else +CFLAGS += -DEAP_GTC +OBJS += ../src/eap_peer/eap_gtc.o +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_OTP +# EAP-OTP +ifeq ($(CONFIG_EAP_OTP), dyn) +CFLAGS += -DEAP_OTP_DYNAMIC +EAPDYN += eap_otp.so +else +CFLAGS += -DEAP_OTP +OBJS += ../src/eap_peer/eap_otp.o +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_SIM +# EAP-SIM +ifeq ($(CONFIG_EAP_SIM), dyn) +CFLAGS += -DEAP_SIM_DYNAMIC +EAPDYN += eap_sim.so +else +CFLAGS += -DEAP_SIM +OBJS += ../src/eap_peer/eap_sim.o +endif +CONFIG_IEEE8021X_EAPOL=y +CONFIG_EAP_SIM_COMMON=y +NEED_AES_CBC=y +endif + +ifdef CONFIG_EAP_LEAP +# EAP-LEAP +ifeq ($(CONFIG_EAP_LEAP), dyn) +CFLAGS += -DEAP_LEAP_DYNAMIC +EAPDYN += eap_leap.so +else +CFLAGS += -DEAP_LEAP +OBJS += ../src/eap_peer/eap_leap.o +endif +MS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_PSK +# EAP-PSK +SRC_EAP_PSK = ../src/eap_peer/eap_psk.c ../src/eap_common/eap_psk_common.c +ifeq ($(CONFIG_EAP_PSK), dyn) +CFLAGS += -DEAP_PSK_DYNAMIC +EAPDYN += eap_psk.so +else +CFLAGS += -DEAP_PSK +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_PSK)) +endif +CONFIG_IEEE8021X_EAPOL=y +NEED_AES=y +NEED_AES_ENCBLOCK=y +NEED_AES_EAX=y +endif + +ifdef CONFIG_EAP_AKA +# EAP-AKA +ifeq ($(CONFIG_EAP_AKA), dyn) +CFLAGS += -DEAP_AKA_DYNAMIC +EAPDYN += eap_aka.so +else +CFLAGS += -DEAP_AKA +OBJS += ../src/eap_peer/eap_aka.o +endif +CONFIG_IEEE8021X_EAPOL=y +CONFIG_EAP_SIM_COMMON=y +NEED_AES_CBC=y +endif + +ifdef CONFIG_EAP_PROXY +CFLAGS += -DCONFIG_EAP_PROXY +OBJS += ../src/eap_peer/eap_proxy_$(CONFIG_EAP_PROXY).o +include eap_proxy_$(CONFIG_EAP_PROXY).mak +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_AKA_PRIME +# EAP-AKA' +ifeq ($(CONFIG_EAP_AKA_PRIME), dyn) +CFLAGS += -DEAP_AKA_PRIME_DYNAMIC +else +CFLAGS += -DEAP_AKA_PRIME +endif +endif + +ifdef CONFIG_EAP_SIM_COMMON +OBJS += ../src/eap_common/eap_sim_common.o +NEED_AES=y +NEED_FIPS186_2_PRF=y +endif + +ifdef CONFIG_EAP_FAST +# EAP-FAST +SRC_EAP_FAST = ../src/eap_peer/eap_fast.c ../src/eap_peer/eap_fast_pac.c +SRC_EAP_FAST += ../src/eap_common/eap_fast_common.c +ifeq ($(CONFIG_EAP_FAST), dyn) +CFLAGS += -DEAP_FAST_DYNAMIC +EAPDYN += eap_fast.so +else +CFLAGS += -DEAP_FAST +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_FAST)) +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +NEED_T_PRF=y +endif + +ifdef CONFIG_EAP_TEAP +# EAP-TEAP +SRC_EAP_TEAP = ../src/eap_peer/eap_teap.c ../src/eap_peer/eap_teap_pac.c +SRC_EAP_TEAP += ../src/eap_common/eap_teap_common.c +ifeq ($(CONFIG_EAP_TEAP), dyn) +CFLAGS += -DEAP_TEAP_DYNAMIC +EAPDYN += eap_teap.so +else +CFLAGS += -DEAP_TEAP +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_TEAP)) +endif +TLS_FUNCS=y +CONFIG_IEEE8021X_EAPOL=y +NEED_T_PRF=y +NEED_SHA384=y +NEED_TLS_PRF_SHA256=y +NEED_TLS_PRF_SHA384=y +endif + +ifdef CONFIG_EAP_PAX +# EAP-PAX +SRC_EAP_PAX = ../src/eap_peer/eap_pax.c ../src/eap_common/eap_pax_common.c +ifeq ($(CONFIG_EAP_PAX), dyn) +CFLAGS += -DEAP_PAX_DYNAMIC +EAPDYN += eap_pax.so +else +CFLAGS += -DEAP_PAX +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_PAX)) +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_SAKE +# EAP-SAKE +SRC_EAP_SAKE = ../src/eap_peer/eap_sake.c ../src/eap_common/eap_sake_common.c +ifeq ($(CONFIG_EAP_SAKE), dyn) +CFLAGS += -DEAP_SAKE_DYNAMIC +EAPDYN += eap_sake.so +else +CFLAGS += -DEAP_SAKE +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_SAKE)) +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_GPSK +# EAP-GPSK +SRC_EAP_GPSK = ../src/eap_peer/eap_gpsk.c ../src/eap_common/eap_gpsk_common.c +ifeq ($(CONFIG_EAP_GPSK), dyn) +CFLAGS += -DEAP_GPSK_DYNAMIC +EAPDYN += eap_gpsk.so +else +CFLAGS += -DEAP_GPSK +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_GPSK)) +endif +CONFIG_IEEE8021X_EAPOL=y +ifdef CONFIG_EAP_GPSK_SHA256 +CFLAGS += -DEAP_GPSK_SHA256 +endif +endif + +ifdef CONFIG_EAP_PWD +CFLAGS += -DEAP_PWD +ifeq ($(CONFIG_TLS), wolfssl) +CFLAGS += -DCONFIG_ECC +endif +OBJS += ../src/eap_peer/eap_pwd.o ../src/eap_common/eap_pwd_common.o +CONFIG_IEEE8021X_EAPOL=y +NEED_ECC=y +NEED_DRAGONFLY=y +endif + +ifdef CONFIG_EAP_EKE +# EAP-EKE +SRC_EAP_EKE = ../src/eap_peer/eap_eke.c ../src/eap_common/eap_eke_common.c +ifeq ($(CONFIG_EAP_EKE), dyn) +CFLAGS += -DEAP_EKE_DYNAMIC +EAPDYN += eap_eke.so +else +CFLAGS += -DEAP_EKE +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_EKE)) +endif +CONFIG_IEEE8021X_EAPOL=y +NEED_DH_GROUPS=y +NEED_DH_GROUPS_ALL=y +NEED_AES_CBC=y +endif + +ifdef CONFIG_WPS +# EAP-WSC +CFLAGS += -DCONFIG_WPS -DEAP_WSC +OBJS += wps_supplicant.o +OBJS += ../src/utils/uuid.o +OBJS += ../src/eap_peer/eap_wsc.o ../src/eap_common/eap_wsc_common.o +OBJS += ../src/wps/wps.o +OBJS += ../src/wps/wps_common.o +OBJS += ../src/wps/wps_attr_parse.o +OBJS += ../src/wps/wps_attr_build.o +OBJS += ../src/wps/wps_attr_process.o +OBJS += ../src/wps/wps_dev_attr.o +OBJS += ../src/wps/wps_enrollee.o +OBJS += ../src/wps/wps_registrar.o +CONFIG_IEEE8021X_EAPOL=y +NEED_DH_GROUPS=y +NEED_BASE64=y +NEED_AES_CBC=y +NEED_MODEXP=y + +ifdef CONFIG_WPS_NFC +CFLAGS += -DCONFIG_WPS_NFC +OBJS += ../src/wps/ndef.o +NEED_WPS_OOB=y +endif + +ifdef NEED_WPS_OOB +CFLAGS += -DCONFIG_WPS_OOB +endif + +ifdef CONFIG_WPS_ER +CONFIG_WPS_UPNP=y +CFLAGS += -DCONFIG_WPS_ER +OBJS += ../src/wps/wps_er.o +OBJS += ../src/wps/wps_er_ssdp.o +endif + +ifdef CONFIG_WPS_UPNP +CFLAGS += -DCONFIG_WPS_UPNP +OBJS += ../src/wps/wps_upnp.o +OBJS += ../src/wps/wps_upnp_ssdp.o +OBJS += ../src/wps/wps_upnp_web.o +OBJS += ../src/wps/wps_upnp_event.o +OBJS += ../src/wps/wps_upnp_ap.o +OBJS += ../src/wps/upnp_xml.o +OBJS += ../src/wps/httpread.o +OBJS += ../src/wps/http_client.o +OBJS += ../src/wps/http_server.o +endif + +ifdef CONFIG_WPS_STRICT +CFLAGS += -DCONFIG_WPS_STRICT +OBJS += ../src/wps/wps_validate.o +endif + +ifdef CONFIG_WPS_TESTING +CFLAGS += -DCONFIG_WPS_TESTING +endif + +ifdef CONFIG_WPS_REG_DISABLE_OPEN +CFLAGS += -DCONFIG_WPS_REG_DISABLE_OPEN +endif + +endif + +ifdef CONFIG_EAP_IKEV2 +# EAP-IKEv2 +SRC_EAP_IKEV2 = ../src/eap_peer/eap_ikev2.c +SRC_EAP_IKEV2 += ../src/eap_peer/ikev2.c +SRC_EAP_IKEV2 += ../src/eap_common/eap_ikev2_common.c +SRC_EAP_IKEV2 += ../src/eap_common/ikev2_common.c +ifeq ($(CONFIG_EAP_IKEV2), dyn) +CFLAGS += -DEAP_IKEV2_DYNAMIC +EAPDYN += eap_ikev2.so +else +CFLAGS += -DEAP_IKEV2 +OBJS += $(patsubst %.c, %.o, $(SRC_EAP_IKEV2)) +endif +CONFIG_IEEE8021X_EAPOL=y +NEED_DH_GROUPS=y +NEED_DH_GROUPS_ALL=y +NEED_MODEXP=y +NEED_CIPHER=y +endif + +ifdef CONFIG_EAP_VENDOR_TEST +ifeq ($(CONFIG_EAP_VENDOR_TEST), dyn) +CFLAGS += -DEAP_VENDOR_TEST_DYNAMIC +EAPDYN += eap_vendor_test.so +else +CFLAGS += -DEAP_VENDOR_TEST +OBJS += ../src/eap_peer/eap_vendor_test.o +endif +CONFIG_IEEE8021X_EAPOL=y +endif + +ifdef CONFIG_EAP_TNC +# EAP-TNC +CFLAGS += -DEAP_TNC +OBJS += ../src/eap_peer/eap_tnc.o +OBJS += ../src/eap_peer/tncc.o +NEED_BASE64=y +ifndef CONFIG_NATIVE_WINDOWS +ifndef CONFIG_DRIVER_BSD +LIBS += -ldl +endif +endif +endif + +ifdef CONFIG_MACSEC +CFLAGS += -DCONFIG_MACSEC +CONFIG_IEEE8021X_EAPOL=y +NEED_AES_ENCBLOCK=y +NEED_AES_UNWRAP=y +NEED_AES_WRAP=y +OBJS += wpas_kay.o +OBJS += ../src/pae/ieee802_1x_cp.o +OBJS += ../src/pae/ieee802_1x_kay.o +OBJS += ../src/pae/ieee802_1x_key.o +OBJS += ../src/pae/ieee802_1x_secy_ops.o +ifdef CONFIG_AP +OBJS += ../src/ap/wpa_auth_kay.o +endif +endif + +ifdef CONFIG_IEEE8021X_EAPOL +# IEEE 802.1X/EAPOL state machines (e.g., for RADIUS authentication) +CFLAGS += -DIEEE8021X_EAPOL +OBJS += ../src/eapol_supp/eapol_supp_sm.o +OBJS += ../src/eap_peer/eap.o ../src/eap_peer/eap_methods.o +NEED_EAP_COMMON=y +ifdef CONFIG_DYNAMIC_EAP_METHODS +CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS +LIBS += -ldl -rdynamic +endif +endif + +ifdef CONFIG_AP +NEED_EAP_COMMON=y +NEED_RSN_AUTHENTICATOR=y +CFLAGS += -DCONFIG_AP +OBJS += ap.o +CFLAGS += -DCONFIG_NO_RADIUS +CFLAGS += -DCONFIG_NO_ACCOUNTING +CFLAGS += -DCONFIG_NO_VLAN +OBJS += ../src/ap/hostapd.o +OBJS += ../src/ap/wpa_auth_glue.o +OBJS += ../src/ap/utils.o +OBJS += ../src/ap/authsrv.o +OBJS += ../src/ap/ap_config.o +OBJS += ../src/ap/sta_info.o +OBJS += ../src/ap/tkip_countermeasures.o +OBJS += ../src/ap/ap_mlme.o +OBJS += ../src/ap/ieee802_1x.o +OBJS += ../src/eapol_auth/eapol_auth_sm.o +OBJS += ../src/ap/ieee802_11_auth.o +OBJS += ../src/ap/ieee802_11_shared.o +OBJS += ../src/ap/drv_callbacks.o +OBJS += ../src/ap/ap_drv_ops.o +OBJS += ../src/ap/beacon.o +OBJS += ../src/ap/bss_load.o +OBJS += ../src/ap/eap_user_db.o +OBJS += ../src/ap/neighbor_db.o +OBJS += ../src/ap/rrm.o +OBJS += ../src/ap/ieee802_11_ht.o +ifdef CONFIG_IEEE80211AC +OBJS += ../src/ap/ieee802_11_vht.o +endif +ifdef CONFIG_IEEE80211AX +OBJS += ../src/ap/ieee802_11_he.o +endif +ifdef CONFIG_WNM_AP +CFLAGS += -DCONFIG_WNM_AP +OBJS += ../src/ap/wnm_ap.o +endif +ifdef CONFIG_MBO +OBJS += ../src/ap/mbo_ap.o +endif +ifdef CONFIG_FILS +OBJS += ../src/ap/fils_hlp.o +endif +ifdef CONFIG_CTRL_IFACE +OBJS += ../src/ap/ctrl_iface_ap.o +endif + +CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY +OBJS += ../src/eap_server/eap_server.o +OBJS += ../src/eap_server/eap_server_identity.o +OBJS += ../src/eap_server/eap_server_methods.o + +ifdef CONFIG_IEEE80211AC +CFLAGS += -DCONFIG_IEEE80211AC +endif +ifdef CONFIG_IEEE80211AX +CFLAGS += -DCONFIG_IEEE80211AX +endif + +ifdef NEED_AP_MLME +OBJS += ../src/ap/wmm.o +OBJS += ../src/ap/ap_list.o +OBJS += ../src/ap/ieee802_11.o +OBJS += ../src/ap/hw_features.o +OBJS += ../src/ap/dfs.o +CFLAGS += -DNEED_AP_MLME +endif +ifdef CONFIG_WPS +CFLAGS += -DEAP_SERVER_WSC +OBJS += ../src/ap/wps_hostapd.o +OBJS += ../src/eap_server/eap_server_wsc.o +endif +ifdef CONFIG_DPP +OBJS += ../src/ap/dpp_hostapd.o +OBJS += ../src/ap/gas_query_ap.o +NEED_AP_GAS_SERV=y +endif +ifdef CONFIG_INTERWORKING +NEED_AP_GAS_SERV=y +endif +ifdef NEED_AP_GAS_SERV +OBJS += ../src/ap/gas_serv.o +endif +ifdef CONFIG_HS20 +OBJS += ../src/ap/hs20.o +endif +endif + +ifdef CONFIG_MBO +OBJS += mbo.o +CFLAGS += -DCONFIG_MBO +endif + +ifdef NEED_RSN_AUTHENTICATOR +CFLAGS += -DCONFIG_NO_RADIUS +NEED_AES_WRAP=y +OBJS += ../src/ap/wpa_auth.o +OBJS += ../src/ap/wpa_auth_ie.o +OBJS += ../src/ap/pmksa_cache_auth.o +endif + +ifdef CONFIG_ACS +CFLAGS += -DCONFIG_ACS +OBJS += ../src/ap/acs.o +LIBS += -lm +endif + +ifdef CONFIG_PCSC +# PC/SC interface for smartcards (USIM, GSM SIM) +CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC +OBJS += ../src/utils/pcsc_funcs.o +ifdef CONFIG_NATIVE_WINDOWS +#Once MinGW gets support for WinScard, -lwinscard could be used instead of the +#dynamic symbol loading that is now used in pcsc_funcs.c +#LIBS += -lwinscard +else +ifdef CONFIG_OSX +LIBS += -framework PCSC +else +LIBS += $(shell $(PKG_CONFIG) --libs libpcsclite) +endif +endif +endif + +ifdef CONFIG_SIM_SIMULATOR +CFLAGS += -DCONFIG_SIM_SIMULATOR +NEED_MILENAGE=y +endif + +ifdef CONFIG_USIM_SIMULATOR +CFLAGS += -DCONFIG_USIM_SIMULATOR +NEED_MILENAGE=y +endif + +ifdef NEED_MILENAGE +OBJS += ../src/crypto/milenage.o +NEED_AES_ENCBLOCK=y +endif + +ifdef CONFIG_PKCS12 +CFLAGS += -DPKCS12_FUNCS +endif + +ifdef CONFIG_SMARTCARD +CFLAGS += -DCONFIG_SMARTCARD +endif + +ifdef NEED_DRAGONFLY +OBJS += ../src/common/dragonfly.o +endif + +ifdef MS_FUNCS +OBJS += ../src/crypto/ms_funcs.o +NEED_DES=y +NEED_MD4=y +endif + +ifdef CHAP +OBJS += ../src/eap_common/chap.o +endif + +ifdef TLS_FUNCS +NEED_DES=y +# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, EAP_TTLS, EAP_FAST, and +# EAP_TEAP) +OBJS += ../src/eap_peer/eap_tls_common.o +ifndef CONFIG_FIPS +NEED_TLS_PRF=y +NEED_SHA1=y +NEED_MD5=y +endif +endif + +ifndef CONFIG_TLS +CONFIG_TLS=openssl +endif + +ifdef CONFIG_TLSV11 +CFLAGS += -DCONFIG_TLSV11 +endif + +ifdef CONFIG_TLSV12 +CFLAGS += -DCONFIG_TLSV12 +endif + +ifeq ($(CONFIG_TLS), wolfssl) +ifdef TLS_FUNCS +CFLAGS += -DWOLFSSL_DER_LOAD +OBJS += ../src/crypto/tls_wolfssl.o +endif +OBJS += ../src/crypto/crypto_wolfssl.o +OBJS_p += ../src/crypto/crypto_wolfssl.o +ifdef NEED_FIPS186_2_PRF +OBJS += ../src/crypto/fips_prf_wolfssl.o +endif +NEED_TLS_PRF_SHA256=y +LIBS += -lwolfssl -lm +LIBS_p += -lwolfssl -lm +endif + +ifeq ($(CONFIG_TLS), openssl) +ifdef TLS_FUNCS +CFLAGS += -DEAP_TLS_OPENSSL +OBJS += ../src/crypto/tls_openssl.o +OBJS += ../src/crypto/tls_openssl_ocsp.o +LIBS += -lssl +endif +OBJS += ../src/crypto/crypto_openssl.o +OBJS_p += ../src/crypto/crypto_openssl.o +OBJS_priv += ../src/crypto/crypto_openssl.o +ifdef NEED_FIPS186_2_PRF +OBJS += ../src/crypto/fips_prf_openssl.o +endif +NEED_TLS_PRF_SHA256=y +LIBS += -lcrypto +LIBS_p += -lcrypto +ifdef CONFIG_TLS_ADD_DL +LIBS += -ldl +LIBS_p += -ldl +endif +ifndef CONFIG_TLS_DEFAULT_CIPHERS +CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW" +endif +CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" +endif + +ifeq ($(CONFIG_TLS), gnutls) +ifndef CONFIG_CRYPTO +# default to libgcrypt +CONFIG_CRYPTO=gnutls +endif +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_gnutls.o +LIBS += -lgnutls -lgpg-error +endif +OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o +OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o +OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o +ifdef NEED_FIPS186_2_PRF +OBJS += ../src/crypto/fips_prf_internal.o +SHA1OBJS += ../src/crypto/sha1-internal.o +endif +ifeq ($(CONFIG_CRYPTO), gnutls) +LIBS += -lgcrypt +LIBS_p += -lgcrypt +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +ifeq ($(CONFIG_CRYPTO), nettle) +LIBS += -lnettle -lgmp +LIBS_p += -lnettle -lgmp +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +endif + +ifeq ($(CONFIG_TLS), internal) +ifndef CONFIG_CRYPTO +CONFIG_CRYPTO=internal +endif +ifdef TLS_FUNCS +OBJS += ../src/crypto/crypto_internal-rsa.o +OBJS += ../src/crypto/tls_internal.o +OBJS += ../src/tls/tlsv1_common.o +OBJS += ../src/tls/tlsv1_record.o +OBJS += ../src/tls/tlsv1_cred.o +OBJS += ../src/tls/tlsv1_client.o +OBJS += ../src/tls/tlsv1_client_write.o +OBJS += ../src/tls/tlsv1_client_read.o +OBJS += ../src/tls/tlsv1_client_ocsp.o +OBJS += ../src/tls/rsa.o +OBJS += ../src/tls/x509v3.o +OBJS += ../src/tls/pkcs1.o +OBJS += ../src/tls/pkcs5.o +OBJS += ../src/tls/pkcs8.o +NEED_ASN1=y +NEED_BASE64=y +NEED_TLS_PRF=y +ifdef CONFIG_TLSV12 +NEED_TLS_PRF_SHA256=y +endif +NEED_MODEXP=y +NEED_CIPHER=y +CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT +endif +ifdef NEED_CIPHER +NEED_DES=y +OBJS += ../src/crypto/crypto_internal-cipher.o +endif +ifdef NEED_MODEXP +OBJS += ../src/crypto/crypto_internal-modexp.o +OBJS += ../src/tls/bignum.o +endif +ifeq ($(CONFIG_CRYPTO), libtomcrypt) +OBJS += ../src/crypto/crypto_libtomcrypt.o +OBJS_p += ../src/crypto/crypto_libtomcrypt.o +LIBS += -ltomcrypt -ltfm +LIBS_p += -ltomcrypt -ltfm +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +ifeq ($(CONFIG_CRYPTO), internal) +OBJS += ../src/crypto/crypto_internal.o +OBJS_p += ../src/crypto/crypto_internal.o +NEED_AES_ENC=y +CFLAGS += -DCONFIG_CRYPTO_INTERNAL +ifdef CONFIG_INTERNAL_LIBTOMMATH +CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH +ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST +CFLAGS += -DLTM_FAST +endif +else +LIBS += -ltommath +LIBS_p += -ltommath +endif +CONFIG_INTERNAL_AES=y +CONFIG_INTERNAL_DES=y +CONFIG_INTERNAL_SHA1=y +CONFIG_INTERNAL_MD4=y +CONFIG_INTERNAL_MD5=y +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_SHA384=y +CONFIG_INTERNAL_SHA512=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +ifeq ($(CONFIG_CRYPTO), cryptoapi) +OBJS += ../src/crypto/crypto_cryptoapi.o +OBJS_p += ../src/crypto/crypto_cryptoapi.o +CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +endif +endif + +ifeq ($(CONFIG_TLS), linux) +OBJS += ../src/crypto/crypto_linux.o +OBJS_p += ../src/crypto/crypto_linux.o +ifdef TLS_FUNCS +OBJS += ../src/crypto/crypto_internal-rsa.o +OBJS += ../src/crypto/tls_internal.o +OBJS += ../src/tls/tlsv1_common.o +OBJS += ../src/tls/tlsv1_record.o +OBJS += ../src/tls/tlsv1_cred.o +OBJS += ../src/tls/tlsv1_client.o +OBJS += ../src/tls/tlsv1_client_write.o +OBJS += ../src/tls/tlsv1_client_read.o +OBJS += ../src/tls/tlsv1_client_ocsp.o +OBJS += ../src/tls/rsa.o +OBJS += ../src/tls/x509v3.o +OBJS += ../src/tls/pkcs1.o +OBJS += ../src/tls/pkcs5.o +OBJS += ../src/tls/pkcs8.o +NEED_ASN1=y +NEED_BASE64=y +NEED_TLS_PRF=y +ifdef CONFIG_TLSV12 +NEED_TLS_PRF_SHA256=y +endif +NEED_MODEXP=y +NEED_CIPHER=y +CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT +endif +ifdef NEED_MODEXP +OBJS += ../src/crypto/crypto_internal-modexp.o +OBJS += ../src/tls/bignum.o +CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH +CFLAGS += -DLTM_FAST +endif +CONFIG_INTERNAL_DH_GROUP5=y +ifdef NEED_FIPS186_2_PRF +OBJS += ../src/crypto/fips_prf_internal.o +OBJS += ../src/crypto/sha1-internal.o +endif +endif + +ifeq ($(CONFIG_TLS), none) +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_none.o +CFLAGS += -DEAP_TLS_NONE +CONFIG_INTERNAL_AES=y +CONFIG_INTERNAL_SHA1=y +CONFIG_INTERNAL_MD5=y +endif +OBJS += ../src/crypto/crypto_none.o +OBJS_p += ../src/crypto/crypto_none.o +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +endif + +ifdef TLS_FUNCS +ifdef CONFIG_SMARTCARD +ifndef CONFIG_NATIVE_WINDOWS +ifneq ($(CONFIG_L2_PACKET), freebsd) +LIBS += -ldl +endif +endif +endif +endif + +ifndef TLS_FUNCS +OBJS += ../src/crypto/tls_none.o +ifeq ($(CONFIG_TLS), internal) +CONFIG_INTERNAL_AES=y +CONFIG_INTERNAL_SHA1=y +CONFIG_INTERNAL_MD5=y +CONFIG_INTERNAL_RC4=y +endif +endif + +AESOBJS = # none so far (see below) +ifdef CONFIG_INTERNAL_AES +AESOBJS += ../src/crypto/aes-internal.o ../src/crypto/aes-internal-dec.o +endif + +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), wolfssl) +NEED_INTERNAL_AES_WRAP=y +endif +endif +ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP +# Seems to be needed at least with BoringSSL +NEED_INTERNAL_AES_WRAP=y +CFLAGS += -DCONFIG_OPENSSL_INTERNAL_AES_WRAP +endif +ifdef CONFIG_FIPS +# Have to use internal AES key wrap routines to use OpenSSL EVP since the +# OpenSSL AES_wrap_key()/AES_unwrap_key() API is not available in FIPS mode. +NEED_INTERNAL_AES_WRAP=y +endif + +ifdef NEED_INTERNAL_AES_WRAP +ifneq ($(CONFIG_TLS), linux) +AESOBJS += ../src/crypto/aes-unwrap.o +endif +endif +ifdef NEED_AES_EAX +AESOBJS += ../src/crypto/aes-eax.o +NEED_AES_CTR=y +endif +ifdef NEED_AES_SIV +AESOBJS += ../src/crypto/aes-siv.o +NEED_AES_CTR=y +endif +ifdef NEED_AES_CTR +AESOBJS += ../src/crypto/aes-ctr.o +endif +ifdef NEED_AES_ENCBLOCK +AESOBJS += ../src/crypto/aes-encblock.o +endif +NEED_AES_ENC=y +ifdef CONFIG_OPENSSL_CMAC +CFLAGS += -DCONFIG_OPENSSL_CMAC +else +ifneq ($(CONFIG_TLS), linux) +ifneq ($(CONFIG_TLS), wolfssl) +AESOBJS += ../src/crypto/aes-omac1.o +endif +endif +endif +ifdef NEED_AES_WRAP +NEED_AES_ENC=y +ifdef NEED_INTERNAL_AES_WRAP +AESOBJS += ../src/crypto/aes-wrap.o +endif +endif +ifdef NEED_AES_CBC +NEED_AES_ENC=y +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), linux) +ifneq ($(CONFIG_TLS), wolfssl) +AESOBJS += ../src/crypto/aes-cbc.o +endif +endif +endif +endif +ifdef NEED_AES_ENC +ifdef CONFIG_INTERNAL_AES +AESOBJS += ../src/crypto/aes-internal-enc.o +endif +endif +ifdef NEED_AES +OBJS += $(AESOBJS) +endif + +ifdef NEED_SHA1 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), linux) +ifneq ($(CONFIG_TLS), gnutls) +ifneq ($(CONFIG_TLS), wolfssl) +SHA1OBJS += ../src/crypto/sha1.o +endif +endif +endif +endif +SHA1OBJS += ../src/crypto/sha1-prf.o +ifdef CONFIG_INTERNAL_SHA1 +SHA1OBJS += ../src/crypto/sha1-internal.o +ifdef NEED_FIPS186_2_PRF +SHA1OBJS += ../src/crypto/fips_prf_internal.o +endif +endif +ifdef CONFIG_NO_WPA_PASSPHRASE +CFLAGS += -DCONFIG_NO_PBKDF2 +else +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), wolfssl) +SHA1OBJS += ../src/crypto/sha1-pbkdf2.o +endif +endif +endif +ifdef NEED_T_PRF +SHA1OBJS += ../src/crypto/sha1-tprf.o +endif +ifdef NEED_TLS_PRF +SHA1OBJS += ../src/crypto/sha1-tlsprf.o +endif +endif + +ifndef CONFIG_FIPS +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), linux) +ifneq ($(CONFIG_TLS), gnutls) +ifneq ($(CONFIG_TLS), wolfssl) +MD5OBJS += ../src/crypto/md5.o +endif +endif +endif +endif +endif +ifdef NEED_MD5 +ifdef CONFIG_INTERNAL_MD5 +MD5OBJS += ../src/crypto/md5-internal.o +endif +OBJS += $(MD5OBJS) +OBJS_p += $(MD5OBJS) +OBJS_priv += $(MD5OBJS) +endif + +ifdef NEED_MD4 +ifdef CONFIG_INTERNAL_MD4 +OBJS += ../src/crypto/md4-internal.o +endif +endif + +DESOBJS = # none needed when not internal +ifdef NEED_DES +ifndef CONFIG_FIPS +CFLAGS += -DCONFIG_DES +endif +ifdef CONFIG_INTERNAL_DES +DESOBJS += ../src/crypto/des-internal.o +endif +endif + +ifdef CONFIG_NO_RC4 +CFLAGS += -DCONFIG_NO_RC4 +endif + +ifdef NEED_RC4 +ifdef CONFIG_INTERNAL_RC4 +ifndef CONFIG_NO_RC4 +OBJS += ../src/crypto/rc4.o +endif +endif +endif + +SHA256OBJS = # none by default +CFLAGS += -DCONFIG_SHA256 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), linux) +ifneq ($(CONFIG_TLS), gnutls) +ifneq ($(CONFIG_TLS), wolfssl) +SHA256OBJS += ../src/crypto/sha256.o +endif +endif +endif +endif +SHA256OBJS += ../src/crypto/sha256-prf.o +ifdef CONFIG_INTERNAL_SHA256 +SHA256OBJS += ../src/crypto/sha256-internal.o +endif +ifdef CONFIG_INTERNAL_SHA384 +CFLAGS += -DCONFIG_INTERNAL_SHA384 +SHA256OBJS += ../src/crypto/sha384-internal.o +endif +ifdef CONFIG_INTERNAL_SHA512 +CFLAGS += -DCONFIG_INTERNAL_SHA512 +SHA256OBJS += ../src/crypto/sha512-internal.o +endif +ifdef NEED_TLS_PRF_SHA256 +SHA256OBJS += ../src/crypto/sha256-tlsprf.o +endif +ifdef NEED_TLS_PRF_SHA384 +SHA256OBJS += ../src/crypto/sha384-tlsprf.o +endif +ifdef NEED_HMAC_SHA256_KDF +CFLAGS += -DCONFIG_HMAC_SHA256_KDF +OBJS += ../src/crypto/sha256-kdf.o +endif +ifdef NEED_HMAC_SHA384_KDF +CFLAGS += -DCONFIG_HMAC_SHA384_KDF +OBJS += ../src/crypto/sha384-kdf.o +endif +ifdef NEED_HMAC_SHA512_KDF +CFLAGS += -DCONFIG_HMAC_SHA512_KDF +OBJS += ../src/crypto/sha512-kdf.o +endif +OBJS += $(SHA256OBJS) +ifdef NEED_SHA384 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), linux) +ifneq ($(CONFIG_TLS), gnutls) +ifneq ($(CONFIG_TLS), wolfssl) +OBJS += ../src/crypto/sha384.o +endif +endif +endif +endif +CFLAGS += -DCONFIG_SHA384 +OBJS += ../src/crypto/sha384-prf.o +endif +ifdef NEED_SHA512 +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), linux) +ifneq ($(CONFIG_TLS), gnutls) +ifneq ($(CONFIG_TLS), wolfssl) +OBJS += ../src/crypto/sha512.o +endif +endif +endif +endif +CFLAGS += -DCONFIG_SHA512 +OBJS += ../src/crypto/sha512-prf.o +endif + +ifdef NEED_ASN1 +OBJS += ../src/tls/asn1.o +endif + +ifdef NEED_DH_GROUPS +OBJS += ../src/crypto/dh_groups.o +endif +ifdef NEED_DH_GROUPS_ALL +CFLAGS += -DALL_DH_GROUPS +endif +ifdef CONFIG_INTERNAL_DH_GROUP5 +ifdef NEED_DH_GROUPS +OBJS += ../src/crypto/dh_group5.o +endif +endif + +ifdef NEED_ECC +CFLAGS += -DCONFIG_ECC +endif + +ifdef CONFIG_NO_RANDOM_POOL +CFLAGS += -DCONFIG_NO_RANDOM_POOL +else +ifdef CONFIG_GETRANDOM +CFLAGS += -DCONFIG_GETRANDOM +endif +OBJS += ../src/crypto/random.o +endif + +ifdef CONFIG_CTRL_IFACE +ifeq ($(CONFIG_CTRL_IFACE), y) +ifdef CONFIG_NATIVE_WINDOWS +CONFIG_CTRL_IFACE=named_pipe +else +CONFIG_CTRL_IFACE=unix +endif +endif +CFLAGS += -DCONFIG_CTRL_IFACE +ifeq ($(CONFIG_CTRL_IFACE), unix) +CFLAGS += -DCONFIG_CTRL_IFACE_UNIX +OBJS += ../src/common/ctrl_iface_common.o +endif +ifeq ($(CONFIG_CTRL_IFACE), udp) +CFLAGS += -DCONFIG_CTRL_IFACE_UDP +endif +ifeq ($(CONFIG_CTRL_IFACE), udp6) +CONFIG_CTRL_IFACE=udp +CFLAGS += -DCONFIG_CTRL_IFACE_UDP +CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6 +endif +ifeq ($(CONFIG_CTRL_IFACE), named_pipe) +CFLAGS += -DCONFIG_CTRL_IFACE_NAMED_PIPE +endif +ifeq ($(CONFIG_CTRL_IFACE), udp-remote) +CONFIG_CTRL_IFACE=udp +CFLAGS += -DCONFIG_CTRL_IFACE_UDP +CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE +endif +ifeq ($(CONFIG_CTRL_IFACE), udp6-remote) +CONFIG_CTRL_IFACE=udp +CFLAGS += -DCONFIG_CTRL_IFACE_UDP +CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE +CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6 +endif +OBJS += ctrl_iface.o ctrl_iface_$(CONFIG_CTRL_IFACE).o +endif + +ifdef CONFIG_CTRL_IFACE_DBUS_NEW +CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW +OBJS += dbus/dbus_dict_helpers.o +OBJS += dbus/dbus_new_helpers.o +OBJS += dbus/dbus_new.o dbus/dbus_new_handlers.o +OBJS += dbus/dbus_common.o +ifdef CONFIG_WPS +OBJS += dbus/dbus_new_handlers_wps.o +endif +ifdef CONFIG_P2P +OBJS += dbus/dbus_new_handlers_p2p.o +endif +ifndef DBUS_LIBS +DBUS_LIBS := $(shell $(PKG_CONFIG) --libs dbus-1) +endif +ifndef DBUS_INCLUDE +DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1) +endif +ifdef CONFIG_CTRL_IFACE_DBUS_INTRO +OBJS += dbus/dbus_new_introspect.o +CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO +endif +CFLAGS += $(DBUS_INCLUDE) +LIBS += $(DBUS_LIBS) +endif + +ifdef CONFIG_READLINE +OBJS_c += ../src/utils/edit_readline.o +LIBS_c += -lreadline -lncurses +else +ifdef CONFIG_WPA_CLI_EDIT +OBJS_c += ../src/utils/edit.o +else +OBJS_c += ../src/utils/edit_simple.o +endif +endif + +ifdef CONFIG_NATIVE_WINDOWS +CFLAGS += -DCONFIG_NATIVE_WINDOWS +LIBS += -lws2_32 -lgdi32 -lcrypt32 +LIBS_c += -lws2_32 +LIBS_p += -lws2_32 -lgdi32 +ifeq ($(CONFIG_CRYPTO), cryptoapi) +LIBS_p += -lcrypt32 +endif +endif + +ifdef CONFIG_NO_STDOUT_DEBUG +CFLAGS += -DCONFIG_NO_STDOUT_DEBUG +ifndef CONFIG_CTRL_IFACE +CFLAGS += -DCONFIG_NO_WPA_MSG +endif +endif + +ifdef CONFIG_IPV6 +# for eapol_test only +CFLAGS += -DCONFIG_IPV6 +endif + +ifdef CONFIG_NO_LINUX_PACKET_SOCKET_WAR +CFLAGS += -DCONFIG_NO_LINUX_PACKET_SOCKET_WAR +endif + +ifdef NEED_BASE64 +OBJS += ../src/utils/base64.o +endif + +ifdef NEED_SME +OBJS += sme.o +CFLAGS += -DCONFIG_SME +endif + +OBJS += ../src/common/ieee802_11_common.o +OBJS += ../src/common/hw_features_common.o + +ifdef NEED_EAP_COMMON +OBJS += ../src/eap_common/eap_common.o +endif + +ifndef CONFIG_MAIN +CONFIG_MAIN=main +endif + +ifdef CONFIG_DEBUG_SYSLOG +CFLAGS += -DCONFIG_DEBUG_SYSLOG +ifdef CONFIG_DEBUG_SYSLOG_FACILITY +CFLAGS += -DLOG_HOSTAPD="$(CONFIG_DEBUG_SYSLOG_FACILITY)" +endif +endif + +ifdef CONFIG_DEBUG_LINUX_TRACING +CFLAGS += -DCONFIG_DEBUG_LINUX_TRACING +endif + +ifdef CONFIG_DEBUG_FILE +CFLAGS += -DCONFIG_DEBUG_FILE +endif + +ifdef CONFIG_DELAYED_MIC_ERROR_REPORT +CFLAGS += -DCONFIG_DELAYED_MIC_ERROR_REPORT +endif + +ifdef CONFIG_FIPS +CFLAGS += -DCONFIG_FIPS +ifneq ($(CONFIG_TLS), openssl) +ifneq ($(CONFIG_TLS), wolfssl) +$(error CONFIG_FIPS=y requires CONFIG_TLS=openssl) +endif +endif +endif + +OBJS += $(SHA1OBJS) $(DESOBJS) + +OBJS_p += $(SHA1OBJS) +OBJS_p += $(SHA256OBJS) +OBJS_priv += $(SHA1OBJS) + +ifdef CONFIG_BGSCAN_SIMPLE +CFLAGS += -DCONFIG_BGSCAN_SIMPLE +OBJS += bgscan_simple.o +NEED_BGSCAN=y +endif + +ifdef CONFIG_BGSCAN_LEARN +CFLAGS += -DCONFIG_BGSCAN_LEARN +OBJS += bgscan_learn.o +NEED_BGSCAN=y +endif + +ifdef NEED_BGSCAN +CFLAGS += -DCONFIG_BGSCAN +OBJS += bgscan.o +endif + +ifdef CONFIG_AUTOSCAN_EXPONENTIAL +CFLAGS += -DCONFIG_AUTOSCAN_EXPONENTIAL +OBJS += autoscan_exponential.o +NEED_AUTOSCAN=y +endif + +ifdef CONFIG_AUTOSCAN_PERIODIC +CFLAGS += -DCONFIG_AUTOSCAN_PERIODIC +OBJS += autoscan_periodic.o +NEED_AUTOSCAN=y +endif + +ifdef NEED_AUTOSCAN +CFLAGS += -DCONFIG_AUTOSCAN +OBJS += autoscan.o +endif + +ifdef CONFIG_EXT_PASSWORD_TEST +OBJS += ../src/utils/ext_password_test.o +CFLAGS += -DCONFIG_EXT_PASSWORD_TEST +NEED_EXT_PASSWORD=y +endif + +ifdef CONFIG_EXT_PASSWORD_FILE +OBJS += ../src/utils/ext_password_file.o +CFLAGS += -DCONFIG_EXT_PASSWORD_FILE +NEED_EXT_PASSWORD=y +endif + +ifdef NEED_EXT_PASSWORD +OBJS += ../src/utils/ext_password.o +CFLAGS += -DCONFIG_EXT_PASSWORD +endif + +ifdef NEED_GAS_SERVER +OBJS += ../src/common/gas_server.o +CFLAGS += -DCONFIG_GAS_SERVER +NEED_GAS=y +endif + +ifdef NEED_GAS +OBJS += ../src/common/gas.o +OBJS += gas_query.o +CFLAGS += -DCONFIG_GAS +NEED_OFFCHANNEL=y +endif + +ifdef NEED_OFFCHANNEL +OBJS += offchannel.o +CFLAGS += -DCONFIG_OFFCHANNEL +endif + +ifdef NEED_JSON +OBJS += ../src/utils/json.o +CFLAGS += -DCONFIG_JSON +endif + +ifdef CONFIG_MODULE_TESTS +CFLAGS += -DCONFIG_MODULE_TESTS +OBJS += wpas_module_tests.o +OBJS += ../src/utils/utils_module_tests.o +OBJS += ../src/common/common_module_tests.o +OBJS += ../src/crypto/crypto_module_tests.o +ifdef CONFIG_WPS +OBJS += ../src/wps/wps_module_tests.o +endif +endif + +OBJS += ../src/drivers/driver_common.o +OBJS_priv += ../src/drivers/driver_common.o + +OBJS += wpa_supplicant.o events.o bssid_ignore.o wpas_glue.o scan.o +OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.o +OBJS_t += ../src/radius/radius_client.o +OBJS_t += ../src/radius/radius.o +OBJS_t2 := $(OBJS) $(OBJS_l2) preauth_test.o + +OBJS_nfc := $(OBJS) $(OBJS_l2) nfc_pw_token.o +OBJS_nfc += $(OBJS_d) ../src/drivers/drivers.o + +OBJS += $(CONFIG_MAIN).o + +ifdef CONFIG_PRIVSEP +OBJS_priv += $(OBJS_d) ../src/drivers/drivers.o +OBJS_priv += $(OBJS_l2) +OBJS_priv += ../src/utils/os_$(CONFIG_OS).o +OBJS_priv += ../src/utils/$(CONFIG_ELOOP).o +OBJS_priv += ../src/utils/common.o +OBJS_priv += ../src/utils/wpa_debug.o +OBJS_priv += ../src/utils/wpabuf.o +OBJS_priv += wpa_priv.o +ifdef CONFIG_DRIVER_NL80211 +OBJS_priv += ../src/common/ieee802_11_common.o +endif +OBJS += ../src/l2_packet/l2_packet_privsep.o +OBJS += ../src/drivers/driver_privsep.o +EXTRA_progs += wpa_priv +else +OBJS += $(OBJS_d) ../src/drivers/drivers.o +OBJS += $(OBJS_l2) +endif + +ifdef CONFIG_NDIS_EVENTS_INTEGRATED +CFLAGS += -DCONFIG_NDIS_EVENTS_INTEGRATED +OBJS += ../src/drivers/ndis_events.o +EXTRALIBS += -loleaut32 -lole32 -luuid +ifdef PLATFORMSDKLIB +EXTRALIBS += $(PLATFORMSDKLIB)/WbemUuid.Lib +else +EXTRALIBS += WbemUuid.Lib +endif +endif + +ifdef CONFIG_FST +CFLAGS += -DCONFIG_FST +ifdef CONFIG_FST_TEST +CFLAGS += -DCONFIG_FST_TEST +endif +FST_OBJS += ../src/fst/fst.o +FST_OBJS += ../src/fst/fst_session.o +FST_OBJS += ../src/fst/fst_iface.o +FST_OBJS += ../src/fst/fst_group.o +FST_OBJS += ../src/fst/fst_ctrl_aux.o +ifdef CONFIG_CTRL_IFACE +FST_OBJS += ../src/fst/fst_ctrl_iface.o +endif +OBJS += $(FST_OBJS) +OBJS_t += $(FST_OBJS) +OBJS_t2 += $(FST_OBJS) +OBJS_nfc += $(FST_OBJS) +endif + +ifdef CONFIG_WEP +CFLAGS += -DCONFIG_WEP +endif + +ifdef CONFIG_NO_TKIP +CFLAGS += -DCONFIG_NO_TKIP +endif + +dynamic_eap_methods: $(EAPDYN) + +_OBJS_VAR := OBJS_priv +include ../src/objs.mk +wpa_priv: $(BCHECK) $(OBJS_priv) + $(Q)$(LDO) $(LDFLAGS) -o wpa_priv $(OBJS_priv) $(LIBS) + @$(E) " LD " $@ + +_OBJS_VAR := OBJS +include ../src/objs.mk +wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) + $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) + @$(E) " LD " $@ + +_OBJS_VAR := OBJS_t +include ../src/objs.mk +eapol_test: $(OBJS_t) + $(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS) + @$(E) " LD " $@ + +_OBJS_VAR := OBJS_t2 +include ../src/objs.mk +preauth_test: $(OBJS_t2) + $(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS) + @$(E) " LD " $@ + +_OBJS_VAR := OBJS_p +include ../src/objs.mk +wpa_passphrase: $(OBJS_p) + $(Q)$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) $(LIBS) + @$(E) " LD " $@ + +_OBJS_VAR := OBJS_c +include ../src/objs.mk +wpa_cli: $(OBJS_c) + $(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c) + @$(E) " LD " $@ + +LIBCTRL += ../src/common/wpa_ctrl.o +LIBCTRL += ../src/utils/os_$(CONFIG_OS).o +LIBCTRL += ../src/utils/common.o +LIBCTRL += ../src/utils/wpa_debug.o +LIBCTRLSO += ../src/common/wpa_ctrl.c +LIBCTRLSO += ../src/utils/os_$(CONFIG_OS).c +LIBCTRLSO += ../src/utils/common.c +LIBCTRLSO += ../src/utils/wpa_debug.c + +_OBJS_VAR := LIBCTRL +include ../src/objs.mk +libwpa_client.a: $(LIBCTRL) + $(Q)rm -f $@ + $(Q)$(AR) crs $@ $? + @$(E) " AR " $@ + +libwpa_client.so: $(LIBCTRLSO) + @$(E) " CC $@ ($^)" + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -fPIC $^ + +OBJS_wpatest := libwpa_test.o +_OBJS_VAR := OBJS_wpatest +include ../src/objs.mk +libwpa_test1: $(OBJS_wpatest) libwpa_client.a + $(Q)$(LDO) $(LDFLAGS) -o libwpa_test1 $(OBJS_wpatest) libwpa_client.a $(LIBS_c) + @$(E) " LD " $@ + +libwpa_test2: $(OBJS_wpatest) libwpa_client.so + $(Q)$(LDO) $(LDFLAGS) -o libwpa_test2 $(OBJS_wpatest) -L. -lwpa_client $(LIBS_c) + @$(E) " LD " $@ + +_OBJS_VAR := OBJS_nfc +include ../src/objs.mk +nfc_pw_token: $(OBJS_nfc) + $(Q)$(LDO) $(LDFLAGS) -o nfc_pw_token $(OBJS_nfc) $(LIBS) + @$(E) " LD " $@ + +win_if_list: win_if_list.c + $(Q)$(LDO) $(LDFLAGS) -o $@ win_if_list.c $(CFLAGS) $(LIBS_w) + @$(E) " LD " $@ + +eap_psk.so: $(SRC_EAP_PSK) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -Deap_peer_psk_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_pax.so: $(SRC_EAP_PAX) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_peap.so: $(SRC_EAP_PEAP) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_sake.so: $(SRC_EAP_SAKE) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_ikev2.so: $(SRC_EAP_IKEV2) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_eke.so: $(SRC_EAP_EKE) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_mschapv2.so: $(SRC_EAP_MSCHAPV2) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_fast.so: $(SRC_EAP_FAST) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_teap.so: $(SRC_EAP_TEAP) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +eap_gpsk.so: $(SRC_EAP_GPSK) + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ + -D$(@F:eap_%.so=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +%.so: ../src/eap_peer/%.c + $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \ + -D$(*F:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init + @$(E) " CC/LD " $@ + +%.service: %.service.in + $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ + @$(E) " sed" $< + +%@.service: %.service.arg.in + $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ + @$(E) " sed" $< + +wpa_supplicant.exe: wpa_supplicant + mv -f $< $@ +wpa_cli.exe: wpa_cli + mv -f $< $@ +wpa_passphrase.exe: wpa_passphrase + mv -f $< $@ +win_if_list.exe: win_if_list + mv -f $< $@ +eapol_test.exe: eapol_test + mv -f $< $@ + +WINALL=wpa_supplicant.exe wpa_cli.exe wpa_passphrase.exe win_if_list.exe + +windows-bin: $(WINALL) + $(STRIP) $(WINALL) + +wpa_gui: + @echo "wpa_gui has been removed - see wpa_gui-qt4 for replacement" + +wpa_gui-qt4/Makefile: + qmake -o wpa_gui-qt4/Makefile wpa_gui-qt4/wpa_gui.pro + +wpa_gui-qt4/lang/wpa_gui_de.qm: wpa_gui-qt4/lang/wpa_gui_de.ts + lrelease wpa_gui-qt4/wpa_gui.pro + +wpa_gui-qt4: wpa_gui-qt4/Makefile wpa_gui-qt4/lang/wpa_gui_de.qm + $(MAKE) -C wpa_gui-qt4 + +FIPSDIR=/usr/local/ssl/fips-2.0 +FIPSLD=$(FIPSDIR)/bin/fipsld +fips: + $(MAKE) CC=$(FIPSLD) FIPSLD_CC="$(CC)" + +.PHONY: lcov-html +lcov-html: $(call BUILDOBJ,wpa_supplicant.gcda) + lcov -c -d $(BUILDDIR) > lcov.info + genhtml lcov.info --output-directory lcov-html + +clean: common-clean + $(MAKE) -C ../src clean + $(MAKE) -C dbus clean + rm -f core *~ *.o *.d *.gcno *.gcda *.gcov + rm -f eap_*.so $(WINALL) eapol_test preauth_test + rm -f wpa_priv + rm -f nfc_pw_token + rm -f lcov.info + rm -rf lcov-html + rm -f libwpa_client.a + rm -f libwpa_client.so + rm -f libwpa_test1 libwpa_test2 diff --git a/wpa_supplicant/README b/wpa_supplicant/README new file mode 100644 index 000000000000..c643b2684700 --- /dev/null +++ b/wpa_supplicant/README @@ -0,0 +1,1163 @@ +wpa_supplicant +============== + +Copyright (c) 2003-2022, Jouni Malinen and contributors +All Rights Reserved. + +This program is licensed under the BSD license (the one with +advertisement clause removed). + +If you are submitting changes to the project, please see CONTRIBUTIONS +file for more instructions. + + + +License +------- + +This software may be distributed, used, and modified under the terms of +BSD license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name(s) of the above-listed copyright holder(s) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +Features +-------- + +Supported WPA/IEEE 802.11i features: +- WPA-PSK ("WPA-Personal") +- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise") + Following authentication methods are supported with an integrate IEEE 802.1X + Supplicant: + * EAP-TLS + * EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1) + * EAP-PEAP/TLS (both PEAPv0 and PEAPv1) + * EAP-PEAP/GTC (both PEAPv0 and PEAPv1) + * EAP-PEAP/OTP (both PEAPv0 and PEAPv1) + * EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1) + * EAP-TTLS/EAP-MD5-Challenge + * EAP-TTLS/EAP-GTC + * EAP-TTLS/EAP-OTP + * EAP-TTLS/EAP-MSCHAPv2 + * EAP-TTLS/EAP-TLS + * EAP-TTLS/MSCHAPv2 + * EAP-TTLS/MSCHAP + * EAP-TTLS/PAP + * EAP-TTLS/CHAP + * EAP-SIM + * EAP-AKA + * EAP-AKA' + * EAP-PSK + * EAP-PAX + * EAP-SAKE + * EAP-IKEv2 + * EAP-GPSK + * EAP-pwd + * LEAP (note: requires special support from the driver for IEEE 802.11 + authentication) + (following methods are supported, but since they do not generate keying + material, they cannot be used with WPA or IEEE 802.1X WEP keying) + * EAP-MD5-Challenge + * EAP-MSCHAPv2 + * EAP-GTC + * EAP-OTP +- key management for CCMP, TKIP, WEP104, WEP40 +- RSN/WPA2 (IEEE 802.11i) + * pre-authentication + * PMKSA caching + +Supported TLS/crypto libraries: +- OpenSSL (default) +- GnuTLS + +Internal TLS/crypto implementation (optional): +- can be used in place of an external TLS/crypto library +- TLSv1 +- X.509 certificate processing +- PKCS #1 +- ASN.1 +- RSA +- bignum +- minimal size (ca. 50 kB binary, parts of which are already needed for WPA; + TLSv1/X.509/ASN.1/RSA/bignum parts are about 25 kB on x86) + + +Requirements +------------ + +Current hardware/software requirements: +- Linux kernel 2.4.x or 2.6.x with Linux Wireless Extensions v15 or newer +- FreeBSD 6-CURRENT +- NetBSD-current +- Microsoft Windows with WinPcap (at least WinXP, may work with other versions) +- drivers: + Linux drivers that support cfg80211/nl80211. Even though there are + number of driver specific interface included in wpa_supplicant, please + note that Linux drivers are moving to use generic wireless configuration + interface driver_nl80211 (-Dnl80211 on wpa_supplicant command line) + should be the default option to start with before falling back to driver + specific interface. + + Linux drivers that support WPA/WPA2 configuration with the generic + Linux wireless extensions (WE-18 or newer). Obsoleted by nl80211. + + In theory, any driver that supports Linux wireless extensions can be + used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in + configuration file. + + Wired Ethernet drivers (with ap_scan=0) + + BSD net80211 layer (e.g., Atheros driver) + At the moment, this is for FreeBSD 6-CURRENT branch and NetBSD-current. + + Windows NDIS + The current Windows port requires WinPcap (http://winpcap.polito.it/). + See README-Windows.txt for more information. + +wpa_supplicant was designed to be portable for different drivers and +operating systems. Hopefully, support for more wlan cards and OSes will be +added in the future. See developer's documentation +(http://hostap.epitest.fi/wpa_supplicant/devel/) for more information about the +design of wpa_supplicant and porting to other drivers. One main goal +is to add full WPA/WPA2 support to Linux wireless extensions to allow +new drivers to be supported without having to implement new +driver-specific interface code in wpa_supplicant. + +Optional libraries for layer2 packet processing: +- libpcap (tested with 0.7.2, most relatively recent versions assumed to work, + this is likely to be available with most distributions, + http://tcpdump.org/) +- libdnet (tested with v1.4, most versions assumed to work, + http://libdnet.sourceforge.net/) + +These libraries are _not_ used in the default Linux build. Instead, +internal Linux specific implementation is used. libpcap/libdnet are +more portable and they can be used by adding CONFIG_L2_PACKET=pcap into +.config. They may also be selected automatically for other operating +systems. In case of Windows builds, WinPcap is used by default +(CONFIG_L2_PACKET=winpcap). + + +Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS: +- OpenSSL (tested with 1.0.1 and 1.0.2 versions; assumed to + work with most relatively recent versions; this is likely to be + available with most distributions, http://www.openssl.org/) +- GnuTLS +- internal TLSv1 implementation + +One of these libraries is needed when EAP-TLS, EAP-PEAP, EAP-TTLS, or +EAP-FAST support is enabled. WPA-PSK mode does not require this or EAPOL/EAP +implementation. A configuration file, .config, for compilation is +needed to enable IEEE 802.1X/EAPOL and EAP methods. Note that EAP-MD5, +EAP-GTC, EAP-OTP, and EAP-MSCHAPV2 cannot be used alone with WPA, so +they should only be enabled if testing the EAPOL/EAP state +machines. However, there can be used as inner authentication +algorithms with EAP-PEAP and EAP-TTLS. + +See Building and installing section below for more detailed +information about the wpa_supplicant build time configuration. + + + +WPA +--- + +The original security mechanism of IEEE 802.11 standard was not +designed to be strong and has proven to be insufficient for most +networks that require some kind of security. Task group I (Security) +of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked +to address the flaws of the base standard and has in practice +completed its work in May 2004. The IEEE 802.11i amendment to the IEEE +802.11 standard was approved in June 2004 and published in July 2004. + +Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the +IEEE 802.11i work (draft 3.0) to define a subset of the security +enhancements that can be implemented with existing wlan hardware. This +is called Wi-Fi Protected Access (WPA). This has now become a +mandatory component of interoperability testing and certification done +by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web +site (http://www.wi-fi.org/OpenSection/protected_access.asp). + +IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm +for protecting wireless networks. WEP uses RC4 with 40-bit keys, +24-bit initialization vector (IV), and CRC32 to protect against packet +forgery. All these choices have proven to be insufficient: key space is +too small against current attacks, RC4 key scheduling is insufficient +(beginning of the pseudorandom stream should be skipped), IV space is +too small and IV reuse makes attacks easier, there is no replay +protection, and non-keyed authentication does not protect against bit +flipping packet data. + +WPA is an intermediate solution for the security issues. It uses +Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a +compromise on strong security and possibility to use existing +hardware. It still uses RC4 for the encryption like WEP, but with +per-packet RC4 keys. In addition, it implements replay protection, +keyed packet authentication mechanism (Michael MIC). + +Keys can be managed using two different mechanisms. WPA can either use +an external authentication server (e.g., RADIUS) and EAP just like +IEEE 802.1X is using or pre-shared keys without need for additional +servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal", +respectively. Both mechanisms will generate a master session key for +the Authenticator (AP) and Supplicant (client station). + +WPA implements a new key handshake (4-Way Handshake and Group Key +Handshake) for generating and exchanging data encryption keys between +the Authenticator and Supplicant. This handshake is also used to +verify that both Authenticator and Supplicant know the master session +key. These handshakes are identical regardless of the selected key +management mechanism (only the method for generating master session +key changes). + + + +IEEE 802.11i / WPA2 +------------------- + +The design for parts of IEEE 802.11i that were not included in WPA has +finished (May 2004) and this amendment to IEEE 802.11 was approved in +June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new +version of WPA called WPA2. This includes, e.g., support for more +robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC) +to replace TKIP and optimizations for handoff (reduced number of +messages in initial key handshake, pre-authentication, and PMKSA caching). + + + +wpa_supplicant +-------------- + +wpa_supplicant is an implementation of the WPA Supplicant component, +i.e., the part that runs in the client stations. It implements WPA key +negotiation with a WPA Authenticator and EAP authentication with +Authentication Server. In addition, it controls the roaming and IEEE +802.11 authentication/association of the wlan driver. + +wpa_supplicant is designed to be a "daemon" program that runs in the +background and acts as the backend component controlling the wireless +connection. wpa_supplicant supports separate frontend programs and an +example text-based frontend, wpa_cli, is included with wpa_supplicant. + +Following steps are used when associating with an AP using WPA: + +- wpa_supplicant requests the kernel driver to scan neighboring BSSes +- wpa_supplicant selects a BSS based on its configuration +- wpa_supplicant requests the kernel driver to associate with the chosen + BSS +- If WPA-EAP: integrated IEEE 802.1X Supplicant completes EAP + authentication with the authentication server (proxied by the + Authenticator in the AP) +- If WPA-EAP: master key is received from the IEEE 802.1X Supplicant +- If WPA-PSK: wpa_supplicant uses PSK as the master session key +- wpa_supplicant completes WPA 4-Way Handshake and Group Key Handshake + with the Authenticator (AP) +- wpa_supplicant configures encryption keys for unicast and broadcast +- normal data packets can be transmitted and received + + + +Building and installing +----------------------- + +In order to be able to build wpa_supplicant, you will first need to +select which parts of it will be included. This is done by creating a +build time configuration file, .config, in the wpa_supplicant root +directory. Configuration options are text lines using following +format: CONFIG_